From 2d0cd3e53ad59f3fe4a42a3158fc85f37e6d6560 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jul 2009 18:02:10 -0700 Subject: (Hopefully) fix the problem Kai reported with net ads leave and IPv6. Ensure all DC lookups prefer IPv4. Jeremy. --- source3/include/proto.h | 3 +++ source3/lib/util_sock.c | 58 ++++++++++++++++++++++++++++++++++++++++---- source3/libads/cldap.c | 2 +- source3/libsmb/dsgetdcname.c | 5 ++-- 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index fc009145f0..697051ceea 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1333,6 +1333,9 @@ bool is_broadcast_addr(const struct sockaddr *pss); bool interpret_string_addr(struct sockaddr_storage *pss, const char *str, int flags); +bool interpret_string_addr_prefer_ipv4(struct sockaddr_storage *pss, + const char *str, + int flags); bool is_loopback_ip_v4(struct in_addr ip); bool is_loopback_addr(const struct sockaddr *pss); bool is_zero_addr(const struct sockaddr *pss); diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index af64f370ba..ec88b6046a 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -23,12 +23,14 @@ /******************************************************************* Map a text hostname or IP address (IPv4 or IPv6) into a - struct sockaddr_storage. + struct sockaddr_storage. Takes a flag which allows it to + prefer an IPv4 address (needed for DC's). ******************************************************************/ -bool interpret_string_addr(struct sockaddr_storage *pss, +static bool interpret_string_addr_pref(struct sockaddr_storage *pss, const char *str, - int flags) + int flags, + bool prefer_ipv4) { struct addrinfo *res = NULL; #if defined(HAVE_IPV6) @@ -60,8 +62,24 @@ bool interpret_string_addr(struct sockaddr_storage *pss, if (!res) { return false; } - /* Copy the first sockaddr. */ - memcpy(pss, res->ai_addr, res->ai_addrlen); + + if (prefer_ipv4) { + struct addrinfo *p; + + for (p = res; p; p = p->ai_next) { + if (p->ai_family == AF_INET) { + memcpy(pss, p->ai_addr, p->ai_addrlen); + break; + } + } + if (p == NULL) { + /* Copy the first sockaddr. */ + memcpy(pss, res->ai_addr, res->ai_addrlen); + } + } else { + /* Copy the first sockaddr. */ + memcpy(pss, res->ai_addr, res->ai_addrlen); + } #if defined(HAVE_IPV6) if (pss->ss_family == AF_INET6 && scope_id) { @@ -77,6 +95,36 @@ bool interpret_string_addr(struct sockaddr_storage *pss, return true; } +/******************************************************************* + Map a text hostname or IP address (IPv4 or IPv6) into a + struct sockaddr_storage. Address agnostic version. +******************************************************************/ + +bool interpret_string_addr(struct sockaddr_storage *pss, + const char *str, + int flags) +{ + return interpret_string_addr_pref(pss, + str, + flags, + false); +} + +/******************************************************************* + Map a text hostname or IP address (IPv4 or IPv6) into a + struct sockaddr_storage. Version that prefers IPv4. +******************************************************************/ + +bool interpret_string_addr_prefer_ipv4(struct sockaddr_storage *pss, + const char *str, + int flags) +{ + return interpret_string_addr_pref(pss, + str, + flags, + true); +} + /******************************************************************* Set an address to INADDR_ANY. ******************************************************************/ diff --git a/source3/libads/cldap.c b/source3/libads/cldap.c index 523020797b..5cefd6ccc1 100644 --- a/source3/libads/cldap.c +++ b/source3/libads/cldap.c @@ -44,7 +44,7 @@ bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx, int ret; struct tsocket_address *dest_addr; - if (!interpret_string_addr(&ss, server, 0)) { + if (!interpret_string_addr_prefer_ipv4(&ss, server, 0)) { DEBUG(2,("Failed to resolve[%s] into an address for cldap\n", server)); return false; diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index 3e0f4977aa..de020d4791 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -613,7 +613,8 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx, /* If we don't have an IP list for a name, lookup it up */ if (!dcs[i].ss_s) { - interpret_string_addr(&r->ss, dcs[i].hostname, 0); + interpret_string_addr_prefer_ipv4(&r->ss, + dcs[i].hostname, 0); i++; j = 0; } else { @@ -973,7 +974,7 @@ static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx, ip_list.ss = dclist[i].ss; ip_list.port = 0; - if (!interpret_string_addr(&ss, dclist[i].hostname, AI_NUMERICHOST)) { + if (!interpret_string_addr_prefer_ipv4(&ss, dclist[i].hostname, AI_NUMERICHOST)) { return NT_STATUS_UNSUCCESSFUL; } -- cgit