bool lp_winbind_normalize_names(void);
bool lp_winbind_rpc_only(void);
bool lp_create_krb5_conf(void);
+int lp_winbind_max_domain_connections(void);
const char *lp_idmap_backend(void);
bool lp_idmap_read_only(void);
int lp_idmap_cache_time(void);
bool bWinbindNormalizeNames;
bool bWinbindRpcOnly;
bool bCreateKrb5Conf;
+ int winbindMaxDomainConnections;
char *szIdmapBackend;
bool bIdmapReadOnly;
char *szAddShareCommand;
.enum_list = NULL,
.flags = FLAG_ADVANCED,
},
+ {
+ .label = "winbind max domain connections",
+ .type = P_INTEGER,
+ .p_class = P_GLOBAL,
+ .ptr = &Globals.winbindMaxDomainConnections,
+ .special = NULL,
+ .enum_list = NULL,
+ .flags = FLAG_ADVANCED,
+ },
{NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
};
Globals.bResetOnZeroVC = False;
Globals.bLogWriteableFilesOnExit = False;
Globals.bCreateKrb5Conf = true;
+ Globals.winbindMaxDomainConnections = 1;
/* hostname lookups can be very expensive and are broken on
a large number of sites (tridge) */
FN_GLOBAL_BOOL(lp_winbind_normalize_names, &Globals.bWinbindNormalizeNames)
FN_GLOBAL_BOOL(lp_winbind_rpc_only, &Globals.bWinbindRpcOnly)
FN_GLOBAL_BOOL(lp_create_krb5_conf, &Globals.bCreateKrb5Conf)
+static FN_GLOBAL_INTEGER(lp_winbind_max_domain_connections_int,
+ &Globals.winbindMaxDomainConnections)
+
+int lp_winbind_max_domain_connections(void)
+{
+ if (lp_winbind_offline_logon() &&
+ lp_winbind_max_domain_connections_int() > 1) {
+ DEBUG(1, ("offline logons active, restricting max domain "
+ "connections to 1\n"));
+ return 1;
+ }
+ return MAX(1, lp_winbind_max_domain_connections_int());
+}
FN_GLOBAL_CONST_STRING(lp_idmap_backend, &Globals.szIdmapBackend)
FN_GLOBAL_BOOL(lp_idmap_read_only, &Globals.bIdmapReadOnly)
child = locator_child();
} else {
struct winbindd_domain *domain = find_our_domain();
- child = &domain->child;
+ child = choose_domain_child(domain);
}
if (domain_guid != NULL) {
}
subreq = dcerpc_wbint_LookupGroupMembers_send(
- state, ev, domain->child.binding_handle, &state->sid, type,
+ state, ev, dom_child_handle(domain), &state->sid, type,
&state->members);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
subreq = dcerpc_wbint_LookupName_send(
- state, ev, domain->child.binding_handle, state->dom_name, state->name,
+ state, ev, dom_child_handle(domain),
+ state->dom_name, state->name,
flags, &state->type, &state->sid);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
subreq = dcerpc_wbint_LookupName_send(
- state, state->ev, root_domain->child.binding_handle, state->dom_name,
+ state, state->ev, dom_child_handle(root_domain),
+ state->dom_name,
state->name, state->flags, &state->type, &state->sid);
if (tevent_req_nomem(subreq, req)) {
return;
}
subreq = dcerpc_wbint_LookupSid_send(
- state, ev, state->lookup_domain->child.binding_handle,
+ state, ev, dom_child_handle(state->lookup_domain),
&state->sid, &state->type, &state->domname, &state->name);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
state->lookup_domain = forest_root;
subreq = dcerpc_wbint_LookupSid_send(
- state, state->ev, state->lookup_domain->child.binding_handle,
+ state, state->ev, dom_child_handle(state->lookup_domain),
&state->sid, &state->type, &state->domname, &state->name);
if (tevent_req_nomem(subreq, req)) {
return;
state->sids.sids = CONST_DISCARD(struct dom_sid *, sids);
subreq = dcerpc_wbint_LookupUserAliases_send(
- state, ev, domain->child.binding_handle, &state->sids, &state->rids);
+ state, ev, dom_child_handle(domain), &state->sids, &state->rids);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
sid_copy(&state->sid, sid);
subreq = dcerpc_wbint_LookupUserGroups_send(
- state, ev, domain->child.binding_handle, &state->sid, &state->sids);
+ state, ev, dom_child_handle(domain), &state->sid, &state->sids);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
return tevent_req_post(req, ev);
}
subreq = dcerpc_wbint_QueryGroupList_send(
- state, state->ev, state->gstate->domain->child.binding_handle,
+ state, state->ev, dom_child_handle(state->gstate->domain),
&state->next_groups);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
return;
}
subreq = dcerpc_wbint_QueryGroupList_send(
- state, state->ev, state->gstate->domain->child.binding_handle,
+ state, state->ev, dom_child_handle(state->gstate->domain),
&state->next_groups);
if (tevent_req_nomem(subreq, req)) {
return;
}
subreq = dcerpc_wbint_QueryUserList_send(state, ev,
- domain->child.binding_handle,
+ dom_child_handle(domain),
&state->users);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
return tevent_req_post(req, ev);
}
- subreq = dcerpc_wbint_QueryUser_send(state, ev, domain->child.binding_handle,
+ subreq = dcerpc_wbint_QueryUser_send(state, ev, dom_child_handle(domain),
&state->sid, state->info);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
return NULL;
}
subreq = dcerpc_wbint_QuerySequenceNumber_send(
- state, ev, domain->child.binding_handle, &state->seqnum);
+ state, ev, dom_child_handle(domain), &state->seqnum);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
/* The child pid we're talking to */
- struct winbindd_child child;
+ struct winbindd_child *children;
/* Callback we use to try put us back online. */
}
subreq = dcerpc_wbint_ChangeMachineAccount_send(state, ev,
- domain->child.binding_handle);
+ dom_child_handle(domain));
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
}
subreq = dcerpc_wbint_CheckMachineAccount_send(state, ev,
- domain->child.binding_handle);
+ dom_child_handle(domain));
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
void setup_domain_child(struct winbindd_domain *domain)
{
- setup_child(domain, &domain->child, domain_dispatch_table,
- "log.wb", domain->name);
+ int i;
+
+ for (i=0; i<lp_winbind_max_domain_connections(); i++) {
+ setup_child(domain, &domain->children[i],
+ domain_dispatch_table,
+ "log.wb", domain->name);
+ domain->children[i].domain = domain;
+ }
}
return 0;
}
+static bool winbindd_child_busy(struct winbindd_child *child)
+{
+ return tevent_queue_length(child->queue) > 0;
+}
+
+static struct winbindd_child *find_idle_child(struct winbindd_domain *domain)
+{
+ int i;
+
+ for (i=0; i<lp_winbind_max_domain_connections(); i++) {
+ if (!winbindd_child_busy(&domain->children[i])) {
+ return &domain->children[i];
+ }
+ }
+
+ return NULL;
+}
+
+struct winbindd_child *choose_domain_child(struct winbindd_domain *domain)
+{
+ struct winbindd_child *result;
+
+ result = find_idle_child(domain);
+ if (result != NULL) {
+ return result;
+ }
+ return &domain->children[rand() % lp_winbind_max_domain_connections()];
+}
+
+struct dcerpc_binding_handle *dom_child_handle(struct winbindd_domain *domain)
+{
+ struct winbindd_child *child;
+
+ child = choose_domain_child(domain);
+ return child->binding_handle;
+}
+
struct wb_domain_request_state {
struct tevent_context *ev;
struct winbindd_domain *domain;
+ struct winbindd_child *child;
struct winbindd_request *request;
struct winbindd_request *init_req;
struct winbindd_response *response;
return NULL;
}
+ state->child = choose_domain_child(domain);
+
if (domain->initialized) {
- subreq = wb_child_request_send(state, ev, &domain->child,
+ subreq = wb_child_request_send(state, ev, state->child,
request);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
state->init_req->data.init_conn.is_primary = domain->primary;
fstrcpy(state->init_req->data.init_conn.dcname, "");
- subreq = wb_child_request_send(state, ev, &domain->child,
+ subreq = wb_child_request_send(state, ev, state->child,
state->init_req);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
state->init_req->cmd = WINBINDD_GETDCNAME;
fstrcpy(state->init_req->domain_name, domain->name);
- subreq = wb_child_request_send(state, ev, &domain->child, request);
+ subreq = wb_child_request_send(state, ev, state->child, request);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
TALLOC_FREE(response);
- subreq = wb_child_request_send(state, state->ev, &state->domain->child,
+ subreq = wb_child_request_send(state, state->ev, state->child,
state->init_req);
if (tevent_req_nomem(subreq, req)) {
return;
TALLOC_FREE(response);
- subreq = wb_child_request_send(state, state->ev, &state->domain->child,
+ subreq = wb_child_request_send(state, state->ev, state->child,
state->request);
if (tevent_req_nomem(subreq, req)) {
return;
struct winbindd_list_groups_domstate *d = &state->domains[i];
d->subreq = dcerpc_wbint_QueryGroupList_send(
- state->domains, ev, d->domain->child.binding_handle,
+ state->domains, ev, dom_child_handle(d->domain),
&d->groups);
if (tevent_req_nomem(d->subreq, req)) {
TALLOC_FREE(state->domains);
struct winbindd_list_users_domstate *d = &state->domains[i];
d->subreq = dcerpc_wbint_QueryUserList_send(
- state->domains, ev, d->domain->child.binding_handle,
+ state->domains, ev, dom_child_handle(d->domain),
&d->users);
if (tevent_req_nomem(d->subreq, req)) {
TALLOC_FREE(state->domains);
}
subreq = dcerpc_wbint_LookupRids_send(
- state, ev, domain->child.binding_handle, &state->rids,
+ state, ev, dom_child_handle(domain), &state->rids,
&state->domain_name, &state->names);
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
const char *name,
const struct winbindd_domain *r)
{
+ int i;
if (!r) {
return;
}
ndr_print_uint32(ndr, "sequence_number", r->sequence_number);
ndr_print_NTSTATUS(ndr, "last_status", r->last_status);
ndr_print_winbindd_cm_conn(ndr, "conn", &r->conn);
- ndr_print_winbindd_child(ndr, "child", &r->child);
+ for (i=0; i<lp_winbind_max_domain_connections(); i++) {
+ ndr_print_winbindd_child(ndr, "children", &r->children[i]);
+ }
ndr_print_uint32(ndr, "check_online_timeout", r->check_online_timeout);
ndr_print_ptr(ndr, "check_online_event", r->check_online_event);
ndr->depth--;
return tevent_req_post(req, ev);
}
- subreq = dcerpc_wbint_PingDc_send(state, ev, domain->child.binding_handle);
+ subreq = dcerpc_wbint_PingDc_send(state, ev, dom_child_handle(domain));
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
/* The following definitions come from winbindd/winbindd_dual.c */
+struct dcerpc_binding_handle *dom_child_handle(struct winbindd_domain *domain);
+struct winbindd_child *choose_domain_child(struct winbindd_domain *domain);
+
struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct winbindd_child *child,
ZERO_STRUCTP(domain);
+ domain->children = SMB_MALLOC_ARRAY(
+ struct winbindd_child, lp_winbind_max_domain_connections());
+ if (domain->children == NULL) {
+ SAFE_FREE(domain);
+ return NULL;
+ }
+ memset(domain->children, 0,
+ sizeof(struct winbindd_child)
+ * lp_winbind_max_domain_connections());
+
fstrcpy(domain->name, domain_name);
if (alternative_name) {
fstrcpy(domain->alt_name, alternative_name);