summaryrefslogtreecommitdiffstats
path: root/src/providers/ldap/sdap_dyndns.c
diff options
context:
space:
mode:
authorPavel Reichl <preichl@redhat.com>2015-09-12 09:09:35 -0400
committerJakub Hrozek <jhrozek@redhat.com>2015-09-22 14:51:22 +0200
commiteeac17ebbe38f16deaa8599231cccfc97aaac85c (patch)
tree9b37ee15c8c3bf452ce6b2fff114d9371c45b785 /src/providers/ldap/sdap_dyndns.c
parente6595222c41af84288d303e8d464ce45b1408ed3 (diff)
downloadsssd-eeac17ebbe38f16deaa8599231cccfc97aaac85c.tar.gz
sssd-eeac17ebbe38f16deaa8599231cccfc97aaac85c.tar.xz
sssd-eeac17ebbe38f16deaa8599231cccfc97aaac85c.zip
DDNS: execute nsupdate for single update of PTR rec
nsupdate fails definitely if any of update request fails when GSSAPI is used. As tmp solution nsupdate is executed for each update. Resolves: https://fedorahosted.org/sssd/ticket/2783 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src/providers/ldap/sdap_dyndns.c')
-rw-r--r--src/providers/ldap/sdap_dyndns.c121
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)
{