diff options
24 files changed, 117 insertions, 28 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index f3ec4d16c6..de6e7acc9e 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -3230,6 +3230,7 @@ bool lp_winbind_offline_logon(void); 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); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 875cab1629..b45e045d64 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -216,6 +216,7 @@ struct global { bool bWinbindNormalizeNames; bool bWinbindRpcOnly; bool bCreateKrb5Conf; + int winbindMaxDomainConnections; char *szIdmapBackend; bool bIdmapReadOnly; char *szAddShareCommand; @@ -4773,6 +4774,15 @@ static struct parm_struct parm_table[] = { .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} }; @@ -5279,6 +5289,7 @@ static void init_globals(bool reinit_globals) 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) */ @@ -5651,6 +5662,19 @@ FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon) 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) diff --git a/source3/winbindd/wb_dsgetdcname.c b/source3/winbindd/wb_dsgetdcname.c index fdd9a6d7df..207d1b61ea 100644 --- a/source3/winbindd/wb_dsgetdcname.c +++ b/source3/winbindd/wb_dsgetdcname.c @@ -64,7 +64,7 @@ struct tevent_req *wb_dsgetdcname_send(TALLOC_CTX *mem_ctx, child = locator_child(); } else { struct winbindd_domain *domain = find_our_domain(); - child = &domain->child; + child = choose_domain_child(domain); } if (domain_guid != NULL) { diff --git a/source3/winbindd/wb_group_members.c b/source3/winbindd/wb_group_members.c index 024b3173b9..c9603e73f8 100644 --- a/source3/winbindd/wb_group_members.c +++ b/source3/winbindd/wb_group_members.c @@ -73,7 +73,7 @@ static struct tevent_req *wb_lookupgroupmem_send(TALLOC_CTX *mem_ctx, } 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); diff --git a/source3/winbindd/wb_lookupname.c b/source3/winbindd/wb_lookupname.c index 4429149f7a..a9b4dfa586 100644 --- a/source3/winbindd/wb_lookupname.c +++ b/source3/winbindd/wb_lookupname.c @@ -70,7 +70,8 @@ struct tevent_req *wb_lookupname_send(TALLOC_CTX *mem_ctx, } 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); @@ -111,7 +112,8 @@ static void wb_lookupname_done(struct tevent_req *subreq) } 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; diff --git a/source3/winbindd/wb_lookupsid.c b/source3/winbindd/wb_lookupsid.c index 52e8bcbdea..2e1b21a8d8 100644 --- a/source3/winbindd/wb_lookupsid.c +++ b/source3/winbindd/wb_lookupsid.c @@ -56,7 +56,7 @@ struct tevent_req *wb_lookupsid_send(TALLOC_CTX *mem_ctx, } 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); @@ -96,7 +96,7 @@ static void wb_lookupsid_done(struct tevent_req *subreq) 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; diff --git a/source3/winbindd/wb_lookupuseraliases.c b/source3/winbindd/wb_lookupuseraliases.c index 1e9b4c318e..f6fe855a85 100644 --- a/source3/winbindd/wb_lookupuseraliases.c +++ b/source3/winbindd/wb_lookupuseraliases.c @@ -47,7 +47,7 @@ struct tevent_req *wb_lookupuseraliases_send(TALLOC_CTX *mem_ctx, 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); } diff --git a/source3/winbindd/wb_lookupusergroups.c b/source3/winbindd/wb_lookupusergroups.c index 27a6a5b00e..aeffc178d9 100644 --- a/source3/winbindd/wb_lookupusergroups.c +++ b/source3/winbindd/wb_lookupusergroups.c @@ -46,7 +46,7 @@ struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx, 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); } diff --git a/source3/winbindd/wb_next_grent.c b/source3/winbindd/wb_next_grent.c index 7eec3e0b94..54c4c1c440 100644 --- a/source3/winbindd/wb_next_grent.c +++ b/source3/winbindd/wb_next_grent.c @@ -70,7 +70,7 @@ struct tevent_req *wb_next_grent_send(TALLOC_CTX *mem_ctx, 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); @@ -134,7 +134,7 @@ static void wb_next_grent_fetch_done(struct tevent_req *subreq) 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; diff --git a/source3/winbindd/wb_query_user_list.c b/source3/winbindd/wb_query_user_list.c index c4eb200d88..abbf7668e9 100644 --- a/source3/winbindd/wb_query_user_list.c +++ b/source3/winbindd/wb_query_user_list.c @@ -41,7 +41,7 @@ struct tevent_req *wb_query_user_list_send(TALLOC_CTX *mem_ctx, } 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); diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c index 870bfd3366..33416b9017 100644 --- a/source3/winbindd/wb_queryuser.c +++ b/source3/winbindd/wb_queryuser.c @@ -54,7 +54,7 @@ struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx, 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); diff --git a/source3/winbindd/wb_seqnum.c b/source3/winbindd/wb_seqnum.c index 0a314e7abe..4a92e036dc 100644 --- a/source3/winbindd/wb_seqnum.c +++ b/source3/winbindd/wb_seqnum.c @@ -39,7 +39,7 @@ struct tevent_req *wb_seqnum_send(TALLOC_CTX *mem_ctx, 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); } diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h index d276b86947..3217acc8ea 100644 --- a/source3/winbindd/winbindd.h +++ b/source3/winbindd/winbindd.h @@ -205,7 +205,7 @@ struct winbindd_domain { /* The child pid we're talking to */ - struct winbindd_child child; + struct winbindd_child *children; /* Callback we use to try put us back online. */ diff --git a/source3/winbindd/winbindd_change_machine_acct.c b/source3/winbindd/winbindd_change_machine_acct.c index ad050ad742..a5514e22eb 100644 --- a/source3/winbindd/winbindd_change_machine_acct.c +++ b/source3/winbindd/winbindd_change_machine_acct.c @@ -58,7 +58,7 @@ struct tevent_req *winbindd_change_machine_acct_send(TALLOC_CTX *mem_ctx, } 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); } diff --git a/source3/winbindd/winbindd_check_machine_acct.c b/source3/winbindd/winbindd_check_machine_acct.c index 6d969c9353..279370146a 100644 --- a/source3/winbindd/winbindd_check_machine_acct.c +++ b/source3/winbindd/winbindd_check_machine_acct.c @@ -62,7 +62,7 @@ struct tevent_req *winbindd_check_machine_acct_send(TALLOC_CTX *mem_ctx, } 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); } diff --git a/source3/winbindd/winbindd_domain.c b/source3/winbindd/winbindd_domain.c index cd3370852b..e998275c8e 100644 --- a/source3/winbindd/winbindd_domain.c +++ b/source3/winbindd/winbindd_domain.c @@ -69,6 +69,12 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = { 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; + } } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 344b7e4bd1..a32459d595 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -193,9 +193,47 @@ int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, 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; @@ -219,8 +257,10 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx, 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); @@ -245,7 +285,7 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx, 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); @@ -266,7 +306,7 @@ struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx, 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); } @@ -297,7 +337,7 @@ static void wb_domain_request_gotdc(struct tevent_req *subreq) 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; @@ -337,7 +377,7 @@ static void wb_domain_request_initialized(struct tevent_req *subreq) 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; diff --git a/source3/winbindd/winbindd_list_groups.c b/source3/winbindd/winbindd_list_groups.c index 4236794485..2e2c70a33d 100644 --- a/source3/winbindd/winbindd_list_groups.c +++ b/source3/winbindd/winbindd_list_groups.c @@ -91,7 +91,7 @@ struct tevent_req *winbindd_list_groups_send(TALLOC_CTX *mem_ctx, 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); diff --git a/source3/winbindd/winbindd_list_users.c b/source3/winbindd/winbindd_list_users.c index 18b8fdd589..54e0106e3d 100644 --- a/source3/winbindd/winbindd_list_users.c +++ b/source3/winbindd/winbindd_list_users.c @@ -91,7 +91,7 @@ struct tevent_req *winbindd_list_users_send(TALLOC_CTX *mem_ctx, 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); diff --git a/source3/winbindd/winbindd_lookuprids.c b/source3/winbindd/winbindd_lookuprids.c index b921818bc6..738adbaefc 100644 --- a/source3/winbindd/winbindd_lookuprids.c +++ b/source3/winbindd/winbindd_lookuprids.c @@ -84,7 +84,7 @@ struct tevent_req *winbindd_lookuprids_send(TALLOC_CTX *mem_ctx, } 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); diff --git a/source3/winbindd/winbindd_ndr.c b/source3/winbindd/winbindd_ndr.c index 396aa06985..94aa7eb965 100644 --- a/source3/winbindd/winbindd_ndr.c +++ b/source3/winbindd/winbindd_ndr.c @@ -120,6 +120,7 @@ void ndr_print_winbindd_domain(struct ndr_print *ndr, const char *name, const struct winbindd_domain *r) { + int i; if (!r) { return; } @@ -150,7 +151,9 @@ void ndr_print_winbindd_domain(struct ndr_print *ndr, 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--; diff --git a/source3/winbindd/winbindd_ping_dc.c b/source3/winbindd/winbindd_ping_dc.c index 36c4def0ab..2304828030 100644 --- a/source3/winbindd/winbindd_ping_dc.c +++ b/source3/winbindd/winbindd_ping_dc.c @@ -61,7 +61,7 @@ struct tevent_req *winbindd_ping_dc_send(TALLOC_CTX *mem_ctx, 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); } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 5cb6c4c155..c822baa462 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -227,6 +227,9 @@ void setup_domain_child(struct winbindd_domain *domain); /* 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, diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index e27c35fe60..58cec444aa 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -162,6 +162,16 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const 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); |