From 63c5e15cb855fb70dccfd9e81af105ea05ffa466 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 29 Mar 2013 15:26:52 +0100
Subject: [PATCH 1/8] resolv: add resolv_get_domain request to resolv utils

---
 Makefile.am                     |   3 +-
 src/resolv/async_resolv.h       |  14 ++++
 src/resolv/async_resolv_utils.c | 155 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 171 insertions(+), 1 deletion(-)
 create mode 100644 src/resolv/async_resolv_utils.c

diff --git a/Makefile.am b/Makefile.am
index 5039cf4809a42e0cf235dd2f492b97b5531e9f2d..b3f262c0905cb735427b8e0a31596330451f7be0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -313,7 +313,8 @@ SSSD_LCL_TOOLS_OBJ = \
     $(SSSD_TOOLS_OBJ)
 
 SSSD_RESOLV_OBJ = \
-    src/resolv/async_resolv.c
+    src/resolv/async_resolv.c \
+    src/resolv/async_resolv_utils.c
 if BUILD_ARES_DATA
     SSSD_RESOLV_OBJ += \
     src/resolv/ares/ares_parse_srv_reply.c \
diff --git a/src/resolv/async_resolv.h b/src/resolv/async_resolv.h
index b66bf9da2104805b1abea82d7b2e31e40e6d3035..cba6ca8d2974cbbbebe3c2f3d44997b4adc48af4 100644
--- a/src/resolv/async_resolv.h
+++ b/src/resolv/async_resolv.h
@@ -156,4 +156,18 @@ int resolv_gettxt_recv(TALLOC_CTX *mem_ctx,
                        int *timeouts,
                        struct ares_txt_reply **reply_list);
 
+/** Utils **/
+
+struct tevent_req *
+resolv_get_domain_send(TALLOC_CTX *mem_ctx,
+                        struct tevent_context *ev,
+                        struct resolv_ctx *resolv_ctx,
+                        const char *hostname,
+                        enum host_database *host_dbs,
+                        enum restrict_family family_order);
+
+errno_t resolv_get_domain_recv(TALLOC_CTX *mem_ctx,
+                               struct tevent_req *req,
+                               char **_dns_domain);
+
 #endif /* __ASYNC_RESOLV_H__ */
diff --git a/src/resolv/async_resolv_utils.c b/src/resolv/async_resolv_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..9a86d022ddfe7276057d7caa4dccd7969e073e98
--- /dev/null
+++ b/src/resolv/async_resolv_utils.c
@@ -0,0 +1,155 @@
+/*
+    Authors:
+        Pavel Březina <pbrezina@redhat.com>
+
+    Copyright (C) 2013 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <talloc.h>
+#include <tevent.h>
+#include <unistd.h>
+
+#include "util/util.h"
+#include "resolv/async_resolv.h"
+
+struct resolv_get_domain_state {
+    char *fqdn;
+    char *hostname;
+};
+
+static void resolv_get_domain_done(struct tevent_req *subreq);
+
+struct tevent_req *
+resolv_get_domain_send(TALLOC_CTX *mem_ctx,
+                        struct tevent_context *ev,
+                        struct resolv_ctx *resolv_ctx,
+                        const char *hostname,
+                        enum host_database *host_dbs,
+                        enum restrict_family family_order)
+{
+    struct resolv_get_domain_state *state = NULL;
+    struct tevent_req *req = NULL;
+    struct tevent_req *subreq = NULL;
+    char system_hostname[HOST_NAME_MAX];
+    errno_t ret;
+
+    req = tevent_req_create(mem_ctx, &state,
+                            struct resolv_get_domain_state);
+    if (req == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("tevent_req_create() failed\n"));
+        return NULL;
+    }
+
+    if (hostname == NULL) {
+        /* use system hostname */
+        ret = gethostname(system_hostname, HOST_NAME_MAX);
+        if (ret) {
+            ret = errno;
+            DEBUG(SSSDBG_CRIT_FAILURE, ("gethostname() failed: [%d]: %s\n",
+                                        ret, strerror(ret)));
+            goto immediately;
+        }
+        system_hostname[HOST_NAME_MAX-1] = '\0';
+        hostname = system_hostname;
+    }
+
+    state->fqdn = NULL;
+    state->hostname = talloc_strdup(state, hostname);
+    if (state->hostname == NULL) {
+        ret = ENOMEM;
+        goto immediately;
+    }
+
+    DEBUG(SSSDBG_TRACE_LIBS, ("Host name is: %s\n", state->hostname));
+
+    subreq = resolv_gethostbyname_send(state, ev, resolv_ctx, state->hostname,
+                                       family_order, host_dbs);
+    if (subreq == NULL) {
+        talloc_zfree(req);
+        return NULL;
+    }
+
+    tevent_req_set_callback(subreq, resolv_get_domain_done, req);
+
+    return req;
+
+immediately:
+    if (ret == EOK) {
+        tevent_req_done(req);
+    } else {
+        tevent_req_error(req, ret);
+    }
+    tevent_req_post(req, ev);
+
+    return req;
+}
+
+static void resolv_get_domain_done(struct tevent_req *subreq)
+{
+    struct resolv_get_domain_state *state = NULL;
+    struct tevent_req *req = NULL;
+    struct resolv_hostent *rhostent;
+    int resolv_status;
+    errno_t ret;
+
+    req = tevent_req_callback_data(subreq, struct tevent_req);
+    state = tevent_req_data(req, struct resolv_get_domain_state);
+
+    ret = resolv_gethostbyname_recv(subreq, req, &resolv_status,
+                                    NULL, &rhostent);
+    talloc_zfree(subreq);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              ("Could not get fully qualified name for host name %s "
+               "error [%d]: %s, resolver returned: [%d]: %s\n",
+               state->hostname, ret, strerror(ret), resolv_status,
+               resolv_strerror(resolv_status)));
+        state->fqdn = state->hostname;
+    } else {
+        DEBUG(SSSDBG_TRACE_LIBS, ("The FQDN is: %s\n", rhostent->name));
+        state->fqdn = talloc_steal(state, rhostent->name);
+        talloc_zfree(rhostent);
+    }
+
+    tevent_req_done(req);
+}
+
+errno_t resolv_get_domain_recv(TALLOC_CTX *mem_ctx,
+                               struct tevent_req *req,
+                               char **_dns_domain)
+{
+    struct resolv_get_domain_state *state = NULL;
+    char *dns_domain = NULL;
+    char *domptr = NULL;
+
+    state = tevent_req_data(req, struct resolv_get_domain_state);
+
+    TEVENT_REQ_RETURN_ON_ERROR(req);
+
+    domptr = strchr(state->fqdn, '.');
+    if (domptr == NULL || (*(domptr+1) == '\0')) {
+        /* If the FQDN did not contain a dot or the dot was the last character
+         * (broken DNS server perhaps) */
+        dns_domain = state->fqdn;
+    } else {
+        dns_domain = domptr + 1;
+    }
+
+    *_dns_domain = talloc_strdup(mem_ctx, dns_domain);
+
+    return EOK;
+}
-- 
1.7.11.7

