diff --git a/source3/libads/cldap.c b/source3/libads/cldap.c index fa1c26b432f..9330b032bec 100644 --- a/source3/libads/cldap.c +++ b/source3/libads/cldap.c @@ -28,27 +28,6 @@ #include "libads/cldap.h" #include "libads/netlogon_ping.h" -struct cldap_multi_netlogon_state { - struct tevent_context *ev; - const struct tsocket_address * const *servers; - int num_servers; - const char *domain; - const char *hostname; - unsigned ntversion; - int min_servers; - - struct cldap_socket **cldap; - struct tevent_req **subreqs; - int num_sent; - int num_received; - int num_good_received; - struct cldap_netlogon *ios; - struct netlogon_samlogon_response **responses; -}; - -static void cldap_multi_netlogon_done(struct tevent_req *subreq); -static void cldap_multi_netlogon_next(struct tevent_req *subreq); - /**************************************************************** ****************************************************************/ @@ -102,267 +81,6 @@ bool check_cldap_reply_required_flags(uint32_t ret_flags, return true; } -/* - * Do a parallel cldap ping to the servers. The first "min_servers" - * are fired directly, the remaining ones in 100msec intervals. If - * "min_servers" responses came in successfully, we immediately reply, - * not waiting for the remaining ones. - */ - -struct tevent_req *cldap_multi_netlogon_send( - TALLOC_CTX *mem_ctx, struct tevent_context *ev, - const struct tsocket_address * const *servers, int num_servers, - const char *domain, const char *hostname, unsigned ntversion, - int min_servers) -{ - struct tevent_req *req, *subreq; - struct cldap_multi_netlogon_state *state; - int i; - - req = tevent_req_create(mem_ctx, &state, - struct cldap_multi_netlogon_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->servers = servers; - state->num_servers = num_servers; - state->domain = domain; - state->hostname = hostname; - state->ntversion = ntversion; - state->min_servers = min_servers; - - if (min_servers > num_servers) { - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); - return tevent_req_post(req, ev); - } - - state->subreqs = talloc_zero_array(state, - struct tevent_req *, - num_servers); - if (tevent_req_nomem(state->subreqs, req)) { - return tevent_req_post(req, ev); - } - - state->cldap = talloc_zero_array(state, - struct cldap_socket *, - num_servers); - if (tevent_req_nomem(state->cldap, req)) { - return tevent_req_post(req, ev); - } - - state->responses = talloc_zero_array(state, - struct netlogon_samlogon_response *, - num_servers); - if (tevent_req_nomem(state->responses, req)) { - return tevent_req_post(req, ev); - } - - state->ios = talloc_array(state->responses, - struct cldap_netlogon, - num_servers); - if (tevent_req_nomem(state->ios, req)) { - return tevent_req_post(req, ev); - } - - for (i=0; icldap, - NULL, /* local_addr */ - state->servers[i], - &state->cldap[i]); - if (!NT_STATUS_IS_OK(status)) { - /* - * Don't error out all sends just - * because one cldap_socket_init() failed. - * Log it here, and the cldap_netlogon_send() - * will catch it (with in.dest_address == NULL) - * and correctly error out in - * cldap_multi_netlogon_done(). This still allows - * the other requests to be concurrently sent. - */ - DBG_NOTICE("cldap_socket_init failed for %s " - " error %s\n", - tsocket_address_string(state->servers[i], - req), - nt_errstr(status)); - } - - state->ios[i] = (struct cldap_netlogon){ - .in.realm = domain, .in.version = ntversion}; - } - - for (i=0; isubreqs[i] = cldap_netlogon_send(state->subreqs, - state->ev, - state->cldap[i], - &state->ios[i]); - if (tevent_req_nomem(state->subreqs[i], req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback( - state->subreqs[i], cldap_multi_netlogon_done, req); - } - state->num_sent = min_servers; - - if (state->num_sent < state->num_servers) { - /* - * After 100 milliseconds fire the next one - */ - subreq = tevent_wakeup_send(state, state->ev, - timeval_current_ofs(0, 100000)); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, cldap_multi_netlogon_next, - req); - } - - return req; -} - -static void cldap_multi_netlogon_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct cldap_multi_netlogon_state *state = tevent_req_data( - req, struct cldap_multi_netlogon_state); - NTSTATUS status; - struct netlogon_samlogon_response *response = NULL; - int i; - - for (i=0; inum_sent; i++) { - if (state->subreqs[i] == subreq) { - break; - } - } - if (i == state->num_sent) { - /* - * Got a response we did not fire... - */ - tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); - return; - } - state->subreqs[i] = NULL; - - response = talloc_zero(state, struct netlogon_samlogon_response); - if (tevent_req_nomem(response, req)) { - return; - } - - status = cldap_netlogon_recv(subreq, response, - &state->ios[i]); - TALLOC_FREE(subreq); - state->num_received += 1; - - if (NT_STATUS_IS_OK(status)) { - *response = *state->ios[i].out.netlogon; - state->responses[i] = talloc_move(state->responses, - &response); - state->num_good_received += 1; - } - - if ((state->num_received == state->num_servers) || - (state->num_good_received >= state->min_servers)) { - tevent_req_done(req); - return; - } -} - -static void cldap_multi_netlogon_next(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct cldap_multi_netlogon_state *state = tevent_req_data( - req, struct cldap_multi_netlogon_state); - bool ret; - - ret = tevent_wakeup_recv(subreq); - TALLOC_FREE(subreq); - if (!ret) { - tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - subreq = cldap_netlogon_send(state->subreqs, - state->ev, - state->cldap[state->num_sent], - &state->ios[state->num_sent]); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, cldap_multi_netlogon_done, req); - state->subreqs[state->num_sent] = subreq; - state->num_sent += 1; - - if (state->num_sent < state->num_servers) { - /* - * After 100 milliseconds fire the next one - */ - subreq = tevent_wakeup_send(state, state->ev, - timeval_current_ofs(0, 100000)); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, cldap_multi_netlogon_next, - req); - } -} - -NTSTATUS cldap_multi_netlogon_recv( - struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct netlogon_samlogon_response ***responses) -{ - struct cldap_multi_netlogon_state *state = tevent_req_data( - req, struct cldap_multi_netlogon_state); - NTSTATUS status; - - if (tevent_req_is_nterror(req, &status) && - !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - return status; - } - /* - * If we timeout, give back what we have so far - */ - *responses = talloc_move(mem_ctx, &state->responses); - return NT_STATUS_OK; -} - -NTSTATUS cldap_multi_netlogon( - TALLOC_CTX *mem_ctx, - const struct tsocket_address * const *servers, - int num_servers, - const char *domain, const char *hostname, unsigned ntversion, - int min_servers, struct timeval timeout, - struct netlogon_samlogon_response ***responses) -{ - struct tevent_context *ev; - struct tevent_req *req; - NTSTATUS status = NT_STATUS_NO_MEMORY; - - ev = samba_tevent_context_init(talloc_tos()); - if (ev == NULL) { - goto fail; - } - req = cldap_multi_netlogon_send( - ev, ev, servers, num_servers, domain, hostname, ntversion, - min_servers); - if (req == NULL) { - goto fail; - } - if (!tevent_req_set_endtime(req, ev, timeout)) { - goto fail; - } - if (!tevent_req_poll_ntstatus(req, ev, &status)) { - goto fail; - } - status = cldap_multi_netlogon_recv(req, mem_ctx, responses); -fail: - TALLOC_FREE(ev); - return status; -} - /******************************************************************* do a cldap netlogon query. Always 389/udp *******************************************************************/ diff --git a/source3/libads/cldap.h b/source3/libads/cldap.h index 7fa1bdf8d60..bbf45a42712 100644 --- a/source3/libads/cldap.h +++ b/source3/libads/cldap.h @@ -30,23 +30,6 @@ bool check_cldap_reply_required_flags(uint32_t ret_flags, uint32_t req_flags); -struct tevent_req *cldap_multi_netlogon_send( - TALLOC_CTX *mem_ctx, struct tevent_context *ev, - const struct tsocket_address * const *servers, - int num_servers, - const char *domain, const char *hostname, unsigned ntversion, - int min_servers); -NTSTATUS cldap_multi_netlogon_recv( - struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct netlogon_samlogon_response ***responses); -NTSTATUS cldap_multi_netlogon( - TALLOC_CTX *mem_ctx, - const struct tsocket_address * const *servers, - int num_servers, - const char *domain, const char *hostname, unsigned ntversion, - int min_servers, struct timeval timeout, - struct netlogon_samlogon_response ***responses); - bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx, struct sockaddr_storage *ss, const char *realm,