summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-07-28 18:02:10 -0700
committerJeremy Allison <jra@samba.org>2009-07-28 18:02:10 -0700
commit2d0cd3e53ad59f3fe4a42a3158fc85f37e6d6560 (patch)
treecc97643e148afa6d31e7dddeec800bb50179372d
parent285edf6a5986eb3a1f831f4b260afda0bb14c51e (diff)
downloadsamba-2d0cd3e53ad59f3fe4a42a3158fc85f37e6d6560.tar.gz
samba-2d0cd3e53ad59f3fe4a42a3158fc85f37e6d6560.tar.bz2
samba-2d0cd3e53ad59f3fe4a42a3158fc85f37e6d6560.zip
(Hopefully) fix the problem Kai reported with
net ads leave and IPv6. Ensure all DC lookups prefer IPv4. Jeremy.
-rw-r--r--source3/include/proto.h3
-rw-r--r--source3/lib/util_sock.c58
-rw-r--r--source3/libads/cldap.c2
-rw-r--r--source3/libsmb/dsgetdcname.c5
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) {
@@ -78,6 +96,36 @@ bool interpret_string_addr(struct sockaddr_storage *pss,
}
/*******************************************************************
+ 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;
}