From 5d05d2299983b5d34615cd269b04806bba173c0d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jul 2009 11:51:58 -0700 Subject: 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. --- source3/auth/auth_server.c | 2 +- source3/include/proto.h | 3 +- source3/libads/ldap.c | 37 +++++++++++++++------- source3/libsmb/libsmb_dir.c | 6 ++-- source3/libsmb/namequery.c | 63 ++++++++++++++++++++++++++++++++++--- source3/libsmb/passchange.c | 2 +- source3/rpc_client/cli_pipe.c | 2 +- source3/rpc_server/srv_spoolss_nt.c | 2 +- source3/smbd/reply.c | 2 +- source3/torture/torture.c | 2 +- source3/utils/net_ads.c | 2 +- source3/utils/net_lookup.c | 4 +-- source3/utils/net_util.c | 8 ++--- source3/utils/smbfilter.c | 2 +- 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 466c4bf129f..287b50b080f 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 f7fedc7e521..fc009145f08 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 102fc83d0fc..bb8d43c96f5 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 a3f63f204d2..7a6632ae4eb 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 05143270b9f..1a641ac7913 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= 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 7f0389f132d..bb70386990a 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 c9f17c65ade..be375f1ba50 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 9dc1a26e3b3..d7bc2624c4e 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 b5882abe9f2..77e122a90c9 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 7185f1c2be8..babcb1e7d0e 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 9ca52a87bc9..4e27278154b 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 66f673b8d32..e770e3299f9 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; idcname && 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; -- cgit v1.2.1