diff options
author | Jeremy Allison <jra@samba.org> | 2009-07-28 11:51:58 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2009-07-28 11:51:58 -0700 |
commit | 5d05d2299983b5d34615cd269b04806bba173c0d (patch) | |
tree | 05b72de06182ef588d5cf1bc14806a0d22144b92 | |
parent | 571f20cd4db48c8d510e10b7188678d585abb2d1 (diff) | |
download | samba-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.
-rw-r--r-- | source3/auth/auth_server.c | 2 | ||||
-rw-r--r-- | source3/include/proto.h | 3 | ||||
-rw-r--r-- | source3/libads/ldap.c | 37 | ||||
-rw-r--r-- | source3/libsmb/libsmb_dir.c | 6 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 63 | ||||
-rw-r--r-- | source3/libsmb/passchange.c | 2 | ||||
-rw-r--r-- | source3/rpc_client/cli_pipe.c | 2 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 2 | ||||
-rw-r--r-- | source3/smbd/reply.c | 2 | ||||
-rw-r--r-- | source3/torture/torture.c | 2 | ||||
-rw-r--r-- | source3/utils/net_ads.c | 2 | ||||
-rw-r--r-- | source3/utils/net_lookup.c | 4 | ||||
-rw-r--r-- | source3/utils/net_util.c | 8 | ||||
-rw-r--r-- | source3/utils/smbfilter.c | 2 | ||||
-rw-r--r-- | source3/winbindd/winbindd_cm.c | 4 |
15 files changed, 104 insertions, 37 deletions
diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c index 466c4bf129..287b50b080 100644 --- a/source3/auth/auth_server.c +++ b/source3/auth/auth_server.c @@ -60,7 +60,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) } strupper_m(desthost); - if(!resolve_name( desthost, &dest_ss, 0x20)) { + if(!resolve_name( desthost, &dest_ss, 0x20, false)) { DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); continue; } diff --git a/source3/include/proto.h b/source3/include/proto.h index f7fedc7e52..fc009145f0 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3132,7 +3132,8 @@ NTSTATUS internal_resolve_name(const char *name, const char *resolve_order); bool resolve_name(const char *name, struct sockaddr_storage *return_ss, - int name_type); + int name_type, + bool prefer_ipv4); NTSTATUS resolve_name_list(TALLOC_CTX *ctx, const char *name, int name_type, diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 102fc83d0f..bb8d43c96f 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -192,29 +192,42 @@ static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc) { char *srv; struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply; - TALLOC_CTX *mem_ctx = NULL; + TALLOC_CTX *frame = talloc_stackframe(); bool ret = false; if (!server || !*server) { + TALLOC_FREE(frame); return False; } - DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n", - server, ads->server.realm)); + if (!is_ipaddress(server)) { + struct sockaddr_storage ss; + char addr[INET6_ADDRSTRLEN]; - mem_ctx = talloc_init("ads_try_connect"); - if (!mem_ctx) { - DEBUG(0,("out of memory\n")); - return false; + if (!resolve_name(server, &ss, 0x20, true)) { + DEBUG(5,("ads_try_connect: unable to resolve name %s\n", + server )); + TALLOC_FREE(frame); + return false; + } + print_sockaddr(addr, sizeof(addr), &ss); + srv = talloc_strdup(frame, addr); + } else { + /* this copes with inet_ntoa brokenness */ + srv = talloc_strdup(frame, server); } - /* this copes with inet_ntoa brokenness */ + if (!srv) { + TALLOC_FREE(frame); + return false; + } - srv = SMB_STRDUP(server); + DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n", + srv, ads->server.realm)); ZERO_STRUCT( cldap_reply ); - if ( !ads_cldap_netlogon_5(mem_ctx, srv, ads->server.realm, &cldap_reply ) ) { + if ( !ads_cldap_netlogon_5(frame, srv, ads->server.realm, &cldap_reply ) ) { DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", srv)); ret = false; goto out; @@ -267,10 +280,10 @@ static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc) sitename_store( cldap_reply.dns_domain, cldap_reply.client_site); ret = true; + out: - SAFE_FREE(srv); - TALLOC_FREE(mem_ctx); + TALLOC_FREE(frame); return ret; } 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; diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index c9f17c65ad..be375f1ba5 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -3171,7 +3171,7 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx, const char *host, result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN; result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN; - if (!resolve_name(host, &addr, 0)) { + if (!resolve_name(host, &addr, 0, false)) { status = NT_STATUS_NOT_FOUND; goto fail; } diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 9dc1a26e3b..d7bc2624c4 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -2579,7 +2579,7 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct sockaddr_storage rm_addr; if ( is_zero_addr((struct sockaddr *)client_ss) ) { - if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) { + if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) { DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine)); return false; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b5882abe9f..77e122a90c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -466,7 +466,7 @@ static bool netbios_session_retarget(const char *name, int name_type) sscanf(p, "%x", &retarget_type); } - ret = resolve_name(retarget, &retarget_addr, retarget_type); + ret = resolve_name(retarget, &retarget_addr, retarget_type, false); if (!ret) { DEBUG(10, ("could not resolve %s\n", retarget)); goto fail; diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 7185f1c2be..babcb1e7d0 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -5633,7 +5633,7 @@ static bool run_tldap(int dummy) struct tevent_req *req; char *basedn; - if (!resolve_name(host, &addr, 0)) { + if (!resolve_name(host, &addr, 0, false)) { d_printf("could not find host %s\n", host); return false; } diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 9ca52a87bc..4e27278154 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -1655,7 +1655,7 @@ static int net_ads_printer_publish(struct net_context *c, int argc, const char * /* Get printer data from SPOOLSS */ - resolve_name(servername, &server_ss, 0x20); + resolve_name(servername, &server_ss, 0x20, false); nt_status = cli_full_connection(&cli, global_myname(), servername, &server_ss, 0, diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c index 66f673b8d3..e770e3299f 100644 --- a/source3/utils/net_lookup.c +++ b/source3/utils/net_lookup.c @@ -53,7 +53,7 @@ static int net_lookup_host(struct net_context *c, int argc, const char **argv) sscanf(++p,"%x",&name_type); } - if (!resolve_name(name, &ss, name_type)) { + if (!resolve_name(name, &ss, name_type, false)) { /* we deliberately use DEBUG() here to send it to stderr so scripts aren't mucked up */ DEBUG(0,("Didn't find %s#%02x\n", name, name_type)); @@ -72,7 +72,7 @@ static void print_ldap_srvlist(struct dns_rr_srv *dclist, int numdcs ) int i; for ( i=0; i<numdcs; i++ ) { - if (resolve_name(dclist[i].hostname, &ss, 0x20) ) { + if (resolve_name(dclist[i].hostname, &ss, 0x20, true) ) { char addr[INET6_ADDRSTRLEN]; print_sockaddr(addr, sizeof(addr), &ss); #ifdef HAVE_IPV6 diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c index 8bf9aac6f2..383fea47cc 100644 --- a/source3/utils/net_util.c +++ b/source3/utils/net_util.c @@ -393,7 +393,7 @@ bool net_find_server(struct net_context *c, } } else if (*server_name) { /* resolve the IP address */ - if (!resolve_name(*server_name, server_ss, 0x20)) { + if (!resolve_name(*server_name, server_ss, 0x20, false)) { DEBUG(1,("Unable to resolve server name\n")); return false; } @@ -420,8 +420,8 @@ bool net_find_server(struct net_context *c, struct sockaddr_storage msbrow_ss; char addr[INET6_ADDRSTRLEN]; - /* if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */ - if (!resolve_name(d, &msbrow_ss, 0x1B)) { + /* if (!resolve_name(MSBROWSE, &msbrow_ip, 1, false)) */ + if (!resolve_name(d, &msbrow_ss, 0x1B, false)) { DEBUG(1,("Unable to resolve domain browser via name lookup\n")); return false; } @@ -431,7 +431,7 @@ bool net_find_server(struct net_context *c, } else if (flags & NET_FLAGS_MASTER) { struct sockaddr_storage brow_ss; char addr[INET6_ADDRSTRLEN]; - if (!resolve_name(d, &brow_ss, 0x1D)) { + if (!resolve_name(d, &brow_ss, 0x1D, false)) { /* go looking for workgroups */ DEBUG(1,("Unable to resolve master browser via name lookup\n")); return false; diff --git a/source3/utils/smbfilter.c b/source3/utils/smbfilter.c index 39a264011e..83de0c4c37 100644 --- a/source3/utils/smbfilter.c +++ b/source3/utils/smbfilter.c @@ -232,7 +232,7 @@ static void start_filter(char *desthost) d_printf("listen failed\n"); } - if (!resolve_name(desthost, &dest_ss, 0x20)) { + if (!resolve_name(desthost, &dest_ss, 0x20, false)) { d_printf("Unable to resolve host %s\n", desthost); exit(1); } diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c index a7c63ea71e..460c7738b3 100644 --- a/source3/winbindd/winbindd_cm.c +++ b/source3/winbindd/winbindd_cm.c @@ -679,7 +679,7 @@ static bool get_dc_name_via_netlogon(struct winbindd_domain *domain, DEBUG(10,("rpccli_netr_GetAnyDCName returned %s\n", dcname)); - if (!resolve_name(dcname, dc_ss, 0x20)) { + if (!resolve_name(dcname, dc_ss, 0x20, true)) { return False; } @@ -1467,7 +1467,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, if (*domain->dcname && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname)) - && (resolve_name(domain->dcname, &domain->dcaddr, 0x20))) + && (resolve_name(domain->dcname, &domain->dcaddr, 0x20, true))) { struct sockaddr_storage *addrs = NULL; int num_addrs = 0; |