From 369c9e4138b93f7cfb6680f0beb541f58554e856 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 6 Dec 2006 23:14:15 +0000 Subject: [PATCH] r20057: Attempt to fix connect timeouts when connected on a network but not one on which any home DC's can be found (hotel network problem). Still testing but this is getting close. Jeremy. --- source/nsswitch/winbindd.h | 1 + source/nsswitch/winbindd_cache.c | 5 ++-- source/nsswitch/winbindd_cm.c | 61 +++++++++++++++++++++++++++++++++++----- source/nsswitch/winbindd_util.c | 9 +----- 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h index c18848ac52b..4063e6b66b9 100644 --- a/source/nsswitch/winbindd.h +++ b/source/nsswitch/winbindd.h @@ -203,6 +203,7 @@ struct winbindd_domain { /* Callback we use to try put us back online. */ + uint32 check_online_timeout; struct timed_event *check_online_event; /* Linked list info */ diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c index 799eb5855c7..7990068ee4e 100644 --- a/source/nsswitch/winbindd_cache.c +++ b/source/nsswitch/winbindd_cache.c @@ -87,10 +87,11 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) struct winbindd_domain *our_domain = domain; #endif - /* we have to know what type of domain we are dealing with first */ + /* We have to know what type of domain we are dealing with first. */ - if ( !domain->initialized ) + if ( !domain->initialized ) { init_dc_connection( domain ); + } /* OK. listen up becasue I'm only going to say this once. diff --git a/source/nsswitch/winbindd_cm.c b/source/nsswitch/winbindd_cm.c index 3f392c48259..4044bb71ee2 100644 --- a/source/nsswitch/winbindd_cm.c +++ b/source/nsswitch/winbindd_cm.c @@ -7,6 +7,7 @@ Copyright (C) Andrew Bartlett 2002 Copyright (C) Gerald (Jerry) Carter 2003-2005. Copyright (C) Volker Lendecke 2004-2005 + Copyright (C) Jeremy Allison 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -64,9 +65,29 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain); static void set_dc_type_and_flags( struct winbindd_domain *domain ); /**************************************************************** + If we're still offline, exponentially increase the timeout check. +****************************************************************/ + +static void calc_new_online_timeout(struct winbindd_domain *domain) +{ + if (domain->startup) { + domain->check_online_timeout = 10; + } else if (domain->check_online_timeout == 0) { + domain->check_online_timeout = lp_winbind_cache_time(); + } else { + uint32 new_to = (domain->check_online_timeout * domain->check_online_timeout); + if (new_to < domain->check_online_timeout) { + new_to = 0x7FFFFFFF; + } + domain->check_online_timeout = new_to; + } +} + +/**************************************************************** Handler triggered if we're offline to try and detect a DC. ****************************************************************/ @@ -104,8 +125,10 @@ static void check_domain_online_handler(struct timed_event *te, /* This call takes care of setting the online flag to true if we connected, or re-adding - the offline handler if false. */ - init_dc_connection(domain); + the offline handler if false. Bypasses online + check so always does network calls. */ + + init_dc_connection_network(domain); } /**************************************************************** @@ -130,6 +153,11 @@ void set_domain_offline(struct winbindd_domain *domain) domain->online = False; + /* Offline domains are always initialized. They're + re-initialized when they go back online. */ + + domain->initialized = True; + /* We only add the timeout handler that checks and allows us to go back online when we've not been told to remain offline. */ @@ -143,10 +171,12 @@ void set_domain_offline(struct winbindd_domain *domain) /* If we're in statup mode, check again in 10 seconds, not in lp_winbind_cache_time() seconds (which is 5 mins by default). */ + if (domain->check_online_timeout == 0) { + calc_new_online_timeout(domain); + } + domain->check_online_event = add_timed_event( NULL, - domain->startup ? - timeval_current_ofs(10,0) : - timeval_current_ofs(lp_winbind_cache_time(), 0), + timeval_current_ofs(domain->check_online_timeout,0), "check_domain_online_handler", check_domain_online_handler, domain); @@ -207,6 +237,12 @@ static void set_domain_online(struct winbindd_domain *domain) } } + /* Ensure we have no online timeout checks. */ + domain->check_online_timeout = 0; + if (domain->check_online_event) { + TALLOC_FREE(domain->check_online_event); + } + domain->online = True; } @@ -1203,9 +1239,10 @@ static BOOL connection_ok(struct winbindd_domain *domain) return True; } -/* Initialize a new connection up to the RPC BIND. */ +/* Initialize a new connection up to the RPC BIND. + Bypass online status check so always does network calls. */ -NTSTATUS init_dc_connection(struct winbindd_domain *domain) +static NTSTATUS init_dc_connection_network(struct winbindd_domain *domain) { NTSTATUS result; @@ -1233,6 +1270,16 @@ NTSTATUS init_dc_connection(struct winbindd_domain *domain) return result; } +NTSTATUS init_dc_connection(struct winbindd_domain *domain) +{ + if (domain->initialized && !domain->online) { + /* We check for online status elsewhere. */ + return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + } + + return init_dc_connection_network(domain); +} + /****************************************************************************** We can 'sense' certain things about the DC by it's replies to certain questions. diff --git a/source/nsswitch/winbindd_util.c b/source/nsswitch/winbindd_util.c index cdffc280873..98990664e37 100644 --- a/source/nsswitch/winbindd_util.c +++ b/source/nsswitch/winbindd_util.c @@ -163,6 +163,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const domain->last_seq_check = 0; domain->initialized = False; domain->online = is_internal_domain(sid); + domain->check_online_timeout = 0; if (sid) { sid_copy(&domain->sid, sid); } @@ -462,7 +463,6 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai init_dc_connection(domain); -#if 1 if (!domain->initialized) { /* If we return error here we can't do any cached authentication, but we may be in disconnected mode and can't initialize correctly. @@ -472,13 +472,6 @@ enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domai DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization " "online = %d\n", domain->name, (int)domain->online )); } -#else - if (!domain->initialized) { - DEBUG(1, ("Could not initialize domain %s\n", - state->request.domain_name)); - return WINBINDD_ERROR; - } -#endif fstrcpy(state->response.data.domain_info.name, domain->name); fstrcpy(state->response.data.domain_info.alt_name, domain->alt_name); -- 2.11.4.GIT