diff options
author | Jeremy Allison <jra@samba.org> | 2004-07-02 01:09:10 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:52:06 -0500 |
commit | 4cc38b8aea51b55cc449cd2144f18de7d4819637 (patch) | |
tree | a4d2c94623dd2db43b022ccf413b9e9112bd3142 /source/libsmb | |
parent | fbc06831d3a7e8645409158ee1ae1f9f192913a7 (diff) | |
download | samba-4cc38b8aea51b55cc449cd2144f18de7d4819637.tar.gz samba-4cc38b8aea51b55cc449cd2144f18de7d4819637.tar.xz samba-4cc38b8aea51b55cc449cd2144f18de7d4819637.zip |
r1326: Modification to get_dc_list to check negative cache. From "Joe Meadows" <jameadows@webopolis.com>.
Jeremy.
Diffstat (limited to 'source/libsmb')
-rw-r--r-- | source/libsmb/conncache.c | 2 | ||||
-rw-r--r-- | source/libsmb/namequery.c | 391 |
2 files changed, 203 insertions, 190 deletions
diff --git a/source/libsmb/conncache.c b/source/libsmb/conncache.c index e6604617d68..15cc75b129e 100644 --- a/source/libsmb/conncache.c +++ b/source/libsmb/conncache.c @@ -154,5 +154,3 @@ void flush_negative_conn_cache( void ) } } - - diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c index 2bb7359e742..cee0015e257 100644 --- a/source/libsmb/namequery.c +++ b/source/libsmb/namequery.c @@ -56,7 +56,8 @@ static struct node_status *parse_node_status(char *p, int *num_names, struct nod return NULL; ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names)); - if (!ret) return NULL; + if (!ret) + return NULL; p++; for (i=0;i< *num_names;i++) { @@ -556,84 +557,80 @@ XFILE *startlmhosts(char *fname) BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr) { - pstring line; - - while(!x_feof(fp) && !x_ferror(fp)) { - pstring ip,flags,extra; - const char *ptr; - char *ptr1; - int count = 0; + pstring line; - *name_type = -1; + while(!x_feof(fp) && !x_ferror(fp)) { + pstring ip,flags,extra; + const char *ptr; + char *ptr1; + int count = 0; - if (!fgets_slash(line,sizeof(pstring),fp)) - continue; + *name_type = -1; - if (*line == '#') - continue; + if (!fgets_slash(line,sizeof(pstring),fp)) { + continue; + } - pstrcpy(ip,""); - pstrcpy(name,""); - pstrcpy(flags,""); + if (*line == '#') { + continue; + } - ptr = line; + pstrcpy(ip,""); + pstrcpy(name,""); + pstrcpy(flags,""); - if (next_token(&ptr,ip ,NULL,sizeof(ip))) - ++count; - if (next_token(&ptr,name ,NULL, sizeof(pstring))) - ++count; - if (next_token(&ptr,flags,NULL, sizeof(flags))) - ++count; - if (next_token(&ptr,extra,NULL, sizeof(extra))) - ++count; + ptr = line; - if (count <= 0) - continue; + if (next_token(&ptr,ip ,NULL,sizeof(ip))) + ++count; + if (next_token(&ptr,name ,NULL, sizeof(pstring))) + ++count; + if (next_token(&ptr,flags,NULL, sizeof(flags))) + ++count; + if (next_token(&ptr,extra,NULL, sizeof(extra))) + ++count; - if (count > 0 && count < 2) - { - DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line)); - continue; - } + if (count <= 0) + continue; - if (count >= 4) - { - DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n")); - continue; - } + if (count > 0 && count < 2) { + DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line)); + continue; + } - DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags)); + if (count >= 4) { + DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n")); + continue; + } - if (strchr_m(flags,'G') || strchr_m(flags,'S')) - { - DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n")); - continue; - } + DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags)); - *ipaddr = *interpret_addr2(ip); + if (strchr_m(flags,'G') || strchr_m(flags,'S')) { + DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n")); + continue; + } - /* Extra feature. If the name ends in '#XX', where XX is a hex number, - then only add that name type. */ - if((ptr1 = strchr_m(name, '#')) != NULL) - { - char *endptr; + *ipaddr = *interpret_addr2(ip); - ptr1++; - *name_type = (int)strtol(ptr1, &endptr, 16); + /* Extra feature. If the name ends in '#XX', where XX is a hex number, + then only add that name type. */ + if((ptr1 = strchr_m(name, '#')) != NULL) { + char *endptr; + ptr1++; - if(!*ptr1 || (endptr == ptr1)) - { - DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name)); - continue; - } + *name_type = (int)strtol(ptr1, &endptr, 16); + if(!*ptr1 || (endptr == ptr1)) { + DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name)); + continue; + } - *(--ptr1) = '\0'; /* Truncate at the '#' */ - } + *(--ptr1) = '\0'; /* Truncate at the '#' */ + } - return True; - } + return True; + } - return False; + return False; } /******************************************************** @@ -998,145 +995,145 @@ static BOOL internal_resolve_name(const char *name, int name_type, struct ip_service **return_iplist, int *return_count, const char *resolve_order) { - pstring name_resolve_list; - fstring tok; - const char *ptr; - BOOL allones = (strcmp(name,"255.255.255.255") == 0); - BOOL allzeros = (strcmp(name,"0.0.0.0") == 0); - BOOL is_address = is_ipaddress(name); - BOOL result = False; - int i; + pstring name_resolve_list; + fstring tok; + const char *ptr; + BOOL allones = (strcmp(name,"255.255.255.255") == 0); + BOOL allzeros = (strcmp(name,"0.0.0.0") == 0); + BOOL is_address = is_ipaddress(name); + BOOL result = False; + int i; - *return_iplist = NULL; - *return_count = 0; + *return_iplist = NULL; + *return_count = 0; - DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type)); + DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type)); - if (allzeros || allones || is_address) { + if (allzeros || allones || is_address) { - if ( (*return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service))) == NULL ) { - DEBUG(0,("internal_resolve_name: malloc fail !\n")); - return False; - } + if ( (*return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service))) == NULL ) { + DEBUG(0,("internal_resolve_name: malloc fail !\n")); + return False; + } - if(is_address) { - /* ignore the port here */ - (*return_iplist)->port = PORT_NONE; + if(is_address) { + /* ignore the port here */ + (*return_iplist)->port = PORT_NONE; - /* if it's in the form of an IP address then get the lib to interpret it */ - if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){ - DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name)); - return False; + /* if it's in the form of an IP address then get the lib to interpret it */ + if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){ + DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name)); + return False; + } + } else { + (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0; } - } else { - (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0; + *return_count = 1; + return True; } - *return_count = 1; - return True; - } - /* Check name cache */ + /* Check name cache */ - if (namecache_fetch(name, name_type, return_iplist, return_count)) { - /* This could be a negative response */ - return (*return_count > 0); - } + if (namecache_fetch(name, name_type, return_iplist, return_count)) { + /* This could be a negative response */ + return (*return_count > 0); + } - /* set the name resolution order */ + /* set the name resolution order */ - if ( strcmp( resolve_order, "NULL") == 0 ) { - DEBUG(8,("internal_resolve_name: all lookups disabled\n")); - return False; - } - - if ( !resolve_order ) - pstrcpy(name_resolve_list, lp_name_resolve_order()); - else - pstrcpy(name_resolve_list, resolve_order); + if ( strcmp( resolve_order, "NULL") == 0 ) { + DEBUG(8,("internal_resolve_name: all lookups disabled\n")); + return False; + } - if ( !name_resolve_list[0] ) - ptr = "host"; - else - ptr = name_resolve_list; + if ( !resolve_order ) { + pstrcpy(name_resolve_list, lp_name_resolve_order()); + } else { + pstrcpy(name_resolve_list, resolve_order); + + if ( !name_resolve_list[0] ) { + ptr = "host"; + } else { + ptr = name_resolve_list; + } - /* iterate through the name resolution backends */ + /* iterate through the name resolution backends */ - while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) { - if((strequal(tok, "host") || strequal(tok, "hosts"))) { - if (resolve_hosts(name, name_type, return_iplist, return_count)) { - result = True; - goto done; - } - } else if(strequal( tok, "ads")) { - /* deal with 0x1c names here. This will result in a - SRV record lookup for _ldap._tcp.<domain> if we - are using 'security = ads' */ - if (resolve_ads(name, name_type, return_iplist, return_count)) { - result = True; - goto done; - } - } else if(strequal( tok, "lmhosts")) { - if (resolve_lmhosts(name, name_type, return_iplist, return_count)) { - result = True; - goto done; - } - } else if(strequal( tok, "wins")) { - /* don't resolve 1D via WINS */ - if (name_type != 0x1D && - resolve_wins(name, name_type, return_iplist, return_count)) { - result = True; - goto done; - } - } else if(strequal( tok, "bcast")) { - if (name_resolve_bcast(name, name_type, return_iplist, return_count)) { - result = True; - goto done; - } - } else { - DEBUG(0,("resolve_name: unknown name switch type %s\n", tok)); - } - } - - /* All of the resolve_* functions above have returned false. */ - - SAFE_FREE(*return_iplist); - *return_count = 0; - - return False; + while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) { + if((strequal(tok, "host") || strequal(tok, "hosts"))) { + if (resolve_hosts(name, name_type, return_iplist, return_count)) { + result = True; + goto done; + } + } else if(strequal( tok, "ads")) { + /* deal with 0x1c names here. This will result in a + SRV record lookup for _ldap._tcp.<domain> if we + are using 'security = ads' */ + if (resolve_ads(name, name_type, return_iplist, return_count)) { + result = True; + goto done; + } + } else if(strequal( tok, "lmhosts")) { + if (resolve_lmhosts(name, name_type, return_iplist, return_count)) { + result = True; + goto done; + } + } else if(strequal( tok, "wins")) { + /* don't resolve 1D via WINS */ + if (name_type != 0x1D && resolve_wins(name, name_type, return_iplist, return_count)) { + result = True; + goto done; + } + } else if(strequal( tok, "bcast")) { + if (name_resolve_bcast(name, name_type, return_iplist, return_count)) { + result = True; + goto done; + } + } else { + DEBUG(0,("resolve_name: unknown name switch type %s\n", tok)); + } + } - done: + /* All of the resolve_* functions above have returned false. */ + + SAFE_FREE(*return_iplist); + *return_count = 0; + + return False; - /* Remove duplicate entries. Some queries, notably #1c (domain - controllers) return the PDC in iplist[0] and then all domain - controllers including the PDC in iplist[1..n]. Iterating over - the iplist when the PDC is down will cause two sets of timeouts. */ + done: - if ( *return_count ) { - *return_count = remove_duplicate_addrs2( *return_iplist, *return_count ); - } + /* Remove duplicate entries. Some queries, notably #1c (domain + controllers) return the PDC in iplist[0] and then all domain + controllers including the PDC in iplist[1..n]. Iterating over + the iplist when the PDC is down will cause two sets of timeouts. */ + + if ( *return_count ) { + *return_count = remove_duplicate_addrs2( *return_iplist, *return_count ); + } - /* Save in name cache */ - if ( DEBUGLEVEL >= 100 ) { - for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++) - DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name, - name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port)); - } + /* Save in name cache */ + if ( DEBUGLEVEL >= 100 ) { + for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++) + DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name, + name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port)); + } - namecache_store(name, name_type, *return_count, *return_iplist); - - /* Display some debugging info */ + namecache_store(name, name_type, *return_count, *return_iplist); - if ( DEBUGLEVEL >= 10 ) { - DEBUG(10, ("internal_resolve_name: returning %d addresses: ", - *return_count)); + /* Display some debugging info */ - for (i = 0; i < *return_count; i++) - DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port)); + if ( DEBUGLEVEL >= 10 ) { + DEBUG(10, ("internal_resolve_name: returning %d addresses: ", *return_count)); - DEBUG(10, ("\n")); - } + for (i = 0; i < *return_count; i++) { + DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port)); + } + DEBUG(10, ("\n")); + } + } - return result; + return result; } /******************************************************** @@ -1218,8 +1215,9 @@ BOOL get_pdc_ip(const char *domain, struct in_addr *ip) /* Look up #1B name */ - if (!internal_resolve_name(domain, 0x1b, &ip_list, &count, lp_name_resolve_order())) + if (!internal_resolve_name(domain, 0x1b, &ip_list, &count, lp_name_resolve_order())) { return False; + } /* if we get more than 1 IP back we have to assume it is a multi-homed PDC and not a mess up */ @@ -1298,16 +1296,17 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list, num_addresses += auto_count; done_auto_lookup = True; DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count)); - } - else + } else { num_addresses++; + } } /* 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 ) + if ( (num_addresses == 0) && !done_auto_lookup ) { return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order); + } /* maybe we just failed? */ @@ -1317,8 +1316,7 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list, } if ( (return_iplist = (struct ip_service *) - malloc(num_addresses * sizeof(struct ip_service))) == NULL ) - { + malloc(num_addresses * sizeof(struct ip_service))) == NULL ) { DEBUG(3,("get_dc_list: malloc fail !\n")); return False; } @@ -1335,6 +1333,13 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list, if ( strequal(name, "*") ) { for ( j=0; j<auto_count; j++ ) { + /* Check for and don't copy any known bad DC IP's. */ + if(!NT_STATUS_IS_OK(check_negative_conn_cache(domain, + inet_ntoa(auto_ip_list[j].ip)))) { + DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n", + inet_ntoa(auto_ip_list[j].ip) )); + continue; + } return_iplist[local_count].ip = auto_ip_list[j].ip; return_iplist[local_count].port = auto_ip_list[j].port; local_count++; @@ -1356,6 +1361,13 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list, /* explicit lookup; resolve_name() will handle names & IP addresses */ if ( resolve_name( name, &name_ip, 0x20 ) ) { + + /* Check for and don't copy any known bad DC IP's. */ + if( !NT_STATUS_IS_OK(check_negative_conn_cache(domain, inet_ntoa(name_ip))) ) { + DEBUG(5,("get_dc_list: negative entry %s removed from DC list\n",name )); + continue; + } + return_iplist[local_count].ip = name_ip; return_iplist[local_count].port = port; local_count++; @@ -1368,8 +1380,9 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list, /* need to remove duplicates in the list if we have any explicit password servers */ - if ( local_count ) + if ( local_count ) { local_count = remove_duplicate_addrs2( return_iplist, local_count ); + } if ( DEBUGLEVEL >= 4 ) { DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count, @@ -1392,8 +1405,9 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list, } /********************************************************************* - small wrapper function to get the DC list and sort it if neccessary + Small wrapper function to get the DC list and sort it if neccessary. *********************************************************************/ + BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL ads_only ) { BOOL ordered; @@ -1401,13 +1415,14 @@ BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *c DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n", (ads_only ? "ads" : lp_name_resolve_order()))); - if ( !get_dc_list(domain, ip_list, count, ads_only, &ordered) ) - return False; + if ( !get_dc_list(domain, ip_list, count, ads_only, &ordered) ) { + return False; + } /* only sort if we don't already have an ordered list */ - if ( !ordered ) + if ( !ordered ) { sort_ip_list2( *ip_list, *count ); + } return True; } - |