Add in rety loop for query_user_list (from APP_HEAD). Deals with a bug
authorJeremy Allison <jra@samba.org>
Tue, 10 Jun 2003 22:11:30 +0000 (22:11 +0000)
committerJeremy Allison <jra@samba.org>
Tue, 10 Jun 2003 22:11:30 +0000 (22:11 +0000)
using MSRPC backend and should be safe with ldap backend.
Jeremy.
(This used to be commit 67535329a2df8986c2d1d85e25cd5c558ee61405)

source3/nsswitch/winbindd_cache.c
source3/nsswitch/winbindd_cm.c

index a38a0fb16d4a40742c48bac6c9f2d45996967eb6..e0860cd695bb76e6add6b2b1a7d7e92c268795e2 100644 (file)
@@ -634,7 +634,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
        struct winbind_cache *cache = get_cache(domain);
        struct cache_entry *centry = NULL;
        NTSTATUS status;
-       unsigned int i;
+       unsigned int i, retry;
 
        if (!cache->tdb)
                goto do_query;
@@ -675,10 +675,29 @@ do_query:
                return NT_STATUS_SERVER_DISABLED;
        }
 
-       DEBUG(10,("query_user_list: [Cached] - doing backend query for list for domain %s\n",
-               domain->name ));
+       /* Put the query_user_list() in a retry loop.  There appears to be
+        * some bug either with Windows 2000 or Samba's handling of large
+        * rpc replies.  This manifests itself as sudden disconnection
+        * at a random point in the enumeration of a large (60k) user list.
+        * The retry loop simply tries the operation again. )-:  It's not
+        * pretty but an acceptable workaround until we work out what the
+        * real problem is. */
+
+       retry = 0;
+       do {
+
+               DEBUG(10,("query_user_list: [Cached] - doing backend query for list for domain %s\n",
+                       domain->name ));
+
+               status = domain->backend->query_user_list(domain, mem_ctx, num_entries, info);
+               if (!NT_STATUS_IS_OK(status))
+                       DEBUG(3, ("query_user_list: returned 0x%08x, retrying\n", NT_STATUS_V(status)));
+                       if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL)) {
+                               DEBUG(3, ("query_user_list: flushing connection cache\n"));
+                               winbindd_cm_flush();
+                       }
 
-       status = domain->backend->query_user_list(domain, mem_ctx, num_entries, info);
+       } while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) && (retry++ < 5));
 
        /* and save it */
        refresh_sequence_number(domain, False);
@@ -878,7 +897,8 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
        fstring uname;
        DOM_SID *sid2;
 
-       if (!cache->tdb) goto do_query;
+       if (!cache->tdb)
+               goto do_query;
 
        fstrcpy(uname, name);
        strupper(uname);
index 9a34293cdb0cc9fb72e90a4ce426d05d16bcf21a..381cdaaa20f258bfe7390830ca5b4644e566075e 100644 (file)
@@ -659,3 +659,34 @@ void winbindd_cm_status(void)
        else
                DEBUG(0, ("\tNo active connections\n"));
 }
+
+/* Close all cached connections */
+
+void winbindd_cm_flush(void)
+{
+       struct winbindd_cm_conn *conn, tmp;
+
+       /* Flush connection cache */
+
+       for (conn = cm_conns; conn; conn = conn->next) {
+
+               if (!connection_ok(conn))
+                       continue;
+
+               DEBUG(10, ("Closing connection to %s on %s\n",
+                       conn->pipe_name, conn->controller));
+
+               if (conn->cli)
+                       cli_shutdown(conn->cli);
+
+               tmp.next = conn->next;
+
+               DLIST_REMOVE(cm_conns, conn);
+               SAFE_FREE(conn);
+               conn = &tmp;
+       }
+
+       /* Flush failed connection cache */
+
+       flush_negative_conn_cache();
+}