diff options
author | Gerald Carter <jerry@samba.org> | 2006-02-03 21:19:24 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 11:06:23 -0500 |
commit | 855e02f1649992f05b685be96dfff4a9140170e9 (patch) | |
tree | f3224a28b08d3d569f929039e0bd7313ab81dbd9 /source3/libsmb | |
parent | 989c9311c5c155a8bea2b7921edf5eeb36c54ead (diff) | |
download | samba-855e02f1649992f05b685be96dfff4a9140170e9.tar.gz samba-855e02f1649992f05b685be96dfff4a9140170e9.tar.bz2 samba-855e02f1649992f05b685be96dfff4a9140170e9.zip |
r13310: first round of server affinity patches for winbindd & net ads join
(This used to be commit 6c3480f9aecc061660ad5c06347b8f1d3e11a330)
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/cliconnect.c | 12 | ||||
-rw-r--r-- | source3/libsmb/namequery.c | 323 | ||||
-rw-r--r-- | source3/libsmb/namequery_dc.c | 28 |
3 files changed, 217 insertions, 146 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index ac7d1b1650..7c15c8d19f 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -865,14 +865,16 @@ BOOL cli_session_setup(struct cli_state *cli, DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status))); return False; } - return True; + } else { + /* otherwise do a NT1 style session setup */ + if ( !cli_session_setup_nt1(cli, user, pass, passlen, ntpass, ntpasslen, workgroup) ) { + DEBUG(3,("cli_session_setup: NT1 session setup failed!\n")); + return False; + } } - /* otherwise do a NT1 style session setup */ + return True; - return cli_session_setup_nt1(cli, user, - pass, passlen, ntpass, ntpasslen, - workgroup); } /**************************************************************************** diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 28b89db908..0986e7f29a 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -24,6 +24,94 @@ /* nmbd.c sets this to True. */ BOOL global_in_nmbd = False; + +/**************************** + * SERVER AFFINITY ROUTINES * + ****************************/ + + /* Server affinity is the concept of preferring the last domain + controller with whom you had a successful conversation */ + +/**************************************************************************** +****************************************************************************/ +#define SAFKEY_FMT "SAF/DOMAIN/%s" +#define SAF_TTL 900 + +static char *saf_key(const char *domain) +{ + char *keystr; + + asprintf( &keystr, SAFKEY_FMT, strupper_static(domain) ); + + return keystr; +} + +/**************************************************************************** +****************************************************************************/ + +BOOL saf_store( const char *domain, const char *servername ) +{ + char *key; + time_t expire; + BOOL ret = False; + + if ( !domain || !servername ) { + DEBUG(2,("saf_store: Refusing to store empty domain or servername!\n")); + return False; + } + + if ( !gencache_init() ) + return False; + + key = saf_key( domain ); + expire = time( NULL ) + SAF_TTL; + + + DEBUG(10,("saf_store: domain = [%s], server = [%s], expire = [%d]\n", + domain, servername, expire )); + + ret = gencache_set( key, servername, expire ); + + SAFE_FREE( key ); + + return ret; +} + +/**************************************************************************** +****************************************************************************/ + +char *saf_fetch( const char *domain ) +{ + char *server = NULL; + time_t timeout; + BOOL ret = False; + char *key = NULL; + + if ( !domain ) { + DEBUG(2,("saf_fetch: Empty domain name!\n")); + return NULL; + } + + if ( !gencache_init() ) + return False; + + key = saf_key( domain ); + + ret = gencache_get( key, &server, &timeout ); + + SAFE_FREE( key ); + + if ( !ret ) { + DEBUG(5,("saf_fetch: failed to find server for \"%s\" domain\n", domain )); + } else { + DEBUG(5,("saf_fetch: Returning \"%s\" for \"%s\" domain\n", + server, domain )); + } + + return server; +} + + /**************************************************************************** Generate a random trn_id. ****************************************************************************/ @@ -1261,6 +1349,18 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list, int *count, BOOL ads_only, int *ordered) { fstring resolve_order; + char *saf_servername; + pstring pserver; + const char *p; + char *port_str; + int port; + fstring name; + int num_addresses = 0; + int local_count, i, j; + struct ip_service *return_iplist = NULL; + struct ip_service *auto_ip_list = NULL; + BOOL done_auto_lookup = False; + int auto_count = 0; /* if we are restricted to solely using DNS for looking up a domain controller, make sure that host lookups @@ -1277,148 +1377,145 @@ static BOOL get_dc_list(const char *domain, struct ip_service **ip_list, fstrcpy( resolve_order, "NULL" ); } - *ordered = False; - - /* If it's our domain then use the 'password server' parameter. */ - + + /* fetch the server we have affinity for. Add the + 'password server' list to a search for our domain controllers */ + + saf_servername = saf_fetch( domain ); + if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) { - const char *p; - char *pserver = lp_passwordserver(); /* UNIX charset. */ - char *port_str; - int port; - fstring name; - int num_addresses = 0; - int local_count, i, j; - struct ip_service *return_iplist = NULL; - struct ip_service *auto_ip_list = NULL; - BOOL done_auto_lookup = False; - int auto_count = 0; - + pstr_sprintf( pserver, "%s, %s", + saf_servername ? saf_servername : "", + lp_passwordserver() ); + } else { + pstr_sprintf( pserver, "%s, *", + saf_servername ? saf_servername : "" ); + } - if (!*pserver) - return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order); + SAFE_FREE( saf_servername ); - 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, "*")) { - if ( internal_resolve_name(domain, 0x1C, &auto_ip_list, &auto_count, resolve_order) ) - num_addresses += auto_count; - done_auto_lookup = True; - DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count)); - } else { - num_addresses++; - } + /* if we are starting from scratch, just lookup DOMAIN<0x1c> */ + + if ( !*pserver ) { + DEBUG(10,("get_dc_list: no preferred domain controllers.\n")); + return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order); + } + + DEBUG(3,("get_dc_list: preferred server list: \"%s\"\n", 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 + */ + + p = pserver; + while (next_token(&p,name,LIST_SEP,sizeof(name))) { + if (strequal(name, "*")) { + if ( internal_resolve_name(domain, 0x1C, &auto_ip_list, &auto_count, resolve_order) ) + num_addresses += auto_count; + done_auto_lookup = True; + DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count)); + } else { + num_addresses++; } + } - /* if we have no addresses and haven't done the auto lookup, then - just return the list of DC's */ + /* if we have no addresses and haven't done the auto lookup, then + just return the list of DC's. Or maybe we just failed. */ - if ( (num_addresses == 0) && !done_auto_lookup ) { + if ( (num_addresses == 0) ) { + if ( !done_auto_lookup ) { return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order); - } - - /* maybe we just failed? */ - - if ( num_addresses == 0 ) { - DEBUG(4,("get_dc_list: no servers found\n")); - return False; - } - - if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) { - DEBUG(3,("get_dc_list: malloc fail !\n")); + } else { + DEBUG(4,("get_dc_list: no servers found\n")); return False; } + } + + if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) { + DEBUG(3,("get_dc_list: malloc fail !\n")); + return False; + } - p = pserver; - local_count = 0; + p = pserver; + local_count = 0; - /* fill in the return list now with real IP's */ + /* 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; + while ( (local_count<num_addresses) && next_token(&p,name,LIST_SEP,sizeof(name)) ) { + struct in_addr name_ip; - /* copy any addersses from the auto lookup */ + /* copy any addersses from the auto lookup */ - 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++; + 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; } - continue; + return_iplist[local_count].ip = auto_ip_list[j].ip; + return_iplist[local_count].port = auto_ip_list[j].port; + local_count++; } + continue; + } - /* added support for address:port syntax for ads (not that I think - anyone will ever run the LDAP server in an AD domain on something - other than port 389 */ + /* added support for address:port syntax for ads (not that I think + anyone will ever run the LDAP server in an AD domain on something + other than port 389 */ - port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE; - if ( (port_str=strchr(name, ':')) != NULL ) { - *port_str = '\0'; - port_str++; - port = atoi( port_str ); - } - - /* explicit lookup; resolve_name() will handle names & IP addresses */ - if ( resolve_name( name, &name_ip, 0x20 ) ) { + port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE; + if ( (port_str=strchr(name, ':')) != NULL ) { + *port_str = '\0'; + port_str++; + port = atoi( port_str ); + } - /* 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; - } + /* explicit lookup; resolve_name() will handle names & IP addresses */ + if ( resolve_name( name, &name_ip, 0x20 ) ) { - return_iplist[local_count].ip = name_ip; - return_iplist[local_count].port = port; - local_count++; - *ordered = True; + /* 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++; + *ordered = True; } + } - SAFE_FREE(auto_ip_list); + SAFE_FREE(auto_ip_list); - /* need to remove duplicates in the list if we have any - explicit password servers */ - - if ( local_count ) { - local_count = remove_duplicate_addrs2( return_iplist, local_count ); - } + /* need to remove duplicates in the list if we have any + explicit password servers */ + + 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, - *ordered ? "":"un")); - DEBUG(4,("get_dc_list: ")); - for ( i=0; i<local_count; i++ ) - DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port )); - DEBUGADD(4,("\n")); - } + if ( DEBUGLEVEL >= 4 ) { + DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count, + *ordered ? "":"un")); + DEBUG(4,("get_dc_list: ")); + for ( i=0; i<local_count; i++ ) + DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port )); + DEBUGADD(4,("\n")); + } - *ip_list = return_iplist; - *count = local_count; + *ip_list = return_iplist; + *count = local_count; - return (*count != 0); - } - - DEBUG(10,("get_dc_list: defaulting to internal auto lookup for domain %s\n", domain)); - - return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order); + return (*count != 0); } /********************************************************************* diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c index 0c9f19313c..b9a593bf2a 100644 --- a/source3/libsmb/namequery_dc.c +++ b/source3/libsmb/namequery_dc.c @@ -75,31 +75,10 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip struct ip_service *ip_list = NULL; struct in_addr dc_ip, exclude_ip; int count, i; - BOOL use_pdc_only; NTSTATUS result; zero_ip(&exclude_ip); - use_pdc_only = must_use_pdc(domain); - - /* Lookup domain controller name */ - - if ( use_pdc_only && get_pdc_ip(domain, &dc_ip) ) - { - DEBUG(10,("rpc_dc_name: Atempting to lookup PDC to avoid sam sync delays\n")); - - /* check the connection cache and perform the node status - lookup only if the IP is not found to be bad */ - - if (name_status_find(domain, 0x1b, 0x20, dc_ip, srv_name) ) { - result = check_negative_conn_cache( domain, srv_name ); - if ( NT_STATUS_IS_OK(result) ) - goto done; - } - /* Didn't get name, remember not to talk to this DC. */ - exclude_ip = dc_ip; - } - /* get a list of all domain controllers */ if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) { @@ -109,13 +88,6 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip /* Remove the entry we've already failed with (should be the PDC). */ - if ( use_pdc_only ) { - for (i = 0; i < count; i++) { - if (ip_equal( exclude_ip, ip_list[i].ip)) - zero_ip(&ip_list[i].ip); - } - } - for (i = 0; i < count; i++) { if (is_zero_ip(ip_list[i].ip)) continue; |