From 5b23bc7d811638b7a2fa354a4c27c4294652a7d9 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Mon, 17 Jan 2011 15:14:20 -0500
Subject: [PATCH] Allow fallback to SSSD domain

For backwards-compatibility with older versions of the SSSD (such
as 1.2.x), we need to be able to have our DNS SRV record lookup be
capable of falling back to using the SSSD domain name as the DNS
discovery domain.

This patch modifies our DNS lookups so that they behave as
follows:

If dns_discovery_domain is specified, it is considered
authoritative. No other discovery domains will be attempted.

If dns_discovery_domain is not specified, we first attempt to look
up the SRV records using the domain portion of the machine's
hostname. If this returns "NOTFOUND", we will try performing an
SRV record query using the SSSD domain name as the DNS discovery
domain.

https://fedorahosted.org/sssd/ticket/754
---
 src/providers/data_provider_fo.c |    6 +++-
 src/providers/fail_over.c        |   48 ++++++++++++++++++++++++++++++++++---
 src/providers/fail_over.h        |    3 +-
 3 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index 0b4b2434974f441d129999ff9359e3fcf5fe3255..ddb348f643ca89e151712ecfa4eaa46dcff384b8 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -284,7 +284,8 @@ int be_fo_add_srv_server(struct be_ctx *ctx, const char *service_name,
 
     /* Add the first protocol as the primary lookup */
     ret = fo_add_srv_server(svc->fo_service, query_service,
-                            domain, proto_table[proto], user_data);
+                            domain, ctx->domain->name,
+                            proto_table[proto], user_data);
     if (ret && ret != EEXIST) {
         DEBUG(1, ("Failed to add SRV lookup reference to failover service\n"));
         return ret;
@@ -295,7 +296,8 @@ int be_fo_add_srv_server(struct be_ctx *ctx, const char *service_name,
         /* All the rest as fallback */
         while (i != proto) {
             ret = fo_add_srv_server(svc->fo_service, query_service,
-                                    domain, proto_table[i], user_data);
+                                    domain, ctx->domain->name,
+                                    proto_table[i], user_data);
             if (ret && ret != EEXIST) {
                 DEBUG(1, ("Failed to add SRV lookup reference to failover service\n"));
                 return ret;
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index 331ccccd027c634f5d396ad29e77f1ca519fef2b..3c560089ba9a5fc56cb2c11753b632f72057303b 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -98,6 +98,8 @@ struct server_common {
 
 struct srv_data {
     char *dns_domain;
+    char *discovery_domain;
+    char *sssd_domain;
     char *proto;
     char *srv;
 
@@ -498,7 +500,8 @@ create_server_common(TALLOC_CTX *mem_ctx, struct fo_ctx *ctx, const char *name)
 
 int
 fo_add_srv_server(struct fo_service *service, const char *srv,
-                  const char *dns_domain, const char *proto, void *user_data)
+                  const char *dns_domain, const char *sssd_domain,
+                  const char *proto, void *user_data)
 {
     struct fo_server *server;
 
@@ -539,11 +542,18 @@ fo_add_srv_server(struct fo_service *service, const char *srv,
         return ENOMEM;
 
     if (dns_domain) {
-        server->srv_data->dns_domain = talloc_strdup(server->srv_data, dns_domain);
-        if (server->srv_data->dns_domain == NULL)
+        server->srv_data->discovery_domain = talloc_strdup(server->srv_data, dns_domain);
+        if (server->srv_data->discovery_domain == NULL)
             return ENOMEM;
+        server->srv_data->dns_domain =
+                server->srv_data->discovery_domain;
     }
 
+    server->srv_data->sssd_domain =
+            talloc_strdup(server->srv_data, sssd_domain);
+    if (server->srv_data->sssd_domain == NULL)
+        return ENOMEM;
+
     server->srv_data->meta = server;
     server->srv_data->srv_lookup_status = DEFAULT_SRV_STATUS;
     server->srv_data->last_status_change.tv_sec = 0;
@@ -1063,8 +1073,38 @@ resolve_srv_done(struct tevent_req *subreq)
                              &resolv_status, NULL, &reply_list);
     talloc_free(subreq);
     if (ret != EOK) {
-        DEBUG(1, ("SRV query failed %s\n",
+        DEBUG(1, ("SRV query failed: [%s]\n",
                   resolv_strerror(resolv_status)));
+        if (resolv_status == ARES_ENOTFOUND &&
+                state->meta->srv_data->dns_domain !=
+                    state->meta->srv_data->discovery_domain &&
+                state->meta->srv_data->dns_domain !=
+                    state->meta->srv_data->sssd_domain) {
+            /* The domain name could not be identified
+             * If the domain wasn't specified in the config
+             * file, also check whether the SSSD domain
+             * works.
+             *
+             * Programming note: It is safe to compare
+             * pointers here, because we're not copying
+             * the data, we're just reassigning the pointer
+             * for the active domain.
+             */
+            talloc_free(state->meta->srv_data->dns_domain);
+            state->meta->srv_data->dns_domain =
+                    state->meta->srv_data->sssd_domain;
+            resolve_srv_cont(req);
+            return;
+        }
+
+        /* We need to make sure we reset this to NULL
+         * so that if we go online later, we re-check
+         * the DNS domain
+         */
+        if (!state->meta->srv_data->discovery_domain) {
+            state->meta->srv_data->dns_domain = NULL;
+        }
+
         fo_set_port_status(state->meta, PORT_NOT_WORKING);
         goto fail;
     }
diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h
index dce02dc60be4bdcd5305ef46e92180da9719f791..6a3101fedb4011131f38006b41859cdffb28422a 100644
--- a/src/providers/fail_over.h
+++ b/src/providers/fail_over.h
@@ -116,7 +116,8 @@ int fo_add_server(struct fo_service *service,
 
 int fo_add_srv_server(struct fo_service *service,
                       const char *srv,
-                      const char *domain,
+                      const char *dns_domain,
+                      const char *sssd_domain,
                       const char *proto,
                       void *user_data);
 
-- 
1.7.3.4

