From ca261795ce61c41d7e62217ccb2ee913923040ff Mon Sep 17 00:00:00 2001 From: Pavel Březina Date: Fri, 29 Mar 2013 15:26:52 +0100 Subject: resolv: add resolv_get_domain request to resolv utils --- Makefile.am | 3 +- src/resolv/async_resolv.h | 14 ++++ src/resolv/async_resolv_utils.c | 154 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 src/resolv/async_resolv_utils.c diff --git a/Makefile.am b/Makefile.am index 3209cbab3..503b2b7bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -315,7 +315,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 b66bf9da2..cba6ca8d2 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 000000000..9f55e01bb --- /dev/null +++ b/src/resolv/async_resolv_utils.c @@ -0,0 +1,154 @@ +/* + Authors: + Pavel B??ezina + + 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 . +*/ + +#include +#include +#include +#include + +#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: + 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); + if (*_dns_domain == NULL) { + return ENOMEM; + } + + return EOK; +} -- cgit