summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/libsmb/cliconnect.c120
1 files changed, 102 insertions, 18 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index ce4b8222e6..36970cc4db 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -2974,6 +2974,14 @@ fail:
return status;
}
+struct cli_start_connection_state {
+ struct tevent_context *ev;
+ struct cli_state *cli;
+};
+
+static void cli_start_connection_connected(struct tevent_req *subreq);
+static void cli_start_connection_done(struct tevent_req *subreq);
+
/**
establishes a connection to after the negprot.
@param output_cli A fully initialised cli structure, non-null only on success
@@ -2981,33 +2989,109 @@ fail:
@param dest_ss (optional) The the destination IP, NULL for name based lookup
@param port (optional) The destination port (0 for default)
*/
+
+static struct tevent_req *cli_start_connection_send(
+ TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ const char *my_name, const char *dest_host,
+ const struct sockaddr_storage *dest_ss, int port,
+ int signing_state, int flags)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_start_connection_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct cli_start_connection_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ subreq = cli_connect_nb_send(state, ev, dest_host, dest_ss, port,
+ 0x20, my_name, signing_state, flags);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_start_connection_connected, req);
+ return req;
+}
+
+static void cli_start_connection_connected(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_start_connection_state *state = tevent_req_data(
+ req, struct cli_start_connection_state);
+ NTSTATUS status;
+
+ status = cli_connect_nb_recv(subreq, &state->cli);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+
+ subreq = smbXcli_negprot_send(state, state->ev, state->cli->conn,
+ state->cli->timeout,
+ PROTOCOL_CORE, PROTOCOL_NT1);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, cli_start_connection_done, req);
+}
+
+static void cli_start_connection_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
+
+ status = smbXcli_negprot_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
+ tevent_req_done(req);
+}
+
+static NTSTATUS cli_start_connection_recv(struct tevent_req *req,
+ struct cli_state **output_cli)
+{
+ struct cli_start_connection_state *state = tevent_req_data(
+ req, struct cli_start_connection_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *output_cli = state->cli;
+ return NT_STATUS_OK;
+}
+
NTSTATUS cli_start_connection(struct cli_state **output_cli,
const char *my_name,
const char *dest_host,
const struct sockaddr_storage *dest_ss, int port,
int signing_state, int flags)
{
- NTSTATUS nt_status;
- struct cli_state *cli;
+ struct tevent_context *ev;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_NO_MEMORY;
- nt_status = cli_connect_nb(dest_host, dest_ss, port, 0x20, my_name,
- signing_state, flags, &cli);
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(10, ("cli_connect_nb failed: %s\n",
- nt_errstr(nt_status)));
- return nt_status;
+ ev = samba_tevent_context_init(talloc_tos());
+ if (ev == NULL) {
+ goto fail;
}
-
- nt_status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
- PROTOCOL_NT1);
- if (!NT_STATUS_IS_OK(nt_status)) {
- DEBUG(1, ("failed negprot: %s\n", nt_errstr(nt_status)));
- cli_shutdown(cli);
- return nt_status;
+ req = cli_start_connection_send(ev, ev, my_name, dest_host, dest_ss,
+ port, signing_state, flags);
+ if (req == NULL) {
+ goto fail;
}
-
- *output_cli = cli;
- return NT_STATUS_OK;
+ if (!tevent_req_poll_ntstatus(req, ev, &status)) {
+ goto fail;
+ }
+ status = cli_start_connection_recv(req, output_cli);
+fail:
+ TALLOC_FREE(ev);
+ return status;
}