diff options
Diffstat (limited to 'src/providers/ldap')
-rw-r--r-- | src/providers/ldap/sdap_dyndns.c | 121 |
1 files changed, 115 insertions, 6 deletions
diff --git a/src/providers/ldap/sdap_dyndns.c b/src/providers/ldap/sdap_dyndns.c index 2a179fd1b..3a52a11d1 100644 --- a/src/providers/ldap/sdap_dyndns.c +++ b/src/providers/ldap/sdap_dyndns.c @@ -60,6 +60,8 @@ struct sdap_dyndns_update_state { enum be_nsupdate_auth auth_type; bool fallback_mode; char *update_msg; + struct sss_iface_addr *ptr_addr_iter; + bool del_phase; }; static void sdap_dyndns_update_addrs_done(struct tevent_req *subreq); @@ -70,6 +72,12 @@ static errno_t sdap_dyndns_update_step(struct tevent_req *req); static errno_t sdap_dyndns_update_ptr_step(struct tevent_req *req); static void sdap_dyndns_update_done(struct tevent_req *subreq); static void sdap_dyndns_update_ptr_done(struct tevent_req *subreq); +static errno_t +sdap_dyndns_next_ptr_record(struct sdap_dyndns_update_state *state, + struct tevent_req *req); +static struct sss_iface_addr* +sdap_get_address_to_delete(struct sss_iface_addr *address_it, + uint8_t remove_af); struct tevent_req * sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, @@ -106,6 +114,8 @@ sdap_dyndns_update_send(TALLOC_CTX *mem_ctx, state->ev = ev; state->opts = opts; state->auth_type = auth_type; + state->ptr_addr_iter = NULL; + state->del_phase = true; /* fallback servername is overriden by user option */ conf_servername = dp_opt_get_string(opts, DP_OPT_DYNDNS_SERVER); @@ -381,6 +391,16 @@ sdap_dyndns_update_done(struct tevent_req *subreq) } talloc_free(state->update_msg); + + /* init iterator for addresses to be deleted */ + state->ptr_addr_iter = sdap_get_address_to_delete(state->dns_addrlist, + state->remove_af); + if (state->ptr_addr_iter == NULL) { + /* init iterator for addresses to be added */ + state->del_phase = false; + state->ptr_addr_iter = state->addresses; + } + ret = sdap_dyndns_update_ptr_step(req); if (ret != EOK) { tevent_req_error(req, ret); @@ -389,6 +409,50 @@ sdap_dyndns_update_done(struct tevent_req *subreq) /* Execution will resume in sdap_dyndns_update_ptr_done */ } + +static bool remove_addr(int address_family, uint8_t remove_af) +{ + bool ret = false; + + switch(address_family) { + case AF_INET: + if (remove_af & DYNDNS_REMOVE_A) { + ret = true; + } + break; + case AF_INET6: + if (remove_af & DYNDNS_REMOVE_AAAA) { + ret = true; + } + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Unknown address family\n"); + ret = false; + } + + return ret; +} + +static struct sss_iface_addr* +sdap_get_address_to_delete(struct sss_iface_addr *address_it, + uint8_t remove_af) +{ + struct sockaddr_storage* address; + + while (address_it != NULL) { + address = sss_iface_addr_get_address(address_it); + + /* skip addresses that are not to be deleted */ + if (remove_addr(address->ss_family, remove_af)) { + break; + } + + address_it = sss_iface_addr_get_next(address_it); + } + + return address_it; +} + static errno_t sdap_dyndns_update_ptr_step(struct tevent_req *req) { @@ -396,6 +460,7 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req) struct sdap_dyndns_update_state *state; const char *servername; struct tevent_req *subreq; + struct sockaddr_storage *address; state = tevent_req_data(req, struct sdap_dyndns_update_state); @@ -405,11 +470,14 @@ sdap_dyndns_update_ptr_step(struct tevent_req *req) servername = state->servername; } - ret = be_nsupdate_create_ptr_msg(state, state->realm, - servername, state->hostname, - state->ttl, state->remove_af, - state->addresses, state->dns_addrlist, - &state->update_msg); + address = sss_iface_addr_get_address(state->ptr_addr_iter); + if (address == NULL) { + return EIO; + } + + ret = be_nsupdate_create_ptr_msg(state, state->realm, servername, + state->hostname, state->ttl, address, + state->del_phase, &state->update_msg); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Can't get addresses for DNS update\n"); return ret; @@ -454,13 +522,55 @@ sdap_dyndns_update_ptr_done(struct tevent_req *subreq) } } + ret = sdap_dyndns_next_ptr_record(state, req); + if (ret == EAGAIN) { + return; + } + tevent_req_error(req, ret); return; } + ret = sdap_dyndns_next_ptr_record(state, req); + if (ret == EAGAIN) { + return; + } + tevent_req_done(req); } +static errno_t +sdap_dyndns_next_ptr_record(struct sdap_dyndns_update_state *state, + struct tevent_req *req) +{ + errno_t ret; + + if (state->del_phase) { + /* iterate to next address to delete */ + state->ptr_addr_iter = sdap_get_address_to_delete( + sss_iface_addr_get_next(state->ptr_addr_iter), state->remove_af); + if (state->ptr_addr_iter == NULL) { + /* init iterator for addresses to be added */ + state->del_phase = false; + state->ptr_addr_iter = state->addresses; + } + } else { + /* iterate to next address to add */ + state->ptr_addr_iter = sss_iface_addr_get_next(state->ptr_addr_iter); + } + + if (state->ptr_addr_iter != NULL) { + + state->fallback_mode = false; + ret = sdap_dyndns_update_ptr_step(req); + if (ret == EOK) { + return EAGAIN; + } + } + + return EOK; +} + errno_t sdap_dyndns_update_recv(struct tevent_req *req) { @@ -755,7 +865,6 @@ fail: return req; } - static void sdap_dyndns_timer_conn_done(struct tevent_req *subreq) { |