LCOV - code coverage report
Current view: top level - providers/ldap - sdap_dyndns.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 380 0.0 %
Date: 2016-06-29 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /*
       2             :     SSSD
       3             : 
       4             :     sdap_dyndns.c: LDAP specific dynamic DNS update
       5             : 
       6             :     Authors:
       7             :         Jakub Hrozek <jhrozek@redhat.com>
       8             : 
       9             :     Copyright (C) 2013 Red Hat
      10             : 
      11             :     This program is free software; you can redistribute it and/or modify
      12             :     it under the terms of the GNU General Public License as published by
      13             :     the Free Software Foundation; either version 3 of the License, or
      14             :     (at your option) any later version.
      15             : 
      16             :     This program is distributed in the hope that it will be useful,
      17             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :     GNU General Public License for more details.
      20             : 
      21             :     You should have received a copy of the GNU General Public License
      22             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "util/util.h"
      26             : #include "resolv/async_resolv.h"
      27             : #include "providers/backend.h"
      28             : #include "providers/be_dyndns.h"
      29             : #include "providers/ldap/sdap_async_private.h"
      30             : #include "providers/ldap/sdap_dyndns.h"
      31             : #include "providers/ldap/sdap_id_op.h"
      32             : #include "providers/ldap/ldap_common.h"
      33             : 
      34             : static struct tevent_req *
      35             : sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx,
      36             :                            struct tevent_context *ev,
      37             :                            struct sdap_id_ctx *sdap_ctx,
      38             :                            const char *iface);
      39             : static errno_t
      40             : sdap_dyndns_get_addrs_recv(struct tevent_req *req,
      41             :                            TALLOC_CTX *mem_ctx,
      42             :                            struct sss_iface_addr **_addresses);
      43             : 
      44             : struct sdap_dyndns_update_state {
      45             :     struct tevent_context *ev;
      46             :     struct be_resolv_ctx *be_res;
      47             :     struct dp_option *opts;
      48             : 
      49             :     const char *hostname;
      50             :     const char *realm;
      51             :     const char *servername;
      52             :     int ttl;
      53             : 
      54             :     struct sss_iface_addr *addresses;
      55             :     struct sss_iface_addr *dns_addrlist;
      56             :     uint8_t remove_af;
      57             : 
      58             :     bool update_ptr;
      59             :     bool check_diff;
      60             :     enum be_nsupdate_auth auth_type;
      61             :     bool fallback_mode;
      62             :     char *update_msg;
      63             :     struct sss_iface_addr *ptr_addr_iter;
      64             :     bool del_phase;
      65             : };
      66             : 
      67             : static void sdap_dyndns_update_addrs_done(struct tevent_req *subreq);
      68             : static void sdap_dyndns_dns_addrs_done(struct tevent_req *subreq);
      69             : static errno_t sdap_dyndns_addrs_diff(struct sdap_dyndns_update_state *state,
      70             :                                       bool *_do_update);
      71             : static errno_t sdap_dyndns_update_step(struct tevent_req *req);
      72             : static errno_t sdap_dyndns_update_ptr_step(struct tevent_req *req);
      73             : static void sdap_dyndns_update_done(struct tevent_req *subreq);
      74             : static void sdap_dyndns_update_ptr_done(struct tevent_req *subreq);
      75             : static errno_t
      76             : sdap_dyndns_next_ptr_record(struct sdap_dyndns_update_state *state,
      77             :                             struct tevent_req *req);
      78             : static struct sss_iface_addr*
      79             : sdap_get_address_to_delete(struct sss_iface_addr *address_it,
      80             :                            uint8_t remove_af);
      81             : 
      82             : struct tevent_req *
      83           0 : sdap_dyndns_update_send(TALLOC_CTX *mem_ctx,
      84             :                         struct tevent_context *ev,
      85             :                         struct be_ctx *be_ctx,
      86             :                         struct dp_option *opts,
      87             :                         struct sdap_id_ctx *sdap_ctx,
      88             :                         enum be_nsupdate_auth auth_type,
      89             :                         const char *ifname,
      90             :                         const char *hostname,
      91             :                         const char *realm,
      92             :                         const int ttl,
      93             :                         bool check_diff)
      94             : {
      95             :     errno_t ret;
      96             :     struct tevent_req *req;
      97             :     struct tevent_req *subreq;
      98             :     struct sdap_dyndns_update_state *state;
      99             :     const char *conf_servername;
     100             : 
     101           0 :     req = tevent_req_create(mem_ctx, &state, struct sdap_dyndns_update_state);
     102           0 :     if (req == NULL) {
     103           0 :         return NULL;
     104             :     }
     105           0 :     state->check_diff = check_diff;
     106           0 :     state->update_ptr = dp_opt_get_bool(opts, DP_OPT_DYNDNS_UPDATE_PTR);
     107           0 :     state->hostname = hostname;
     108           0 :     state->realm = realm;
     109           0 :     state->servername = NULL;
     110           0 :     state->fallback_mode = false;
     111           0 :     state->ttl = ttl;
     112           0 :     state->be_res = be_ctx->be_res;
     113           0 :     state->ev = ev;
     114           0 :     state->opts = opts;
     115           0 :     state->auth_type = auth_type;
     116           0 :     state->ptr_addr_iter = NULL;
     117           0 :     state->del_phase = true;
     118             : 
     119             :     /* fallback servername is overriden by user option */
     120           0 :     conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER);
     121           0 :     if (conf_servername != NULL) {
     122           0 :         state->servername = conf_servername;
     123             :     }
     124             : 
     125           0 :     if (ifname) {
     126             :        /* Unless one family is restricted, just replace all
     127             :         * address families during the update
     128             :         */
     129           0 :         switch (state->be_res->family_order) {
     130             :         case IPV4_ONLY:
     131           0 :             state->remove_af |= DYNDNS_REMOVE_A;
     132           0 :             break;
     133             :         case IPV6_ONLY:
     134           0 :             state->remove_af |= DYNDNS_REMOVE_AAAA;
     135           0 :             break;
     136             :         case IPV4_FIRST:
     137             :         case IPV6_FIRST:
     138           0 :             state->remove_af |= (DYNDNS_REMOVE_A |
     139             :                                  DYNDNS_REMOVE_AAAA);
     140           0 :             break;
     141             :         }
     142             :     } else {
     143             :         /* If the interface isn't specified, we ONLY want to have the address
     144             :          * that's connected to the LDAP server stored, so we need to check
     145             :          * (and later remove) both address families.
     146             :          */
     147           0 :         state->remove_af = (DYNDNS_REMOVE_A | DYNDNS_REMOVE_AAAA);
     148             :     }
     149             : 
     150           0 :     subreq = sdap_dyndns_get_addrs_send(state, state->ev, sdap_ctx, ifname);
     151           0 :     if (!subreq) {
     152           0 :         ret = EIO;
     153           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n",
     154             :               ret, sss_strerror(ret));
     155           0 :         goto done;
     156             :     }
     157           0 :     tevent_req_set_callback(subreq, sdap_dyndns_update_addrs_done, req);
     158             : 
     159           0 :     ret = EOK;
     160             : done:
     161           0 :     if (ret != EOK) {
     162           0 :         tevent_req_error(req, ret);
     163           0 :         tevent_req_post(req, ev);
     164             :     }
     165           0 :     return req;
     166             : }
     167             : 
     168             : static void
     169           0 : sdap_dyndns_update_addrs_done(struct tevent_req *subreq)
     170             : {
     171             :     errno_t ret;
     172             :     struct tevent_req *req;
     173             :     struct sdap_dyndns_update_state *state;
     174             : 
     175           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     176           0 :     state = tevent_req_data(req, struct sdap_dyndns_update_state);
     177             : 
     178           0 :     ret = sdap_dyndns_get_addrs_recv(subreq, state, &state->addresses);
     179           0 :     talloc_zfree(subreq);
     180           0 :     if (ret != EOK) {
     181           0 :         DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses for DNS update\n");
     182           0 :         tevent_req_error(req, ret);
     183           0 :         return;
     184             :     }
     185             : 
     186           0 :     if (state->check_diff || state->update_ptr) {
     187             :         /* Check if we need the update at all. In case we are updating the PTR
     188             :          * records as well, we need to know the old addresses to be able to
     189             :          * reliably delete the PTR records */
     190           0 :         subreq = nsupdate_get_addrs_send(state, state->ev,
     191             :                                          state->be_res, state->hostname);
     192           0 :         if (subreq == NULL) {
     193           0 :             DEBUG(SSSDBG_OP_FAILURE, "Can't initiate address check\n");
     194           0 :             tevent_req_error(req, ret);
     195           0 :             return;
     196             :         }
     197           0 :         tevent_req_set_callback(subreq, sdap_dyndns_dns_addrs_done, req);
     198           0 :         return;
     199             :     }
     200             : 
     201             :     /* Perform update */
     202           0 :     ret = sdap_dyndns_update_step(req);
     203           0 :     if (ret != EOK) {
     204           0 :         tevent_req_error(req, ret);
     205           0 :         return;
     206             :     }
     207             :     /* Execution will resume in sdap_dyndns_update_done */
     208             : }
     209             : 
     210             : static void
     211           0 : sdap_dyndns_dns_addrs_done(struct tevent_req *subreq)
     212             : {
     213             :     struct tevent_req *req;
     214             :     struct sdap_dyndns_update_state *state;
     215             :     errno_t ret;
     216             :     bool do_update;
     217             : 
     218           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     219           0 :     state = tevent_req_data(req, struct sdap_dyndns_update_state);
     220             : 
     221           0 :     ret = nsupdate_get_addrs_recv(subreq, state, &state->dns_addrlist, NULL);
     222           0 :     talloc_zfree(subreq);
     223           0 :     if (ret != EOK) {
     224           0 :         DEBUG(SSSDBG_OP_FAILURE,
     225             :               "Could not receive list of current addresses [%d]: %s\n",
     226             :               ret, sss_strerror(ret));
     227           0 :         tevent_req_error(req, ret);
     228           0 :         return;
     229             :     }
     230             : 
     231           0 :     if (state->check_diff) {
     232           0 :         ret = sdap_dyndns_addrs_diff(state, &do_update);
     233           0 :         if (ret != EOK) {
     234           0 :             DEBUG(SSSDBG_OP_FAILURE, "Could not check the diff between DNS "
     235             :                   "and current addresses [%d]: %s\n", ret, strerror(ret));
     236           0 :             tevent_req_error(req, ret);
     237           0 :             return;
     238             :         }
     239             : 
     240           0 :         if (do_update == false) {
     241           0 :             DEBUG(SSSDBG_TRACE_FUNC,
     242             :                   "No DNS update needed, addresses did not change\n");
     243           0 :             tevent_req_done(req);
     244           0 :             return;
     245             :         }
     246           0 :         DEBUG(SSSDBG_TRACE_FUNC,
     247             :               "Detected IP addresses change, will perform an update\n");
     248             :     }
     249             : 
     250             :     /* Either we needed the addresses for updating PTR records only or
     251             :      * the addresses have changed (or both) */
     252           0 :     ret = sdap_dyndns_update_step(req);
     253           0 :     if (ret != EOK) {
     254           0 :         DEBUG(SSSDBG_OP_FAILURE, "Could not start the update [%d]: %s\n",
     255             :               ret, sss_strerror(ret));
     256           0 :         tevent_req_error(req, ret);
     257             :     }
     258           0 :     return;
     259             : }
     260             : 
     261             : static errno_t
     262           0 : sdap_dyndns_addrs_diff(struct sdap_dyndns_update_state *state, bool *_do_update)
     263             : {
     264             :     errno_t ret;
     265             :     int i;
     266           0 :     char **str_dnslist = NULL, **str_local_list = NULL;
     267           0 :     char **dns_only = NULL, **local_only = NULL;
     268           0 :     bool do_update = false;
     269             : 
     270           0 :     ret = sss_iface_addr_list_as_str_list(state,
     271             :                                           state->dns_addrlist, &str_dnslist);
     272           0 :     if (ret != EOK) {
     273           0 :         DEBUG(SSSDBG_OP_FAILURE,
     274             :                "Converting DNS IP addresses to strings failed: [%d]: %s\n",
     275             :                ret, sss_strerror(ret));
     276           0 :         return ret;
     277             :     }
     278             : 
     279           0 :     ret = sss_iface_addr_list_as_str_list(state,
     280             :                                           state->addresses, &str_local_list);
     281           0 :     if (ret != EOK) {
     282           0 :         DEBUG(SSSDBG_OP_FAILURE,
     283             :                "Converting local IP addresses to strings failed: [%d]: %s\n",
     284             :                ret, sss_strerror(ret));
     285           0 :         return ret;
     286             :     }
     287             : 
     288             :     /* Compare the lists */
     289           0 :     ret = diff_string_lists(state, str_dnslist, str_local_list,
     290             :                             &dns_only, &local_only, NULL);
     291           0 :     if (ret != EOK) {
     292           0 :         DEBUG(SSSDBG_OP_FAILURE,
     293             :               "diff_string_lists failed: [%d]: %s\n", ret, sss_strerror(ret));
     294           0 :         return ret;
     295             :     }
     296             : 
     297           0 :     if (dns_only) {
     298           0 :         for (i=0; dns_only[i]; i++) {
     299           0 :             DEBUG(SSSDBG_TRACE_LIBS,
     300             :                   "Address in DNS only: %s\n", dns_only[i]);
     301           0 :             do_update = true;
     302             :         }
     303             :     }
     304             : 
     305           0 :     if (local_only) {
     306           0 :         for (i=0; local_only[i]; i++) {
     307           0 :             DEBUG(SSSDBG_TRACE_LIBS,
     308             :                   "Address on localhost only: %s\n", local_only[i]);
     309           0 :             do_update = true;
     310             :         }
     311             :     }
     312             : 
     313           0 :     *_do_update = do_update;
     314           0 :     return EOK;
     315             : }
     316             : 
     317             : static errno_t
     318           0 : sdap_dyndns_update_step(struct tevent_req *req)
     319             : {
     320             :     errno_t ret;
     321             :     struct sdap_dyndns_update_state *state;
     322             :     const char *servername;
     323             :     const char *realm;
     324             :     struct tevent_req *subreq;
     325             : 
     326           0 :     state = tevent_req_data(req, struct sdap_dyndns_update_state);
     327             : 
     328           0 :     servername = NULL;
     329           0 :     realm = NULL;
     330           0 :     if (state->fallback_mode) {
     331           0 :         servername = state->servername;
     332           0 :         realm = state->realm;
     333             :     }
     334             : 
     335           0 :     ret = be_nsupdate_create_fwd_msg(state, realm, servername,
     336             :                                      state->hostname,
     337           0 :                                      state->ttl, state->remove_af,
     338             :                                      state->addresses,
     339             :                                      &state->update_msg);
     340           0 :     if (ret != EOK) {
     341           0 :         DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses for DNS update\n");
     342           0 :         return ret;
     343             :     }
     344             : 
     345             :     /* Fork a child process to perform the DNS update */
     346           0 :     subreq = be_nsupdate_send(state, state->ev, state->auth_type,
     347             :                               state->update_msg,
     348           0 :                               dp_opt_get_bool(state->opts,
     349             :                                               DP_OPT_DYNDNS_FORCE_TCP));
     350           0 :     if (subreq == NULL) {
     351           0 :         return EIO;
     352             :     }
     353             : 
     354           0 :     tevent_req_set_callback(subreq, sdap_dyndns_update_done, req);
     355           0 :     return EOK;
     356             : }
     357             : 
     358             : static void
     359           0 : sdap_dyndns_update_done(struct tevent_req *subreq)
     360             : {
     361             :     errno_t ret;
     362             :     int child_status;
     363             :     struct tevent_req *req;
     364             :     struct sdap_dyndns_update_state *state;
     365             : 
     366           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     367           0 :     state = tevent_req_data(req, struct sdap_dyndns_update_state);
     368             : 
     369           0 :     ret = be_nsupdate_recv(subreq, &child_status);
     370           0 :     talloc_zfree(subreq);
     371           0 :     if (ret != EOK) {
     372             :         /* If the update didn't succeed, we can retry using the server name */
     373           0 :         if (state->fallback_mode == false
     374           0 :                 && WIFEXITED(child_status)
     375           0 :                 && WEXITSTATUS(child_status) != 0) {
     376           0 :             state->fallback_mode = true;
     377           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     378             :                   "nsupdate failed, retrying.\n");
     379           0 :             ret = sdap_dyndns_update_step(req);
     380           0 :             if (ret == EOK) {
     381           0 :                 return;
     382             :             }
     383             :         }
     384             : 
     385           0 :         tevent_req_error(req, ret);
     386           0 :         return;
     387             :     }
     388             : 
     389           0 :     if (state->update_ptr == false) {
     390           0 :         DEBUG(SSSDBG_TRACE_FUNC, "No PTR update requested, done\n");
     391           0 :         tevent_req_done(req);
     392           0 :         return;
     393             :     }
     394             : 
     395           0 :     talloc_free(state->update_msg);
     396             : 
     397             :     /* init iterator for addresses to be deleted */
     398           0 :     state->ptr_addr_iter = sdap_get_address_to_delete(state->dns_addrlist,
     399           0 :                                                       state->remove_af);
     400           0 :     if (state->ptr_addr_iter == NULL) {
     401             :         /* init iterator for addresses to be added */
     402           0 :         state->del_phase = false;
     403           0 :         state->ptr_addr_iter = state->addresses;
     404             :     }
     405             : 
     406           0 :     ret = sdap_dyndns_update_ptr_step(req);
     407           0 :     if (ret != EOK) {
     408           0 :         tevent_req_error(req, ret);
     409           0 :         return;
     410             :     }
     411             :     /* Execution will resume in sdap_dyndns_update_ptr_done */
     412             : }
     413             : 
     414             : 
     415           0 : static bool remove_addr(int address_family, uint8_t remove_af)
     416             : {
     417           0 :     bool ret = false;
     418             : 
     419           0 :     switch(address_family) {
     420             :     case AF_INET:
     421           0 :         if (remove_af & DYNDNS_REMOVE_A) {
     422           0 :             ret = true;
     423             :         }
     424           0 :         break;
     425             :     case AF_INET6:
     426           0 :         if (remove_af & DYNDNS_REMOVE_AAAA) {
     427           0 :             ret = true;
     428             :         }
     429           0 :         break;
     430             :     default:
     431           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n");
     432           0 :         ret = false;
     433             :     }
     434             : 
     435           0 :     return ret;
     436             : }
     437             : 
     438             : static struct sss_iface_addr*
     439           0 : sdap_get_address_to_delete(struct sss_iface_addr *address_it,
     440             :                            uint8_t remove_af)
     441             : {
     442             :     struct sockaddr_storage* address;
     443             : 
     444           0 :     while (address_it != NULL) {
     445           0 :         address = sss_iface_addr_get_address(address_it);
     446             : 
     447             :         /* skip addresses that are not to be deleted */
     448           0 :         if (remove_addr(address->ss_family, remove_af)) {
     449           0 :             break;
     450             :         }
     451             : 
     452           0 :         address_it = sss_iface_addr_get_next(address_it);
     453             :     }
     454             : 
     455           0 :     return address_it;
     456             : }
     457             : 
     458             : static errno_t
     459           0 : sdap_dyndns_update_ptr_step(struct tevent_req *req)
     460             : {
     461             :     errno_t ret;
     462             :     struct sdap_dyndns_update_state *state;
     463             :     const char *servername;
     464             :     const char *realm;
     465             :     struct tevent_req *subreq;
     466             :     struct sockaddr_storage *address;
     467             : 
     468           0 :     state = tevent_req_data(req, struct sdap_dyndns_update_state);
     469             : 
     470           0 :     servername = NULL;
     471           0 :     realm = NULL;
     472           0 :     if (state->fallback_mode == true) {
     473           0 :         servername = state->servername;
     474           0 :         realm = state->realm;
     475             :     }
     476             : 
     477           0 :     address = sss_iface_addr_get_address(state->ptr_addr_iter);
     478           0 :     if (address == NULL) {
     479           0 :         return EIO;
     480             :     }
     481             : 
     482           0 :     ret = be_nsupdate_create_ptr_msg(state, realm, servername, state->hostname,
     483           0 :                                      state->ttl, address, state->del_phase,
     484             :                                      &state->update_msg);
     485             : 
     486           0 :     if (ret != EOK) {
     487           0 :         DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses for DNS update\n");
     488           0 :         return ret;
     489             :     }
     490             : 
     491             :     /* Fork a child process to perform the DNS update */
     492           0 :     subreq = be_nsupdate_send(state, state->ev, state->auth_type,
     493             :                               state->update_msg,
     494           0 :                               dp_opt_get_bool(state->opts,
     495             :                                               DP_OPT_DYNDNS_FORCE_TCP));
     496           0 :     if (subreq == NULL) {
     497           0 :         return EIO;
     498             :     }
     499             : 
     500           0 :     tevent_req_set_callback(subreq, sdap_dyndns_update_ptr_done, req);
     501           0 :     return EOK;
     502             : }
     503             : 
     504             : static void
     505           0 : sdap_dyndns_update_ptr_done(struct tevent_req *subreq)
     506             : {
     507             :     errno_t ret;
     508             :     int child_status;
     509             :     struct tevent_req *req;
     510             :     struct sdap_dyndns_update_state *state;
     511             : 
     512           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     513           0 :     state = tevent_req_data(req, struct sdap_dyndns_update_state);
     514             : 
     515           0 :     ret = be_nsupdate_recv(subreq, &child_status);
     516           0 :     talloc_zfree(subreq);
     517           0 :     if (ret != EOK) {
     518             :         /* If the update didn't succeed, we can retry using the server name */
     519           0 :         if (state->fallback_mode == false
     520           0 :                 && WIFEXITED(child_status)
     521           0 :                 && WEXITSTATUS(child_status) != 0) {
     522           0 :             state->fallback_mode = true;
     523           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "nsupdate failed, retrying\n");
     524           0 :             ret = sdap_dyndns_update_ptr_step(req);
     525           0 :             if (ret == EOK) {
     526           0 :                 return;
     527             :             }
     528             :         }
     529             : 
     530           0 :         ret = sdap_dyndns_next_ptr_record(state, req);
     531           0 :         if (ret == EAGAIN) {
     532           0 :             return;
     533             :         }
     534             : 
     535           0 :         tevent_req_error(req, ret);
     536           0 :         return;
     537             :     }
     538             : 
     539           0 :     ret = sdap_dyndns_next_ptr_record(state, req);
     540           0 :     if (ret == EAGAIN) {
     541           0 :         return;
     542             :     }
     543             : 
     544           0 :     tevent_req_done(req);
     545             : }
     546             : 
     547             : static errno_t
     548           0 : sdap_dyndns_next_ptr_record(struct sdap_dyndns_update_state *state,
     549             :                             struct tevent_req *req)
     550             : {
     551             :     errno_t ret;
     552             : 
     553           0 :     if (state->del_phase) {
     554             :         /* iterate to next address to delete */
     555           0 :         state->ptr_addr_iter = sdap_get_address_to_delete(
     556           0 :             sss_iface_addr_get_next(state->ptr_addr_iter), state->remove_af);
     557           0 :         if (state->ptr_addr_iter == NULL) {
     558             :             /* init iterator for addresses to be added */
     559           0 :             state->del_phase = false;
     560           0 :             state->ptr_addr_iter = state->addresses;
     561             :         }
     562             :     } else {
     563             :         /* iterate to next address to add */
     564           0 :         state->ptr_addr_iter = sss_iface_addr_get_next(state->ptr_addr_iter);
     565             :     }
     566             : 
     567           0 :     if (state->ptr_addr_iter != NULL) {
     568             : 
     569           0 :         state->fallback_mode = false;
     570           0 :         ret = sdap_dyndns_update_ptr_step(req);
     571           0 :         if (ret == EOK) {
     572           0 :             return EAGAIN;
     573             :         }
     574             :     }
     575             : 
     576           0 :     return EOK;
     577             : }
     578             : 
     579             : errno_t
     580           0 : sdap_dyndns_update_recv(struct tevent_req *req)
     581             : {
     582           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     583           0 :     return EOK;
     584             : }
     585             : 
     586             : /* A request to get addresses to update with */
     587             : struct sdap_dyndns_get_addrs_state {
     588             :     struct sdap_id_op* sdap_op;
     589             :     struct sss_iface_addr *addresses;
     590             : };
     591             : 
     592             : static void sdap_dyndns_get_addrs_done(struct tevent_req *subreq);
     593             : static errno_t sdap_dyndns_add_ldap_conn(struct sdap_dyndns_get_addrs_state *state,
     594             :                                          struct sdap_handle *sh);
     595             : 
     596           0 : static errno_t get_ifaces_addrs(TALLOC_CTX *mem_ctx,
     597             :                                 const char *iface,
     598             :                                 struct sss_iface_addr **_result)
     599             : {
     600           0 :     struct sss_iface_addr *result_addrs = NULL;
     601             :     struct sss_iface_addr *intf_addrs;
     602             :     TALLOC_CTX *tmp_ctx;
     603             :     char **list_of_intfs;
     604             :     int num_of_intfs;
     605             :     errno_t ret;
     606             :     int i;
     607             : 
     608           0 :     tmp_ctx = talloc_new(NULL);
     609           0 :     if (tmp_ctx == NULL) {
     610           0 :         ret = ENOMEM;
     611           0 :         goto done;
     612             :     }
     613             : 
     614           0 :     ret = split_on_separator(tmp_ctx, iface, ',', true, true, &list_of_intfs,
     615             :                              &num_of_intfs);
     616           0 :     if (ret != EOK) {
     617           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     618             :               "Parsing names of interfaces failed - %d:[%s].\n",
     619             :               ret, sss_strerror(ret));
     620           0 :         goto done;
     621             :     }
     622             : 
     623           0 :     for (i = 0; i < num_of_intfs; i++) {
     624           0 :         ret = sss_iface_addr_list_get(tmp_ctx, list_of_intfs[i], &intf_addrs);
     625           0 :         if (ret == EOK) {
     626           0 :             if (result_addrs != NULL) {
     627             :                 /* If there is already an existing list, head of this existing
     628             :                  * list will be considered as parent talloc context for the
     629             :                  * new list.
     630             :                  */
     631           0 :                 talloc_steal(result_addrs, intf_addrs);
     632             :             }
     633           0 :             sss_iface_addr_concatenate(&result_addrs, intf_addrs);
     634           0 :         } else if (ret == ENOENT) {
     635             :             /* non-critical failure */
     636           0 :             DEBUG(SSSDBG_TRACE_FUNC,
     637             :                   "Cannot get interface %s or there are no addresses "
     638             :                   "bind to it.\n", list_of_intfs[i]);
     639             :         } else {
     640           0 :             DEBUG(SSSDBG_OP_FAILURE,
     641             :                   "Cannot get list of addresses from interface %s - %d:[%s]\n",
     642             :                   list_of_intfs[i], ret, sss_strerror(ret));
     643           0 :             goto done;
     644             :         }
     645             :     }
     646             : 
     647           0 :     ret = EOK;
     648           0 :     *_result = talloc_steal(mem_ctx, result_addrs);
     649             : 
     650             : done:
     651           0 :     talloc_free(tmp_ctx);
     652           0 :     return ret;
     653             : }
     654             : 
     655             : static struct tevent_req *
     656           0 : sdap_dyndns_get_addrs_send(TALLOC_CTX *mem_ctx,
     657             :                            struct tevent_context *ev,
     658             :                            struct sdap_id_ctx *sdap_ctx,
     659             :                            const char *iface)
     660             : {
     661             :     errno_t ret;
     662             :     struct tevent_req *req;
     663             :     struct tevent_req *subreq;
     664             :     struct sdap_dyndns_get_addrs_state *state;
     665             : 
     666           0 :     req = tevent_req_create(mem_ctx, &state,
     667             :                             struct sdap_dyndns_get_addrs_state);
     668           0 :     if (req == NULL) {
     669           0 :         return NULL;
     670             :     }
     671             : 
     672           0 :     if (iface) {
     673           0 :         ret = get_ifaces_addrs(state, iface, &state->addresses);
     674           0 :         if (ret != EOK || state->addresses == NULL) {
     675           0 :             DEBUG(SSSDBG_MINOR_FAILURE,
     676             :                   "get_ifaces_addrs() failed: %d:[%s]\n",
     677             :                   ret, sss_strerror(ret));
     678             :         }
     679             :         /* We're done. Just fake an async request completion */
     680           0 :         goto done;
     681             :     }
     682             : 
     683             :     /* Detect DYNDNS address from LDAP connection */
     684           0 :     state->sdap_op = sdap_id_op_create(state, sdap_ctx->conn->conn_cache);
     685           0 :     if (!state->sdap_op) {
     686           0 :         ret = ENOMEM;
     687           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
     688           0 :         goto done;
     689             :     }
     690             : 
     691           0 :     subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
     692           0 :     if (!subreq) {
     693           0 :         ret = EIO;
     694           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n",
     695             :               ret, sss_strerror(ret));
     696           0 :         goto done;
     697             :     }
     698           0 :     tevent_req_set_callback(subreq, sdap_dyndns_get_addrs_done, req);
     699             : 
     700           0 :     ret = EAGAIN;
     701             : done:
     702           0 :     if (ret == EOK) {
     703           0 :         tevent_req_done(req);
     704           0 :         tevent_req_post(req, ev);
     705           0 :     } else if (ret != EAGAIN) {
     706           0 :         tevent_req_error(req, ret);
     707           0 :         tevent_req_post(req, ev);
     708             :     }
     709             : 
     710             :     /* EAGAIN - resolution in progress */
     711           0 :     return req;
     712             : }
     713             : 
     714             : static void
     715           0 : sdap_dyndns_get_addrs_done(struct tevent_req *subreq)
     716             : {
     717             :     errno_t ret;
     718             :     int dp_error;
     719             :     struct tevent_req *req;
     720             :     struct sdap_dyndns_get_addrs_state *state;
     721             : 
     722           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     723           0 :     state = tevent_req_data(req, struct sdap_dyndns_get_addrs_state);
     724             : 
     725           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     726           0 :     talloc_zfree(subreq);
     727           0 :     if (ret != EOK) {
     728           0 :         if (dp_error == DP_ERR_OFFLINE) {
     729           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "No LDAP server is available, "
     730             :                   "dynamic DNS update is skipped in offline mode.\n");
     731           0 :             ret = ERR_DYNDNS_OFFLINE;
     732             :         } else {
     733           0 :             DEBUG(SSSDBG_OP_FAILURE,
     734             :                   "Failed to connect to LDAP server: [%d](%s)\n",
     735             :                   ret, sss_strerror(ret));
     736             :         }
     737           0 :         tevent_req_error(req, ret);
     738           0 :         return;
     739             :     }
     740             : 
     741           0 :     ret = sdap_dyndns_add_ldap_conn(state, sdap_id_op_handle(state->sdap_op));
     742           0 :     if (ret != EOK) {
     743           0 :         DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses from LDAP connection\n");
     744           0 :         tevent_req_error(req, ret);
     745           0 :         return;
     746             :     }
     747             : 
     748             :     /* Got the address! Done! */
     749           0 :     tevent_req_done(req);
     750             : }
     751             : 
     752             : static errno_t
     753           0 : sdap_dyndns_add_ldap_conn(struct sdap_dyndns_get_addrs_state *state,
     754             :                           struct sdap_handle *sh)
     755             : {
     756             :     int ret;
     757             :     int fd;
     758             :     struct sockaddr_storage ss;
     759           0 :     socklen_t ss_len = sizeof(ss);
     760             : 
     761           0 :     if (sh == NULL) {
     762           0 :         return EINVAL;
     763             :     }
     764             : 
     765             :     /* Get the file descriptor for the primary LDAP connection */
     766           0 :     ret = get_fd_from_ldap(sh->ldap, &fd);
     767           0 :     if (ret != EOK) {
     768           0 :         return ret;
     769             :     }
     770             : 
     771           0 :     errno = 0;
     772           0 :     ret = getsockname(fd, (struct sockaddr *) &ss, &ss_len);
     773           0 :     if (ret == -1) {
     774           0 :         ret = errno;
     775           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to get socket name\n");
     776           0 :         return ret;
     777             :     }
     778             : 
     779           0 :     if (ss.ss_family != AF_INET && ss.ss_family != AF_INET6) {
     780           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     781             :               "Connection to LDAP is neither IPv4 nor IPv6\n");
     782           0 :         return EIO;
     783             :     }
     784             : 
     785           0 :     ret = sss_get_dualstack_addresses(state, (struct sockaddr *) &ss,
     786             :                                       &state->addresses);
     787           0 :     if (ret != EOK) {
     788           0 :         DEBUG(SSSDBG_MINOR_FAILURE,
     789             :               "sss_get_dualstack_addresses failed: %d:[%s]\n",
     790             :               ret, sss_strerror(ret));
     791           0 :         return ret;
     792             :     }
     793             : 
     794           0 :     return EOK;
     795             : }
     796             : 
     797             : static errno_t
     798           0 : sdap_dyndns_get_addrs_recv(struct tevent_req *req,
     799             :                            TALLOC_CTX *mem_ctx,
     800             :                            struct sss_iface_addr **_addresses)
     801             : {
     802             :     struct sdap_dyndns_get_addrs_state *state;
     803             : 
     804           0 :     state = tevent_req_data(req, struct sdap_dyndns_get_addrs_state);
     805             : 
     806           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     807             : 
     808           0 :     *_addresses = talloc_steal(mem_ctx, state->addresses);
     809           0 :     return EOK;
     810             : }
     811             : 
     812             : struct sdap_dyndns_timer_state {
     813             :     struct tevent_context *ev;
     814             :     struct sdap_id_ctx *sdap_ctx;
     815             :     struct be_nsupdate_ctx *dyndns_ctx;
     816             : 
     817             :     struct sdap_id_op *sdap_op;
     818             : };
     819             : 
     820             : static void sdap_dyndns_timer_conn_done(struct tevent_req *req);
     821             : 
     822             : struct tevent_req *
     823           0 : sdap_dyndns_timer_conn_send(TALLOC_CTX *mem_ctx,
     824             :                             struct tevent_context *ev,
     825             :                             struct sdap_id_ctx *sdap_ctx,
     826             :                             struct be_nsupdate_ctx *dyndns_ctx)
     827             : {
     828             :     struct sdap_dyndns_timer_state *state;
     829             :     struct tevent_req *req;
     830             :     struct tevent_req *subreq;
     831             :     errno_t ret;
     832             : 
     833           0 :     req = tevent_req_create(mem_ctx, &state, struct sdap_dyndns_timer_state);
     834           0 :     if (req == NULL) {
     835           0 :         return NULL;
     836             :     }
     837           0 :     state->ev = ev;
     838           0 :     state->sdap_ctx = sdap_ctx;
     839           0 :     state->dyndns_ctx = dyndns_ctx;
     840             : 
     841             :     /* In order to prevent the connection triggering an
     842             :      * online callback which would in turn trigger a concurrent DNS
     843             :      * update
     844             :      */
     845           0 :     state->dyndns_ctx->timer_in_progress = true;
     846             : 
     847             :     /* Make sure to have a valid LDAP connection */
     848           0 :     state->sdap_op = sdap_id_op_create(state, state->sdap_ctx->conn->conn_cache);
     849           0 :     if (state->sdap_op == NULL) {
     850           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n");
     851           0 :         ret = ENOMEM;
     852           0 :         goto fail;
     853             :     }
     854             : 
     855           0 :     subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret);
     856           0 :     if (subreq == NULL) {
     857           0 :         DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed: [%d](%s)\n",
     858             :               ret, sss_strerror(ret));
     859           0 :         ret = ENOMEM;
     860           0 :         goto fail;
     861             :     }
     862           0 :     tevent_req_set_callback(subreq, sdap_dyndns_timer_conn_done, req);
     863           0 :     return req;
     864             : 
     865             : fail:
     866           0 :     dyndns_ctx->timer_in_progress = false;
     867           0 :     be_nsupdate_timer_schedule(ev, dyndns_ctx);
     868           0 :     tevent_req_error(req, ret);
     869           0 :     tevent_req_post(req, ev);
     870           0 :     return req;
     871             : }
     872             : 
     873             : static void
     874           0 : sdap_dyndns_timer_conn_done(struct tevent_req *subreq)
     875             : {
     876           0 :     struct tevent_req *req = tevent_req_callback_data(subreq,
     877             :                                                       struct tevent_req);
     878           0 :     struct sdap_dyndns_timer_state *state = tevent_req_data(req,
     879             :                                             struct sdap_dyndns_timer_state);
     880             :     errno_t ret;
     881             :     int dp_error;
     882             : 
     883           0 :     state->dyndns_ctx->timer_in_progress = false;
     884             : 
     885           0 :     ret = sdap_id_op_connect_recv(subreq, &dp_error);
     886           0 :     talloc_zfree(subreq);
     887           0 :     if (ret != EOK) {
     888           0 :         if (dp_error == DP_ERR_OFFLINE) {
     889           0 :             DEBUG(SSSDBG_MINOR_FAILURE, "No server is available, "
     890             :                   "dynamic DNS update is skipped in offline mode.\n");
     891             :             /* Another timer will be scheduled when provider goes online */
     892           0 :             tevent_req_error(req, ERR_DYNDNS_OFFLINE);
     893             :         } else {
     894           0 :             DEBUG(SSSDBG_OP_FAILURE,
     895             :                   "Failed to connect to LDAP server: [%d](%s)\n",
     896             :                   ret, sss_strerror(ret));
     897             : 
     898             :             /* Just schedule another dyndns retry */
     899           0 :             be_nsupdate_timer_schedule(state->ev, state->dyndns_ctx);
     900           0 :             tevent_req_error(req, ERR_NETWORK_IO);
     901             :         }
     902           0 :         return;
     903             :     }
     904             : 
     905             :     /* All OK, schedule another refresh and let the user call its
     906             :      * provider-specific update
     907             :      */
     908           0 :     be_nsupdate_timer_schedule(state->ev, state->dyndns_ctx);
     909           0 :     tevent_req_done(req);
     910             : }
     911             : 
     912             : errno_t
     913           0 : sdap_dyndns_timer_conn_recv(struct tevent_req *req)
     914             : {
     915           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     916           0 :     return EOK;
     917             : }

Generated by: LCOV version 1.10