summaryrefslogtreecommitdiffstats
path: root/source3/winbindd/winbindd_async.c
diff options
context:
space:
mode:
authorSteven Danneman <steven.danneman@isilon.com>2008-05-21 20:16:33 -0700
committerGerald W. Carter <jerry@samba.org>2008-05-22 13:55:57 -0500
commit96653e1ff7551dd9214dc14eed4029e2214598f8 (patch)
treeec0f71e07ec90bf6c1101ea779039e5c1c3cb3e1 /source3/winbindd/winbindd_async.c
parentf6a70e02498ba935f9ab6b9691c024f9a9bfe08e (diff)
downloadsamba-96653e1ff7551dd9214dc14eed4029e2214598f8.tar.gz
samba-96653e1ff7551dd9214dc14eed4029e2214598f8.tar.xz
samba-96653e1ff7551dd9214dc14eed4029e2214598f8.zip
Make WINBINDD_LIST_GROUPS handler asynchronous.
Previously WINBINDD_LIST_GROUPS requests (ex: wbinfo -g) were handled by the winbindd parent process in a sequential fashion. This patch, delegates the work to the winbindd children so that the request is handled much faster in large domain topologies, and doesn't block the parent from receiving new requests. The core group enumeration and conversion that was handled in winbindd_list_groups() has been moved into winbindd_dual_list_groups() to be done by the child. The parent winbindd_list_groups() simply calls each of the children asynchronously. listgroups_recv() aggregates the final group list that will be returned to the client and tracks how many of the children have returned their lists. The domain name of the child is passed back through the callbacks to be used in debugging messages. There are also several fixes to typos in various comments. (This used to be commit 037b9689d9042a398cb91e4628a82fcdfa913c21)
Diffstat (limited to 'source3/winbindd/winbindd_async.c')
-rw-r--r--source3/winbindd/winbindd_async.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c
index 2ff5ef230d3..635bc6b244f 100644
--- a/source3/winbindd/winbindd_async.c
+++ b/source3/winbindd/winbindd_async.c
@@ -453,6 +453,97 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
return WINBINDD_OK;
}
+/* This is the first callback after enumerating groups from a domain */
+static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success,
+ struct winbindd_response *response,
+ void *c, void *private_data)
+{
+ void (*cont)(void *priv, bool succ, fstring dom_name, char *data) =
+ (void (*)(void *, bool, fstring, char*))c;
+
+ if (!success || response->result != WINBINDD_OK) {
+ DEBUG(5, ("list_groups() failed!\n"));
+ cont(private_data, False, response->data.name.dom_name, NULL);
+ return;
+ }
+
+ cont(private_data, True, response->data.name.dom_name,
+ response->extra_data.data);
+
+ SAFE_FREE(response->extra_data.data);
+}
+
+/* Request the name of all groups in a single domain */
+void winbindd_listgroups_async(TALLOC_CTX *mem_ctx,
+ struct winbindd_domain *domain,
+ void (*cont)(void *private_data, bool success,
+ fstring dom_name, char* extra_data),
+ void *private_data)
+{
+ struct winbindd_request request;
+
+ ZERO_STRUCT(request);
+ request.cmd = WINBINDD_LIST_GROUPS;
+
+ do_async_domain(mem_ctx, domain, &request, listgroups_recv,
+ (void *)cont, private_data);
+}
+
+enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ struct getent_state groups = {};
+ char *extra_data = NULL;
+ unsigned int extra_data_len = 0, i;
+
+ /* Must copy domain into response first for bookeeping in parent */
+ fstrcpy(state->response.data.name.dom_name, domain->name);
+ fstrcpy(groups.domain_name, domain->name);
+
+ /* Get list of sam groups */
+ if (!get_sam_group_entries(&groups)) {
+ /* this domain is empty or in an error state */
+ return WINBINDD_ERROR;
+ }
+
+ /* Allocate some memory for extra data. Note that we limit
+ account names to sizeof(fstring) = 256 characters.
+ +1 for the ',' between group names */
+ extra_data = (char *)SMB_REALLOC(extra_data,
+ (sizeof(fstring) + 1) * groups.num_sam_entries);
+
+ if (!extra_data) {
+ DEBUG(0,("failed to enlarge buffer!\n"));
+ SAFE_FREE(groups.sam_entries);
+ return WINBINDD_ERROR;
+ }
+
+ /* Pack group list into extra data fields */
+ for (i = 0; i < groups.num_sam_entries; i++) {
+ char *group_name = ((struct acct_info *)
+ groups.sam_entries)[i].acct_name;
+ fstring name;
+
+ fill_domain_username(name, domain->name, group_name, True);
+ /* Append to extra data */
+ memcpy(&extra_data[extra_data_len], name, strlen(name));
+ extra_data_len += strlen(name);
+ extra_data[extra_data_len++] = ',';
+ }
+
+ SAFE_FREE(groups.sam_entries);
+
+ /* Assign extra_data fields in response structure */
+ if (extra_data) {
+ /* remove trailing ',' */
+ extra_data[extra_data_len - 1] = '\0';
+ state->response.extra_data.data = extra_data;
+ state->response.length += extra_data_len;
+ }
+
+ return WINBINDD_OK;
+}
+
bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
size_t num_sids, char **result, ssize_t *len)
{