diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/auth/auth_domain.c | 5 | ||||
-rw-r--r-- | source3/libads/ldap.c | 3 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 126 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 7 | ||||
-rw-r--r-- | source3/utils/net_lookup.c | 3 |
5 files changed, 115 insertions, 29 deletions
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 2a6614e28e..eebe647ec0 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -275,6 +275,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli, NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS; time_t time_now = time(NULL); BOOL use_pdc_only = False; + BOOL list_ordered; /* * If the time the machine password has changed @@ -301,7 +302,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli, count = 1; } else { - if (!get_dc_list(domain, &ip_list, &count)) + if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) return NT_STATUS_NO_LOGON_SERVERS; } @@ -310,7 +311,7 @@ static NTSTATUS find_connect_pdc(struct cli_state **cli, * network address as any of our interfaces. */ for(i = 0; i < count; i++) { - if(!is_local_net(ip_list[i])) + if( !list_ordered && !is_local_net(ip_list[i]) ) continue; if(NT_STATUS_IS_OK(nt_status = diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 60427323b0..fcb96dd174 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -186,6 +186,7 @@ static BOOL ads_try_netbios(ADS_STRUCT *ads) int count; int i; const char *workgroup = ads->server.workgroup; + BOOL list_ordered; if (!workgroup) { workgroup = lp_workgroup(); @@ -202,7 +203,7 @@ static BOOL ads_try_netbios(ADS_STRUCT *ads) } /* now any DC, including backups */ - if (get_dc_list(workgroup, &ip_list, &count)) { + if (get_dc_list(workgroup, &ip_list, &count, &list_ordered)) { for (i=0;i<count;i++) { DEBUG(6,("ads_try_netbios: trying server '%s'\n", inet_ntoa(ip_list[i]))); diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 5c3d942b90..6190c872ee 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -1235,19 +1235,24 @@ BOOL get_pdc_ip(const char *domain, struct in_addr *ip) a domain. *********************************************************/ -BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count) +BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count, int *ordered) { - /* - * If it's our domain then - * use the 'password server' parameter. - */ + + *ordered = False; + + /* If it's our domain then use the 'password server' parameter. */ if (strequal(domain, lp_workgroup())) { - const char *p; - char *pserver = lp_passwordserver(); + char *p; + char *pserver = lp_passwordserver(); /* UNIX charset. */ fstring name; - int num_adresses = 0; + int num_addresses = 0; + int local_count, i, j; struct in_addr *return_iplist = NULL; + struct in_addr *auto_ip_list = NULL; + BOOL done_auto_lookup = False; + int auto_count = 0; + if (!*pserver) return internal_resolve_name( @@ -1255,19 +1260,31 @@ BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count) p = pserver; + /* + * if '*' appears in the "password server" list then add + * an auto lookup to the list of manually configured + * DC's. If any DC is listed by name, then the list should be + * considered to be ordered + */ + while (next_token(&p,name,LIST_SEP,sizeof(name))) { - if (strequal(name, "*")) - return internal_resolve_name( - domain, 0x1C, ip_list, count); - num_adresses++; + if (strequal(name, "*")) { + if ( internal_resolve_name(domain, 0x1C, &auto_ip_list, &auto_count) ) + num_addresses += auto_count; + done_auto_lookup = True; + DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count)); + } + else + num_addresses++; } - if (num_adresses == 0) - return internal_resolve_name( - domain, 0x1C, ip_list, count); + /* if we have no addresses and haven't done the auto lookup, then + just return the list of DC's */ + + if ( (num_addresses == 0) && !done_auto_lookup ) + return internal_resolve_name(domain, 0x1C, ip_list, count); - return_iplist = (struct in_addr *)malloc( - num_adresses * sizeof(struct in_addr)); + return_iplist = (struct in_addr *)malloc(num_addresses * sizeof(struct in_addr)); if (return_iplist == NULL) { DEBUG(3,("get_dc_list: malloc fail !\n")); @@ -1275,19 +1292,84 @@ BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count) } p = pserver; - *count = 0; + local_count = 0; - while (next_token(&p,name,LIST_SEP,sizeof(name))) { + /* fill in the return list now with real IP's */ + + while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) + { struct in_addr name_ip; - if (resolve_name( name, &name_ip, 0x20) == False) + + /* copy any addersses from the auto lookup */ + + if ( strequal(name, "*") ) { + for ( j=0; j<auto_count; j++ ) + return_iplist[local_count++] = auto_ip_list[j]; continue; - return_iplist[(*count)++] = name_ip; + } + + /* explicit lookup */ + + if ( resolve_name( name, &name_ip, 0x20) ) { + return_iplist[local_count++] = name_ip; + *ordered = True; + } + } - + + /* need to remove duplicates in the list if we have + any explicit password servers */ + + if ( *ordered ) + { + int hole_index = -1; + + /* one loop to remove duplicates */ + for ( i=0; i<local_count; i++ ) + { + if ( is_zero_ip(return_iplist[i]) ) + continue; + + for ( j=i+1; j<local_count; j++ ) { + if ( ip_equal( return_iplist[i], return_iplist[j]) ) + zero_ip(&return_iplist[j]); + } + } + + /* one loop to clean up any holes we left */ + /* first ip can never be a zero_ip() */ + i = 0; + while ( i<local_count ) + { + if ( !is_zero_ip(return_iplist[i]) ) { + i++; + continue; + } + + hole_index = i; + i++; + + while ( i<local_count ) { + if ( !is_zero_ip(return_iplist[i]) ) + return_iplist[hole_index++] = return_iplist[i]; + i++; + } + + /* we should exit the loop implicitly here, but ... */ + break; + } + + local_count = hole_index; + } + *ip_list = return_iplist; + *count = local_count; + + DEBUG(8,("get_dc_list: return %d ip addresses\n", *count)); return (*count != 0); } return internal_resolve_name(domain, 0x1C, ip_list, count); } + diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index d44219d172..403bc38052 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -142,8 +142,9 @@ static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr { struct in_addr *ip_list = NULL; int count, i; + BOOL list_ordered; - if (!get_dc_list(domain, &ip_list, &count)) { + if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) { struct in_addr pdc_ip; if (!get_pdc_ip(domain, &pdc_ip)) { @@ -161,8 +162,8 @@ static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr count = 1; } - /* Pick a nice close server */ - if (count > 1) { + /* Pick a nice close server, but only if the list was not ordered */ + if (!list_ordered && (count > 1) ) { qsort(ip_list, count, sizeof(struct in_addr), QSORT_CAST ip_compare); } diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c index 32921de620..271094480c 100644 --- a/source3/utils/net_lookup.c +++ b/source3/utils/net_lookup.c @@ -128,6 +128,7 @@ static int net_lookup_dc(int argc, const char **argv) char *pdc_str = NULL; const char *domain=opt_target_workgroup; int count, i; + BOOL list_ordered; if (argc > 0) domain=argv[0]; @@ -139,7 +140,7 @@ static int net_lookup_dc(int argc, const char **argv) asprintf(&pdc_str, "%s", inet_ntoa(addr)); d_printf("%s\n", pdc_str); - if (!get_dc_list(domain, &ip_list, &count)) { + if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) { SAFE_FREE(pdc_str); return 0; } |