r20057: Attempt to fix connect timeouts when connected on
authorJeremy Allison <jra@samba.org>
Wed, 6 Dec 2006 23:14:15 +0000 (23:14 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:16:23 +0000 (12:16 -0500)
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
source/nsswitch/winbindd_cache.c
source/nsswitch/winbindd_cm.c
source/nsswitch/winbindd_util.c

index c18848ac52b94798b58b892be7c99e2235c85f37..4063e6b66b94ed5f59303e2d1a736fe6c9e989ed 100644 (file)
@@ -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 */
index 799eb5855c7f4ba1c1959ebc5ec3eaea3599ed87..7990068ee4e9b50dfcb54fcae7ec9e9b2624c1d0 100644 (file)
@@ -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.
index 3f392c482592e709ee107e1acd7ced4e603a89c1..4044bb71ee296d3b6bda27664a3a008ea02d43ae 100644 (file)
@@ -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
 #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.
index cdffc280873ea3b3e78211f43f29b47396046f1f..98990664e377f0b678794f31fa213f36ad7681e3 100644 (file)
@@ -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);