summaryrefslogtreecommitdiffstats
path: root/source3/winbindd/winbindd_async.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2008-06-26 14:02:39 -0700
committerJeremy Allison <jra@samba.org>2008-06-26 14:02:39 -0700
commit120c09b125f656d6d03b979560f3ef6652217691 (patch)
treec7f5db8defa25852acacb3e1eebaaba4b2bc3e04 /source3/winbindd/winbindd_async.c
parent23cafd02d3222b910dbc30a7eab20ebdcc81ab33 (diff)
downloadsamba-120c09b125f656d6d03b979560f3ef6652217691.tar.gz
samba-120c09b125f656d6d03b979560f3ef6652217691.tar.xz
samba-120c09b125f656d6d03b979560f3ef6652217691.zip
From Steve Danneman @ Isilon.
Attached is the companion patch to (037b9689d9042a398cb91e4628a82fcdfa913c21), which made handling of WINBINDD_LIST_GROUPS asynchronous. Because most all of the list_groups code was reusable, I abstracted it, and implemented both list_groups and list_users on top of it. On my large test domain a "wbinfo -u" call went from 70 seconds to 30 seconds with this patch. Plus, the parent process is no longer blocked from receiving new requests during that time. Steven Danneman | Software Development Engineer Isilon Systems P +1-206-315-7500 F +1-206-315-7501 www.isilon.com (This used to be commit 5188f2861137ff06d5399561d55d7d00c3a08644)
Diffstat (limited to 'source3/winbindd/winbindd_async.c')
-rw-r--r--source3/winbindd/winbindd_async.c85
1 files changed, 75 insertions, 10 deletions
diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c
index bc0f9d836b4..e47666462e2 100644
--- a/source3/winbindd/winbindd_async.c
+++ b/source3/winbindd/winbindd_async.c
@@ -453,8 +453,8 @@ 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,
+/* This is the first callback after enumerating users/groups from a domain */
+static void listent_recv(TALLOC_CTX *mem_ctx, bool success,
struct winbindd_response *response,
void *c, void *private_data)
{
@@ -462,7 +462,7 @@ static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success,
(void (*)(void *, bool, fstring, char*))c;
if (!success || response->result != WINBINDD_OK) {
- DEBUG(5, ("list_groups() failed!\n"));
+ DEBUG(5, ("list_ent() failed!\n"));
cont(private_data, False, response->data.name.dom_name, NULL);
return;
}
@@ -473,30 +473,95 @@ static void listgroups_recv(TALLOC_CTX *mem_ctx, bool success,
SAFE_FREE(response->extra_data.data);
}
-/* Request the name of all groups in a single domain */
-void winbindd_listgroups_async(TALLOC_CTX *mem_ctx,
+/* Request the name of all users/groups in a single domain */
+void winbindd_listent_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)
+ void *private_data, enum ent_type type)
{
struct winbindd_request request;
ZERO_STRUCT(request);
- request.cmd = WINBINDD_LIST_GROUPS;
+ if (type == LIST_USERS)
+ request.cmd = WINBINDD_LIST_USERS;
+ else if (type == LIST_GROUPS)
+ request.cmd = WINBINDD_LIST_GROUPS;
- do_async_domain(mem_ctx, domain, &request, listgroups_recv,
+ do_async_domain(mem_ctx, domain, &request, listent_recv,
(void *)cont, private_data);
}
+
+enum winbindd_result winbindd_dual_list_users(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ WINBIND_USERINFO *info;
+ NTSTATUS status;
+ struct winbindd_methods *methods;
+ uint32 num_entries = 0;
+ char *extra_data = NULL;
+ uint32_t extra_data_len = 0, i;
+
+ /* Must copy domain into response first for debugging in parent */
+ fstrcpy(state->response.data.name.dom_name, domain->name);
+
+ /* Query user info */
+ methods = domain->methods;
+ status = methods->query_user_list(domain, state->mem_ctx,
+ &num_entries, &info);
+
+ if (!NT_STATUS_IS_OK(status))
+ return WINBINDD_ERROR;
+
+ if (num_entries == 0)
+ return WINBINDD_OK;
+
+ /* 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) * num_entries);
+
+ if (!extra_data) {
+ DEBUG(0,("failed to enlarge buffer!\n"));
+ return WINBINDD_ERROR;
+ }
+
+ /* Pack user list into extra data fields */
+ for (i = 0; i < num_entries; i++) {
+ fstring acct_name, name;
+
+ if (info[i].acct_name == NULL)
+ fstrcpy(acct_name, "");
+ else
+ fstrcpy(acct_name, info[i].acct_name);
+
+ fill_domain_username(name, domain->name, acct_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++] = ',';
+ }
+
+ /* 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;
+}
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;
+ uint32_t extra_data_len = 0, i;
- /* Must copy domain into response first for bookeeping in parent */
+ /* Must copy domain into response first for debugging in parent */
fstrcpy(state->response.data.name.dom_name, domain->name);
fstrcpy(groups.domain_name, domain->name);