summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-01-13 11:02:02 -0500
committerStephen Gallagher <sgallagh@redhat.com>2010-01-22 13:40:21 -0500
commit79cafdcc25948300e2b0c85955b67b0d0c4c73c7 (patch)
tree1d69ed37c2c7e8866f5d3a5047363315d9170ce4
parent2176c6534872b1229a24f34ddd5eebae1ea08a76 (diff)
downloadsssd-79cafdcc25948300e2b0c85955b67b0d0c4c73c7.tar.gz
sssd-79cafdcc25948300e2b0c85955b67b0d0c4c73c7.tar.bz2
sssd-79cafdcc25948300e2b0c85955b67b0d0c4c73c7.zip
Handle IPv6 addresses with the async resolver
-rw-r--r--server/providers/fail_over.c3
-rw-r--r--server/resolv/async_resolv.c62
-rw-r--r--server/resolv/async_resolv.h3
-rw-r--r--server/tests/resolv-tests.c10
4 files changed, 65 insertions, 13 deletions
diff --git a/server/providers/fail_over.c b/server/providers/fail_over.c
index 9795ccec..7560b89e 100644
--- a/server/providers/fail_over.c
+++ b/server/providers/fail_over.c
@@ -497,9 +497,8 @@ fo_resolve_service_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
switch (get_server_status(server)) {
case SERVER_NAME_NOT_RESOLVED: /* Request name resolution. */
- /* TODO: Enable IPv6. */
subreq = resolv_gethostbyname_send(server->common, ev, resolv,
- server->common->name, AF_INET);
+ server->common->name);
if (subreq == NULL) {
ret = ENOMEM;
goto done;
diff --git a/server/resolv/async_resolv.c b/server/resolv/async_resolv.c
index 7973a78f..70d8d11e 100644
--- a/server/resolv/async_resolv.c
+++ b/server/resolv/async_resolv.c
@@ -472,7 +472,7 @@ ares_gethostbyname_wakeup(struct tevent_req *req);
struct tevent_req *
resolv_gethostbyname_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
- struct resolv_ctx *ctx, const char *name, int family)
+ struct resolv_ctx *ctx, const char *name)
{
struct tevent_req *req, *subreq;
struct gethostbyname_state *state;
@@ -491,7 +491,7 @@ resolv_gethostbyname_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
state->resolv_ctx = ctx;
state->name = name;
- state->family = family;
+ state->family = AF_INET;
state->hostent = NULL;
state->status = 0;
state->timeouts = 0;
@@ -513,6 +513,9 @@ resolv_gethostbyname_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
}
static void
+resolv_gethostbyname6_done(void *arg, int status, int timeouts, struct hostent *hostent);
+
+static void
resolv_gethostbyname_done(void *arg, int status, int timeouts, struct hostent *hostent)
{
struct tevent_req *req = talloc_get_type(arg, struct tevent_req);
@@ -540,10 +543,61 @@ resolv_gethostbyname_done(void *arg, int status, int timeouts, struct hostent *h
state->status = status;
state->timeouts = timeouts;
- if (status != ARES_SUCCESS)
+ if (status != ARES_SUCCESS) {
+ if (status == ARES_ENOTFOUND || status == ARES_ENODATA) {
+ /* IPv4 failure. Try IPv6 */
+ state->family = AF_INET6;
+ state->retrying = 0;
+ state->timeouts = 0;
+ DEBUG(4, ("Trying to resolve AAAA record of '%s'\n",
+ state->name));
+ ares_gethostbyname(state->resolv_ctx->channel, state->name,
+ state->family, resolv_gethostbyname6_done,
+ req);
+ return;
+ }
+
+ /* Any other error indicates a server error,
+ * so don't bother trying again
+ */
tevent_req_error(req, return_code(status));
- else
+ }
+ else {
tevent_req_done(req);
+ }
+}
+
+static void
+resolv_gethostbyname6_done(void *arg, int status, int timeouts, struct hostent *hostent)
+{
+ struct tevent_req *req = talloc_get_type(arg, struct tevent_req);
+ struct gethostbyname_state *state = tevent_req_data(req, struct gethostbyname_state);
+
+ if (state->retrying == 0 && status == ARES_EDESTRUCTION) {
+ state->retrying = 1;
+ ares_gethostbyname(state->resolv_ctx->channel, state->name,
+ state->family, resolv_gethostbyname6_done, req);
+ return;
+ }
+
+ if (hostent != NULL) {
+ state->hostent = resolv_copy_hostent(req, hostent);
+ if (state->hostent == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ } else {
+ state->hostent = NULL;
+ }
+ state->status = status;
+ state->timeouts = timeouts;
+
+ if (status != ARES_SUCCESS) {
+ tevent_req_error(req, return_code(status));
+ }
+ else {
+ tevent_req_done(req);
+ }
}
int
diff --git a/server/resolv/async_resolv.h b/server/resolv/async_resolv.h
index 5558e15c..2ba6449b 100644
--- a/server/resolv/async_resolv.h
+++ b/server/resolv/async_resolv.h
@@ -60,8 +60,7 @@ struct hostent *resolv_copy_hostent(TALLOC_CTX *mem_ctx,
struct tevent_req *resolv_gethostbyname_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct resolv_ctx *ctx,
- const char *name,
- int family);
+ const char *name);
int resolv_gethostbyname_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
diff --git a/server/tests/resolv-tests.c b/server/tests/resolv-tests.c
index 0c18dfdc..c1b32781 100644
--- a/server/tests/resolv-tests.c
+++ b/server/tests/resolv-tests.c
@@ -178,7 +178,7 @@ START_TEST(test_resolv_localhost)
}
check_leaks_push(test_ctx);
- req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
+ req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname);
DEBUG(7, ("Sent resolv_gethostbyname\n"));
if (req == NULL) {
ret = ENOMEM;
@@ -232,7 +232,7 @@ START_TEST(test_resolv_negative)
}
check_leaks_push(test_ctx);
- req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
+ req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname);
DEBUG(7, ("Sent resolv_gethostbyname\n"));
if (req == NULL) {
ret = ENOMEM;
@@ -322,7 +322,7 @@ START_TEST(test_resolv_internet)
test_ctx->tested_function = TESTING_HOSTNAME;
check_leaks_push(test_ctx);
- req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
+ req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname);
DEBUG(7, ("Sent resolv_gethostbyname\n"));
if (req == NULL) {
ret = ENOMEM;
@@ -425,7 +425,7 @@ START_TEST(test_resolv_free_context)
return;
}
- req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
+ req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname);
DEBUG(7, ("Sent resolv_gethostbyname\n"));
if (req == NULL) {
fail("Error calling resolv_gethostbyname_send");
@@ -484,7 +484,7 @@ START_TEST(test_resolv_free_req)
}
check_leaks_push(test_ctx);
- req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname, AF_INET);
+ req = resolv_gethostbyname_send(test_ctx, test_ctx->ev, test_ctx->resolv, hostname);
DEBUG(7, ("Sent resolv_gethostbyname\n"));
if (req == NULL) {
fail("Error calling resolv_gethostbyname_send");