diff options
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/winbindd_cache.c | 30 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_cm.c | 31 |
2 files changed, 56 insertions, 5 deletions
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index a38a0fb16d..e0860cd695 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -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); diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 9a34293cdb..381cdaaa20 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -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(); +} |