The Samba-Bugzilla – Attachment 11135 Details for
Bug 11321
net ads testjoin fails to find an off-site DC if the on-site DC is unavailable
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Proposed fix ('git show' output)
fb.patch (text/plain), 8.50 KB, created by
Uri Simchoni
on 2015-06-09 12:02:19 UTC
(
hide
)
Description:
Proposed fix ('git show' output)
Filename:
MIME Type:
Creator:
Uri Simchoni
Created:
2015-06-09 12:02:19 UTC
Size:
8.50 KB
patch
obsolete
>commit 59cad95cacedc601c94081fe96461479068c9bd8 >Author: Uri Simchoni <urisimchoni@gmail.com> >Date: Tue Jun 9 14:30:14 2015 +0300 > > libads: Fix fallback logic when finding a domain controller > > - Fallback first from site-aware lookup to site-less and > only then to netbios (if permitted) > - When falling back to netbios, resolve domain flat name > > Signed-off-by: Uri Simchoni <urisimchoni@gmail.com> > >diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c >index 1c0375d..b55b90c 100644 >--- a/source3/libads/ldap.c >+++ b/source3/libads/ldap.c >@@ -313,22 +313,85 @@ static bool ads_try_connect(ADS_STRUCT *ads, bool gc, > } > > /********************************************************************** >+ resolve a name and perform an "ldap ping" >+**********************************************************************/ >+ >+static NTSTATUS resolve_and_ping(ADS_STRUCT *ads, const char *sitename, >+ const char *resolve_target, bool use_dns, >+ const char *realm) >+{ >+ int count, i = 0; >+ struct ip_service *ip_list; >+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL; >+ bool ok = false; >+ >+ DEBUG(6, ("resolve_and_ping: (cldap) looking for %s '%s'\n", >+ (use_dns ? "realm" : "domain"), resolve_target)); >+ >+ status = get_sorted_dc_list(resolve_target, sitename, &ip_list, &count, >+ use_dns); >+ if (!NT_STATUS_IS_OK(status)) { >+ return status; >+ } >+ >+ /* if we fail this loop, then giveup since all the IP addresses returned >+ * were dead */ >+ for (i = 0; i < count; i++) { >+ char server[INET6_ADDRSTRLEN]; >+ >+ print_sockaddr(server, sizeof(server), &ip_list[i].ss); >+ >+ if (!NT_STATUS_IS_OK( >+ check_negative_conn_cache(resolve_target, server))) >+ continue; >+ >+ if (!use_dns) { >+ /* resolve_target in this case is a workgroup name. We >+ need >+ to ignore any IP addresses in the negative connection >+ cache that match ip addresses returned in the ad >+ realm >+ case.. */ >+ if (realm && *realm && >+ !NT_STATUS_IS_OK( >+ check_negative_conn_cache(realm, server))) { >+ /* Ensure we add the workgroup name for this >+ IP address as negative too. */ >+ add_failed_connection_entry( >+ resolve_target, server, >+ NT_STATUS_UNSUCCESSFUL); >+ continue; >+ } >+ } >+ >+ ok = ads_try_connect(ads, false, &ip_list[i].ss); >+ if (ok) { >+ SAFE_FREE(ip_list); >+ return NT_STATUS_OK; >+ } >+ >+ /* keep track of failures */ >+ add_failed_connection_entry(resolve_target, server, >+ NT_STATUS_UNSUCCESSFUL); >+ } >+ >+ SAFE_FREE(ip_list); >+ >+ return NT_STATUS_NO_LOGON_SERVERS; >+} >+ >+/********************************************************************** > Try to find an AD dc using our internal name resolution routines >- Try the realm first and then then workgroup name if netbios is not >+ Try the realm first and then then workgroup name if netbios is not > disabled > **********************************************************************/ > > static NTSTATUS ads_find_dc(ADS_STRUCT *ads) > { >- const char *c_domain; >+ const char *c_domain = ""; > const char *c_realm; >- int count, i=0; >- struct ip_service *ip_list; >- const char *realm; >- const char *domain; >- bool got_realm = False; > bool use_own_domain = False; >- char *sitename; >+ char *sitename = NULL; > NTSTATUS status = NT_STATUS_UNSUCCESSFUL; > bool ok = false; > >@@ -337,7 +400,10 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads) > /* realm */ > c_realm = ads->server.realm; > >- if ( !c_realm || !*c_realm ) { >+ if (!c_realm) >+ c_realm = ""; >+ >+ if (!*c_realm) { > /* special case where no realm and no workgroup means our own */ > if ( !ads->server.workgroup || !*ads->server.workgroup ) { > use_own_domain = True; >@@ -345,35 +411,31 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads) > } > } > >- if (c_realm && *c_realm) >- got_realm = True; >+ if (!c_realm) { >+ c_realm = ""; >+ } > >- /* we need to try once with the realm name and fallback to the >- netbios domain name if we fail (if netbios has not been disabled */ >+ if (!lp_disable_netbios()) { >+ if (use_own_domain) { >+ c_domain = lp_workgroup(); >+ } else { >+ c_domain = ads->server.workgroup; >+ if (!*c_realm && (!c_domain || !*c_domain)) { >+ c_domain = lp_workgroup(); >+ } >+ } > >- if ( !got_realm && !lp_disable_netbios() ) { >- c_realm = ads->server.workgroup; >- if (!c_realm || !*c_realm) { >- if ( use_own_domain ) >- c_realm = lp_workgroup(); >+ if (!c_domain) { >+ c_domain = ""; > } > } > >- if ( !c_realm || !*c_realm ) { >+ if (!*c_realm && !*c_domain) { > DEBUG(1, ("ads_find_dc: no realm or workgroup! Don't know " > "what to do\n")); > return NT_STATUS_INVALID_PARAMETER; /* rather need MISSING_PARAMETER ... */ > } > >- if ( use_own_domain ) { >- c_domain = lp_workgroup(); >- } else { >- c_domain = ads->server.workgroup; >- } >- >- realm = c_realm; >- domain = c_domain; >- > /* > * In case of LDAP we use get_dc_name() as that > * creates the custom krb5.conf file >@@ -382,10 +444,11 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads) > fstring srv_name; > struct sockaddr_storage ip_out; > >- DEBUG(6,("ads_find_dc: (ldap) looking for %s '%s'\n", >- (got_realm ? "realm" : "domain"), realm)); >+ DEBUG(6, ("ads_find_dc: (ldap) looking for realm '%s'" >+ " and falling back to domain '%s'\n", >+ c_realm, c_domain)); > >- ok = get_dc_name(domain, realm, srv_name, &ip_out); >+ ok = get_dc_name(c_domain, c_realm, srv_name, &ip_out); > if (ok) { > /* > * we call ads_try_connect() to fill in the >@@ -400,80 +463,35 @@ static NTSTATUS ads_find_dc(ADS_STRUCT *ads) > return NT_STATUS_NO_LOGON_SERVERS; > } > >- sitename = sitename_fetch(talloc_tos(), realm); >- >- again: >- >- DEBUG(6,("ads_find_dc: (cldap) looking for %s '%s'\n", >- (got_realm ? "realm" : "domain"), realm)); >- >- status = get_sorted_dc_list(realm, sitename, &ip_list, &count, got_realm); >- if (!NT_STATUS_IS_OK(status)) { >- /* fall back to netbios if we can */ >- if ( got_realm && !lp_disable_netbios() ) { >- got_realm = False; >- goto again; >+ if (*c_realm) { >+ sitename = sitename_fetch(talloc_tos(), c_realm); >+ status = resolve_and_ping(ads, sitename, c_realm, true, c_realm); >+ /* In case we failed to contact one of our closest DC on our >+ * site we >+ * need to try to find another DC, retry with a site-less SRV >+ * DNS query >+ * - Guenther */ >+ >+ if (!NT_STATUS_IS_OK(status) && sitename) { >+ DEBUG(1, ("ads_find_dc: failed to find a valid DC on " >+ "our site (%s), " >+ "trying to find another DC\n", >+ sitename)); >+ namecache_delete(c_realm, 0x1C); >+ status = >+ resolve_and_ping(ads, NULL, c_realm, true, c_realm); > } > > TALLOC_FREE(sitename); >- return status; >- } >- >- /* if we fail this loop, then giveup since all the IP addresses returned were dead */ >- for ( i=0; i<count; i++ ) { >- char server[INET6_ADDRSTRLEN]; >- >- print_sockaddr(server, sizeof(server), &ip_list[i].ss); >- >- if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) ) >- continue; >- >- if (!got_realm) { >- /* realm in this case is a workgroup name. We need >- to ignore any IP addresses in the negative connection >- cache that match ip addresses returned in the ad realm >- case. It sucks that I have to reproduce the logic above... */ >- c_realm = ads->server.realm; >- if ( !c_realm || !*c_realm ) { >- if ( !ads->server.workgroup || !*ads->server.workgroup ) { >- c_realm = lp_realm(); >- } >- } >- if (c_realm && *c_realm && >- !NT_STATUS_IS_OK(check_negative_conn_cache(c_realm, server))) { >- /* Ensure we add the workgroup name for this >- IP address as negative too. */ >- add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL ); >- continue; >- } >- } >- >- ok = ads_try_connect(ads, false, &ip_list[i].ss); >- if (ok) { >- SAFE_FREE(ip_list); >- TALLOC_FREE(sitename); >- return NT_STATUS_OK; >- } >- >- /* keep track of failures */ >- add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL ); > } > >- SAFE_FREE(ip_list); >- >- /* In case we failed to contact one of our closest DC on our site we >- * need to try to find another DC, retry with a site-less SRV DNS query >- * - Guenther */ >- >- if (sitename) { >- DEBUG(1,("ads_find_dc: failed to find a valid DC on our site (%s), " >- "trying to find another DC\n", sitename)); >- TALLOC_FREE(sitename); >- namecache_delete(realm, 0x1C); >- goto again; >+ /* try netbios as fallback - if permitted, >+ or if configuration specifically requests it */ >+ if (!NT_STATUS_IS_OK(status) && *c_domain) { >+ status = resolve_and_ping(ads, NULL, c_domain, false, c_realm); > } > >- return NT_STATUS_NO_LOGON_SERVERS; >+ return status; > } > > /*********************************************************************
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 11321
: 11135