summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-07-28 11:51:58 -0700
committerJeremy Allison <jra@samba.org>2009-07-28 11:51:58 -0700
commit5d05d2299983b5d34615cd269b04806bba173c0d (patch)
tree05b72de06182ef588d5cf1bc14806a0d22144b92 /source3/libsmb
parent571f20cd4db48c8d510e10b7188678d585abb2d1 (diff)
downloadsamba-5d05d2299983b5d34615cd269b04806bba173c0d.tar.gz
samba-5d05d2299983b5d34615cd269b04806bba173c0d.tar.bz2
samba-5d05d2299983b5d34615cd269b04806bba173c0d.zip
Added prefer_ipv4 bool parameter to resolve_name().
W2K3 DC's can have IPv6 addresses but won't serve krb5/ldap or cldap on those addresses. Make sure when we're asking for DC's we prefer IPv4. If you have an IPv6-only network this prioritizing code will be a no-op. And if you have a mixed network then you need to prioritize IPv4 due to W2K3 DC's. Jeremy.
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/libsmb_dir.c6
-rw-r--r--source3/libsmb/namequery.c63
-rw-r--r--source3/libsmb/passchange.c2
3 files changed, 62 insertions, 9 deletions
diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c
index a3f63f204d..7a6632ae4e 100644
--- a/source3/libsmb/libsmb_dir.c
+++ b/source3/libsmb/libsmb_dir.c
@@ -615,8 +615,8 @@ SMBC_opendir_ctx(SMBCCTX *context,
*/
if (!srv &&
!is_ipaddress(server) &&
- (resolve_name(server, &rem_ss, 0x1d) || /* LMB */
- resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */
+ (resolve_name(server, &rem_ss, 0x1d, false) || /* LMB */
+ resolve_name(server, &rem_ss, 0x1b, false) )) { /* DMB */
fstring buserver;
@@ -675,7 +675,7 @@ SMBC_opendir_ctx(SMBCCTX *context,
return NULL;
}
} else if (srv ||
- (resolve_name(server, &rem_ss, 0x20))) {
+ (resolve_name(server, &rem_ss, 0x20, false))) {
/*
* If we hadn't found the server, get one now
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 05143270b9..1a641ac791 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -439,12 +439,12 @@ static int addr_compare(const struct sockaddr *ss1,
int num_interfaces = iface_count();
int i;
- /* Sort IPv6 addresses first. */
+ /* Sort IPv4 addresses first. */
if (ss1->sa_family != ss2->sa_family) {
if (ss2->sa_family == AF_INET) {
- return -1;
- } else {
return 1;
+ } else {
+ return -1;
}
}
@@ -601,6 +601,38 @@ static int remove_duplicate_addrs2(struct ip_service *iplist, int count )
return count;
}
+static bool prioritize_ipv4_list(struct ip_service *iplist, int count)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct ip_service *iplist_new = TALLOC_ARRAY(frame, struct ip_service, count);
+ int i, j;
+
+ if (iplist_new == NULL) {
+ TALLOC_FREE(frame);
+ return false;
+ }
+
+ j = 0;
+
+ /* Copy IPv4 first. */
+ for (i = 0; i < count; i++) {
+ if (iplist[i].ss.ss_family == AF_INET) {
+ iplist_new[j++] = iplist[i];
+ }
+ }
+
+ /* Copy IPv6. */
+ for (i = 0; i < count; i++) {
+ if (iplist[i].ss.ss_family != AF_INET) {
+ iplist_new[j++] = iplist[i];
+ }
+ }
+
+ memcpy(iplist, iplist_new, sizeof(struct ip_service)*count);
+ TALLOC_FREE(frame);
+ return true;
+}
+
/****************************************************************************
Do a netbios name query to find someones IP.
Returns an array of IP addresses or NULL if none.
@@ -1664,7 +1696,8 @@ NTSTATUS internal_resolve_name(const char *name,
bool resolve_name(const char *name,
struct sockaddr_storage *return_ss,
- int name_type)
+ int name_type,
+ bool prefer_ipv4)
{
struct ip_service *ss_list = NULL;
char *sitename = NULL;
@@ -1681,6 +1714,19 @@ bool resolve_name(const char *name,
lp_name_resolve_order()))) {
int i;
+ if (prefer_ipv4) {
+ for (i=0; i<count; i++) {
+ if (!is_zero_addr((struct sockaddr *)&ss_list[i].ss) &&
+ !is_broadcast_addr((struct sockaddr *)&ss_list[i].ss) &&
+ (ss_list[i].ss.ss_family == AF_INET)) {
+ *return_ss = ss_list[i].ss;
+ SAFE_FREE(ss_list);
+ SAFE_FREE(sitename);
+ return True;
+ }
+ }
+ }
+
/* only return valid addresses for TCP connections */
for (i=0; i<count; i++) {
if (!is_zero_addr((struct sockaddr *)&ss_list[i].ss) &&
@@ -2056,7 +2102,7 @@ static NTSTATUS get_dc_list(const char *domain,
/* explicit lookup; resolve_name() will
* handle names & IP addresses */
- if (resolve_name( name, &name_ss, 0x20 )) {
+ if (resolve_name( name, &name_ss, 0x20, true )) {
char addr[INET6_ADDRSTRLEN];
print_sockaddr(addr,
sizeof(addr),
@@ -2086,6 +2132,13 @@ static NTSTATUS get_dc_list(const char *domain,
local_count );
}
+ /* For DC's we always prioritize IPv4 due to W2K3 not
+ * supporting LDAP, KRB5 or CLDAP over IPv6. */
+
+ if (local_count && return_iplist) {
+ prioritize_ipv4_list(return_iplist, local_count);
+ }
+
if ( DEBUGLEVEL >= 4 ) {
DEBUG(4,("get_dc_list: returning %d ip addresses "
"in an %sordered list\n",
diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c
index 7f0389f132..bb70386990 100644
--- a/source3/libsmb/passchange.c
+++ b/source3/libsmb/passchange.c
@@ -37,7 +37,7 @@ NTSTATUS remote_password_change(const char *remote_machine, const char *user_nam
*err_str = NULL;
- if(!resolve_name( remote_machine, &ss, 0x20)) {
+ if(!resolve_name( remote_machine, &ss, 0x20, false)) {
if (asprintf(err_str, "Unable to find an IP address for machine "
"%s.\n", remote_machine) == -1) {
*err_str = NULL;