diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/cliconnect.c | 118 |
1 files changed, 94 insertions, 24 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 1624e7bbb2..11b3ee6efb 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -2893,46 +2893,116 @@ fail: return status; } -NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss, - uint16_t port, int name_type, const char *myname, - int signing_state, int flags, struct cli_state **pcli) -{ - TALLOC_CTX *frame = talloc_stackframe(); +struct cli_connect_nb_state { + const char *desthost; + int signing_state; + int flags; struct cli_state *cli; - NTSTATUS status = NT_STATUS_NO_MEMORY; - int fd = -1; - char *desthost; +}; + +static void cli_connect_nb_done(struct tevent_req *subreq); + +static struct tevent_req *cli_connect_nb_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, + const char *host, const struct sockaddr_storage *dest_ss, + uint16_t port, int name_type, const char *myname, + int signing_state, int flags) +{ + struct tevent_req *req, *subreq; + struct cli_connect_nb_state *state; char *p; - /* Save the original host definition for cli_state_create */ - desthost = host; + req = tevent_req_create(mem_ctx, &state, struct cli_connect_nb_state); + if (req == NULL) { + return NULL; + } + state->desthost = host; + state->signing_state = signing_state; + state->flags = flags; p = strchr(host, '#'); if (p != NULL) { name_type = strtol(p+1, NULL, 16); - host = talloc_strndup(talloc_tos(), host, p - host); - if (host == NULL) { - goto fail; + host = talloc_strndup(state, host, p - host); + if (tevent_req_nomem(host, req)) { + return tevent_req_post(req, ev); } } - status = cli_connect_sock(host, name_type, dest_ss, myname, port, - 20, &fd, &port); - if (!NT_STATUS_IS_OK(status)) { - goto fail; + subreq = cli_connect_sock_send(state, ev, host, name_type, dest_ss, + myname, port); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, cli_connect_nb_done, req); + return req; +} - cli = cli_state_create(NULL, fd, desthost, NULL, signing_state, flags); - if (cli == NULL) { +static void cli_connect_nb_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_connect_nb_state *state = tevent_req_data( + req, struct cli_connect_nb_state); + NTSTATUS status; + int fd; + uint16_t port; + + status = cli_connect_sock_recv(subreq, &fd, &port); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + + state->cli = cli_state_create(state, fd, state->desthost, NULL, + state->signing_state, state->flags); + if (tevent_req_nomem(state->cli, req)) { close(fd); - fd = -1; - goto fail; + return; } + tevent_req_done(req); +} + +static NTSTATUS cli_connect_nb_recv(struct tevent_req *req, + struct cli_state **pcli) +{ + struct cli_connect_nb_state *state = tevent_req_data( + req, struct cli_connect_nb_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *pcli = talloc_move(NULL, &state->cli); + return NT_STATUS_OK; +} + +NTSTATUS cli_connect_nb(const char *host, const struct sockaddr_storage *dest_ss, + uint16_t port, int name_type, const char *myname, + int signing_state, int flags, struct cli_state **pcli) +{ + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; - *pcli = cli; - status = NT_STATUS_OK; + ev = samba_tevent_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; + } + req = cli_connect_nb_send(ev, ev, host, dest_ss, port, name_type, + myname, signing_state, flags); + if (req == NULL) { + goto fail; + } + if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(20, 0))) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = cli_connect_nb_recv(req, pcli); fail: - TALLOC_FREE(frame); + TALLOC_FREE(ev); return status; } |