From bb843be3bfe4a9e15f345edb8acb290d63b28781 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Nov 2018 21:01:19 +0100 Subject: [PATCH 1/6] libsmb: Make cli_trans a normal subreq function A lot of "state" variables, but still I don't think the additional complexity is justified by saving a few lines. Make this a completely regular tevent_req "req/subreq" function. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libsmb/clitrans.c | 208 +++++++++++++++++++++----------------- 1 file changed, 113 insertions(+), 95 deletions(-) diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index a96d8bf4769..7817fd4b3c5 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -25,28 +25,16 @@ struct cli_trans_state { struct cli_state *cli; - struct tevent_req *req; - struct cli_trans_state **ptr; + uint16_t recv_flags2; + uint16_t *setup; + uint8_t num_setup; + uint8_t *param; + uint32_t num_param; + uint8_t *data; + uint32_t num_data; }; -static int cli_trans_state_destructor(struct cli_trans_state *state) -{ - talloc_set_destructor(state->ptr, NULL); - talloc_free(state->ptr); - return 0; -} - -static int cli_trans_state_ptr_destructor(struct cli_trans_state **ptr) -{ - struct cli_trans_state *state = *ptr; - void *parent = talloc_parent(state); - - talloc_set_destructor(state, NULL); - - talloc_reparent(state, parent, state->req); - talloc_free(state); - return 0; -} +static void cli_trans_done(struct tevent_req *subreq); struct tevent_req *cli_trans_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -56,45 +44,57 @@ struct tevent_req *cli_trans_send( uint8_t *param, uint32_t num_param, uint32_t max_param, uint8_t *data, uint32_t num_data, uint32_t max_data) { + struct tevent_req *req, *subreq; struct cli_trans_state *state; uint8_t additional_flags = 0; uint8_t clear_flags = 0; uint16_t clear_flags2 = 0; - state = talloc_zero(mem_ctx, struct cli_trans_state); - if (state == NULL) { + req = tevent_req_create(mem_ctx, &state, struct cli_trans_state); + if (req == NULL) { return NULL; } state->cli = cli; - state->ptr = talloc(state, struct cli_trans_state *); - if (state->ptr == NULL) { - talloc_free(state); - return NULL; - } - *state->ptr = state; - - state->req = smb1cli_trans_send(state, ev, - cli->conn, cmd, - additional_flags, clear_flags, - additional_flags2, clear_flags2, - cli->timeout, - cli->smb1.pid, - cli->smb1.tcon, - cli->smb1.session, - pipe_name, fid, function, flags, - setup, num_setup, max_setup, - param, num_param, max_param, - data, num_data, max_data); - if (state->req == NULL) { - talloc_free(state); - return NULL; + + subreq = smb1cli_trans_send(state, ev, + cli->conn, cmd, + additional_flags, clear_flags, + additional_flags2, clear_flags2, + cli->timeout, + cli->smb1.pid, + cli->smb1.tcon, + cli->smb1.session, + pipe_name, fid, function, flags, + setup, num_setup, max_setup, + param, num_param, max_param, + data, num_data, max_data); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, cli_trans_done, req); + return req; +} - talloc_reparent(state, state->req, state->ptr); - talloc_set_destructor(state, cli_trans_state_destructor); - talloc_set_destructor(state->ptr, cli_trans_state_ptr_destructor); +static void cli_trans_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_trans_state *state = tevent_req_data( + req, struct cli_trans_state); + NTSTATUS status; - return state->req; + status = smb1cli_trans_recv( + subreq, + state, + &state->recv_flags2, + &state->setup, 0, &state->num_setup, + &state->param, 0, &state->num_param, + &state->data, 0, &state->num_data); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + tevent_req_done(req); } NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, @@ -106,25 +106,41 @@ NTSTATUS cli_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint8_t **data, uint32_t min_data, uint32_t *num_data) { - NTSTATUS status; - void *parent = talloc_parent(req); - struct cli_trans_state *state = - talloc_get_type(parent, - struct cli_trans_state); + struct cli_trans_state *state = tevent_req_data( + req, struct cli_trans_state); + NTSTATUS status = NT_STATUS_OK; bool map_dos_errors = true; - status = smb1cli_trans_recv(req, mem_ctx, recv_flags2, - setup, min_setup, num_setup, - param, min_param, num_param, - data, min_data, num_data); + if (tevent_req_is_nterror(req, &status)) { + goto map_error; + } + + if ((state->num_setup < min_setup) || + (state->num_param < min_param) || + (state->num_data < min_data)) { + return NT_STATUS_INVALID_NETWORK_RESPONSE; + } - if (state) { - map_dos_errors = state->cli->map_dos_errors; - state->cli->raw_status = status; - talloc_free(state->ptr); - state = NULL; + if (recv_flags2 != NULL) { + *recv_flags2 = state->recv_flags2; + } + if (setup != NULL) { + *setup = talloc_move(mem_ctx, &state->setup); + *num_setup = state->num_setup; + } + if (param != NULL) { + *param = talloc_move(mem_ctx, &state->param); + *num_param = state->num_param; + } + if (data != NULL) { + *data = talloc_move(mem_ctx, &state->data); + *num_data = state->num_data; } +map_error: + map_dos_errors = state->cli->map_dos_errors; + state->cli->raw_status = status; + if (NT_STATUS_IS_DOS(status) && map_dos_errors) { uint8_t eclass = NT_STATUS_DOS_CLASS(status); uint16_t ecode = NT_STATUS_DOS_CODE(status); @@ -152,42 +168,44 @@ NTSTATUS cli_trans(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint8_t **rparam, uint32_t min_rparam, uint32_t *num_rparam, uint8_t **rdata, uint32_t min_rdata, uint32_t *num_rdata) { - NTSTATUS status; - uint8_t additional_flags = 0; - uint8_t clear_flags = 0; - uint16_t additional_flags2 = 0; - uint16_t clear_flags2 = 0; + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; - status = smb1cli_trans(mem_ctx, - cli->conn, trans_cmd, - additional_flags, clear_flags, - additional_flags2, clear_flags2, - cli->timeout, - cli->smb1.pid, - cli->smb1.tcon, - cli->smb1.session, - pipe_name, fid, function, flags, - setup, num_setup, max_setup, - param, num_param, max_param, - data, num_data, max_data, - recv_flags2, - rsetup, min_rsetup, num_rsetup, - rparam, min_rparam, num_rparam, - rdata, min_rdata, num_rdata); - - cli->raw_status = status; - - if (NT_STATUS_IS_DOS(status) && cli->map_dos_errors) { - uint8_t eclass = NT_STATUS_DOS_CLASS(status); - uint16_t ecode = NT_STATUS_DOS_CODE(status); + if (smbXcli_conn_has_async_calls(cli->conn)) { /* - * TODO: is it really a good idea to do a mapping here? - * - * The old cli_pull_error() also does it, so I do not change - * the behavior yet. + * Can't use sync call while an async call is in flight */ - status = dos_to_ntstatus(eclass, ecode); + status = NT_STATUS_INVALID_PARAMETER; + goto fail; } - + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = cli_trans_send( + frame, /* mem_ctx */ + ev, /* ev */ + cli, /* cli */ + 0, /* additional_flags2 */ + trans_cmd, /* cmd */ + pipe_name, fid, function, flags, + setup, num_setup, max_setup, + param, num_param, max_param, + data, num_data, max_data); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = cli_trans_recv( + req, mem_ctx, recv_flags2, + rsetup, min_rsetup, num_rsetup, + rparam, min_rparam, num_rparam, + rdata, min_rdata, num_rdata); +fail: + TALLOC_FREE(frame); return status; } -- 2.22.0.410.gd8fdbe21b5-goog From 9c9ccf234989a28e0f3d8f46fa7bce070e44c5a4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Nov 2018 21:03:45 +0100 Subject: [PATCH 2/6] libsmb: Make cli_trans_send cancellable Required to cancel SMB1 notify Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libsmb/clitrans.c | 43 +++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index 7817fd4b3c5..e5b4c4a4618 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -25,6 +25,7 @@ struct cli_trans_state { struct cli_state *cli; + struct tevent_req *subreq; uint16_t recv_flags2; uint16_t *setup; uint8_t num_setup; @@ -35,6 +36,7 @@ struct cli_trans_state { }; static void cli_trans_done(struct tevent_req *subreq); +static bool cli_trans_cancel(struct tevent_req *req); struct tevent_req *cli_trans_send( TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -44,7 +46,7 @@ struct tevent_req *cli_trans_send( uint8_t *param, uint32_t num_param, uint32_t max_param, uint8_t *data, uint32_t num_data, uint32_t max_data) { - struct tevent_req *req, *subreq; + struct tevent_req *req; struct cli_trans_state *state; uint8_t additional_flags = 0; uint8_t clear_flags = 0; @@ -56,25 +58,36 @@ struct tevent_req *cli_trans_send( } state->cli = cli; - subreq = smb1cli_trans_send(state, ev, - cli->conn, cmd, - additional_flags, clear_flags, - additional_flags2, clear_flags2, - cli->timeout, - cli->smb1.pid, - cli->smb1.tcon, - cli->smb1.session, - pipe_name, fid, function, flags, - setup, num_setup, max_setup, - param, num_param, max_param, - data, num_data, max_data); - if (tevent_req_nomem(subreq, req)) { + state->subreq = smb1cli_trans_send(state, ev, + cli->conn, cmd, + additional_flags, clear_flags, + additional_flags2, clear_flags2, + cli->timeout, + cli->smb1.pid, + cli->smb1.tcon, + cli->smb1.session, + pipe_name, fid, function, flags, + setup, num_setup, max_setup, + param, num_param, max_param, + data, num_data, max_data); + if (tevent_req_nomem(state->subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, cli_trans_done, req); + tevent_req_set_callback(state->subreq, cli_trans_done, req); + tevent_req_set_cancel_fn(req, cli_trans_cancel); return req; } +static bool cli_trans_cancel(struct tevent_req *req) +{ + struct cli_trans_state *state = tevent_req_data( + req, struct cli_trans_state); + bool ok; + + ok = tevent_req_cancel(state->subreq); + return ok; +} + static void cli_trans_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( -- 2.22.0.410.gd8fdbe21b5-goog From 499d97b38c4477751d2dd38e9882bc7a5c7a8337 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Nov 2018 19:01:57 +0100 Subject: [PATCH 3/6] libcli: Make smb2cli_notify_send cancellable Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- libcli/smb/smb2cli_notify.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/libcli/smb/smb2cli_notify.c b/libcli/smb/smb2cli_notify.c index 1a2a2793a32..9026a6b1c30 100644 --- a/libcli/smb/smb2cli_notify.c +++ b/libcli/smb/smb2cli_notify.c @@ -32,10 +32,12 @@ struct smb2cli_notify_state { uint32_t data_length; struct tevent_req *subreq; + struct tevent_req *timeout_subreq; }; static void smb2cli_notify_done(struct tevent_req *subreq); static void smb2cli_notify_timedout(struct tevent_req *subreq); +static bool smb2cli_notify_cancel(struct tevent_req *req); struct tevent_req *smb2cli_notify_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -49,7 +51,7 @@ struct tevent_req *smb2cli_notify_send(TALLOC_CTX *mem_ctx, uint32_t completion_filter, bool recursive) { - struct tevent_req *req, *subreq; + struct tevent_req *req; struct smb2cli_notify_state *state; uint8_t *fixed; uint16_t watch_tree; @@ -83,16 +85,33 @@ struct tevent_req *smb2cli_notify_send(TALLOC_CTX *mem_ctx, } tevent_req_set_callback(state->subreq, smb2cli_notify_done, req); - subreq = tevent_wakeup_send(state, ev, - timeval_current_ofs_msec(timeout_msec)); - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); + if (timeout_msec != 0) { + state->timeout_subreq = tevent_wakeup_send( + state, ev, timeval_current_ofs_msec(timeout_msec)); + if (tevent_req_nomem(state->timeout_subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback( + state->timeout_subreq, smb2cli_notify_timedout, req); } - tevent_req_set_callback(subreq, smb2cli_notify_timedout, req); + + tevent_req_set_cancel_fn(req, smb2cli_notify_cancel); return req; } +static bool smb2cli_notify_cancel(struct tevent_req *req) +{ + struct smb2cli_notify_state *state = tevent_req_data( + req, struct smb2cli_notify_state); + bool ok; + + TALLOC_FREE(state->timeout_subreq); + + ok = tevent_req_cancel(state->subreq); + return ok; +} + static void smb2cli_notify_timedout(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( -- 2.22.0.410.gd8fdbe21b5-goog From d4a8bed85512b6d80e2a256f0343b4f59e3f63ad Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Nov 2018 13:47:00 +0100 Subject: [PATCH 4/6] libsmb: Introduce cli_smb2_notify_send/recv This only existed as a sync wrapper where the underlying function could do send/recv already. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libsmb/cli_smb2_fnum.c | 207 ++++++++++++++++++++++++--------- source3/libsmb/cli_smb2_fnum.h | 12 ++ 2 files changed, 167 insertions(+), 52 deletions(-) diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c index 3cf16b325dd..35edec88809 100644 --- a/source3/libsmb/cli_smb2_fnum.c +++ b/source3/libsmb/cli_smb2_fnum.c @@ -4196,52 +4196,95 @@ NTSTATUS cli_smb2_ftruncate(struct cli_state *cli, return status; } -NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, - uint32_t buffer_size, uint32_t completion_filter, - bool recursive, TALLOC_CTX *mem_ctx, - struct notify_change **pchanges, - uint32_t *pnum_changes) +struct cli_smb2_notify_state { + struct tevent_req *subreq; + struct notify_change *changes; + size_t num_changes; +}; + +static void cli_smb2_notify_done(struct tevent_req *subreq); +static bool cli_smb2_notify_cancel(struct tevent_req *req); + +struct tevent_req *cli_smb2_notify_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint32_t buffer_size, + uint32_t completion_filter, + bool recursive) { - NTSTATUS status; + struct tevent_req *req = NULL; + struct cli_smb2_notify_state *state = NULL; struct smb2_hnd *ph = NULL; - TALLOC_CTX *frame = talloc_stackframe(); - uint8_t *base; - uint32_t len, ofs; - struct notify_change *changes = NULL; - size_t num_changes = 0; + NTSTATUS status; - if (smbXcli_conn_has_async_calls(cli->conn)) { - /* - * Can't use sync call while an async call is in flight - */ - status = NT_STATUS_INVALID_PARAMETER; - goto fail; + req = tevent_req_create(mem_ctx, &state, + struct cli_smb2_notify_state); + if (req == NULL) { + return NULL; } if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) { - status = NT_STATUS_INVALID_PARAMETER; - goto fail; + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); } status = map_fnum_to_smb2_handle(cli, fnum, &ph); - if (!NT_STATUS_IS_OK(status)) { - goto fail; + if (tevent_req_nterror(req, status)) { + return tevent_req_post(req, ev); } - status = smb2cli_notify(cli->conn, cli->timeout, - cli->smb2.session, cli->smb2.tcon, - buffer_size, - ph->fid_persistent, ph->fid_volatile, - completion_filter, recursive, - frame, &base, &len); + state->subreq = smb2cli_notify_send( + state, + ev, + cli->conn, + cli->timeout, + cli->smb2.session, + cli->smb2.tcon, + buffer_size, + ph->fid_persistent, + ph->fid_volatile, + completion_filter, + recursive); + if (tevent_req_nomem(state->subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(state->subreq, cli_smb2_notify_done, req); + tevent_req_set_cancel_fn(req, cli_smb2_notify_cancel); + return req; +} + +static bool cli_smb2_notify_cancel(struct tevent_req *req) +{ + struct cli_smb2_notify_state *state = tevent_req_data( + req, struct cli_smb2_notify_state); + bool ok; + + ok = tevent_req_cancel(state->subreq); + return ok; +} + +static void cli_smb2_notify_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_smb2_notify_state *state = tevent_req_data( + req, struct cli_smb2_notify_state); + uint8_t *base; + uint32_t len; + uint32_t ofs; + NTSTATUS status; + + status = smb2cli_notify_recv(subreq, state, &base, &len); + TALLOC_FREE(subreq); if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { - len = 0; - status = NT_STATUS_OK; + tevent_req_done(req); + return; } - - if (!NT_STATUS_IS_OK(status)) { - goto fail; + if (tevent_req_nterror(req, status)) { + return; } ofs = 0; @@ -4254,30 +4297,39 @@ NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, size_t namelen; bool ok; - tmp = talloc_realloc(frame, changes, struct notify_change, - num_changes + 1); - if (tmp == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; + tmp = talloc_realloc( + state, + state->changes, + struct notify_change, + state->num_changes + 1); + if (tevent_req_nomem(tmp, req)) { + return; } - changes = tmp; - c = &changes[num_changes]; - num_changes += 1; + state->changes = tmp; + c = &state->changes[state->num_changes]; + state->num_changes += 1; if (smb_buffer_oob(len, ofs, next_ofs) || smb_buffer_oob(len, ofs+12, file_name_length)) { - status = NT_STATUS_INVALID_NETWORK_RESPONSE; - goto fail; + tevent_req_nterror( + req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } c->action = IVAL(base, ofs+4); - ok = convert_string_talloc(changes, CH_UTF16LE, CH_UNIX, - base + ofs + 12, file_name_length, - &c->name, &namelen); + ok = convert_string_talloc( + state->changes, + CH_UTF16LE, + CH_UNIX, + base + ofs + 12, + file_name_length, + &c->name, + &namelen); if (!ok) { - status = NT_STATUS_INVALID_NETWORK_RESPONSE; - goto fail; + tevent_req_nterror( + req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } if (next_ofs == 0) { @@ -4286,13 +4338,64 @@ NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, ofs += next_ofs; } - *pchanges = talloc_move(mem_ctx, &changes); - *pnum_changes = num_changes; - status = NT_STATUS_OK; + tevent_req_done(req); +} -fail: - cli->raw_status = status; +NTSTATUS cli_smb2_notify_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct notify_change **pchanges, + uint32_t *pnum_changes) +{ + struct cli_smb2_notify_state *state = tevent_req_data( + req, struct cli_smb2_notify_state); + NTSTATUS status; + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *pchanges = talloc_move(mem_ctx, &state->changes); + *pnum_changes = state->num_changes; + return NT_STATUS_OK; +} + +NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, + uint32_t buffer_size, uint32_t completion_filter, + bool recursive, TALLOC_CTX *mem_ctx, + struct notify_change **pchanges, + uint32_t *pnum_changes) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + if (smbXcli_conn_has_async_calls(cli->conn)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + ev = samba_tevent_context_init(frame); + if (ev == NULL) { + goto fail; + } + req = cli_smb2_notify_send( + frame, + ev, + cli, + fnum, + buffer_size, + completion_filter, + recursive); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = cli_smb2_notify_recv(req, mem_ctx, pchanges, pnum_changes); +fail: TALLOC_FREE(frame); return status; } diff --git a/source3/libsmb/cli_smb2_fnum.h b/source3/libsmb/cli_smb2_fnum.h index 0ceddd0b9ab..4fce5fce1c3 100644 --- a/source3/libsmb/cli_smb2_fnum.h +++ b/source3/libsmb/cli_smb2_fnum.h @@ -237,6 +237,18 @@ NTSTATUS cli_smb2_shadow_copy_data(TALLOC_CTX *mem_ctx, NTSTATUS cli_smb2_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t newsize); +struct tevent_req *cli_smb2_notify_send( + TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli, + uint16_t fnum, + uint32_t buffer_size, + uint32_t completion_filter, + bool recursive); +NTSTATUS cli_smb2_notify_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct notify_change **pchanges, + uint32_t *pnum_changes); NTSTATUS cli_smb2_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size, uint32_t completion_filter, bool recursive, TALLOC_CTX *mem_ctx, -- 2.22.0.410.gd8fdbe21b5-goog From 4c984f3f50c74a9f9fc35583ac00576faab1d0c5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Nov 2018 13:53:01 +0100 Subject: [PATCH 5/6] libsmb: Make cli_notify_send/recv smb2-aware smb2-awareness only existed in the sync wrapper Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libsmb/clifile.c | 43 ++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 5f6e98ce460..1964a155005 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -5497,6 +5497,7 @@ struct cli_notify_state { }; static void cli_notify_done(struct tevent_req *subreq); +static void cli_notify_done_smb2(struct tevent_req *subreq); struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -5513,6 +5514,22 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, return NULL; } + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { + subreq = cli_smb2_notify_send( + state, + ev, + cli, + fnum, + buffer_size, + completion_filter, + recursive); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_notify_done_smb2, req); + return req; + } + SIVAL(state->setup, 0, completion_filter); SSVAL(state->setup, 4, fnum); SSVAL(state->setup, 6, recursive); @@ -5622,6 +5639,26 @@ static void cli_notify_done(struct tevent_req *subreq) tevent_req_done(req); } +static void cli_notify_done_smb2(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_notify_state *state = tevent_req_data( + req, struct cli_notify_state); + NTSTATUS status; + + status = cli_smb2_notify_recv( + subreq, + state, + &state->changes, + &state->num_changes); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; + } + tevent_req_done(req); +} + NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, uint32_t *pnum_changes, struct notify_change **pchanges) @@ -5649,12 +5686,6 @@ NTSTATUS cli_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size, struct tevent_req *req; NTSTATUS status = NT_STATUS_NO_MEMORY; - if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - return cli_smb2_notify(cli, fnum, buffer_size, - completion_filter, recursive, - mem_ctx, pchanges, pnum_changes); - } - frame = talloc_stackframe(); if (smbXcli_conn_has_async_calls(cli->conn)) { -- 2.22.0.410.gd8fdbe21b5-goog From 88d82b44c326cfb3ab1cf1f7288eada2566ab4bc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Nov 2018 21:11:57 +0100 Subject: [PATCH 6/6] libsmb: Make cli_notify_send cancellable Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Wed Nov 21 20:50:13 CET 2018 on sn-devel-144 --- source3/libsmb/clifile.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index 1964a155005..b50926307a5 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -5491,6 +5491,7 @@ NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname) ****************************************************************************/ struct cli_notify_state { + struct tevent_req *subreq; uint8_t setup[8]; uint32_t num_changes; struct notify_change *changes; @@ -5498,6 +5499,7 @@ struct cli_notify_state { static void cli_notify_done(struct tevent_req *subreq); static void cli_notify_done_smb2(struct tevent_req *subreq); +static bool cli_notify_cancel(struct tevent_req *req); struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -5505,7 +5507,7 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, uint32_t buffer_size, uint32_t completion_filter, bool recursive) { - struct tevent_req *req, *subreq; + struct tevent_req *req; struct cli_notify_state *state; unsigned old_timeout; @@ -5515,7 +5517,12 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, } if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - subreq = cli_smb2_notify_send( + /* + * Notifies should not time out + */ + old_timeout = cli_set_timeout(cli, 0); + + state->subreq = cli_smb2_notify_send( state, ev, cli, @@ -5523,11 +5530,15 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, buffer_size, completion_filter, recursive); - if (tevent_req_nomem(subreq, req)) { + + cli_set_timeout(cli, old_timeout); + + if (tevent_req_nomem(state->subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, cli_notify_done_smb2, req); - return req; + tevent_req_set_callback( + state->subreq, cli_notify_done_smb2, req); + goto done; } SIVAL(state->setup, 0, completion_filter); @@ -5539,7 +5550,7 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, */ old_timeout = cli_set_timeout(cli, 0); - subreq = cli_trans_send( + state->subreq = cli_trans_send( state, /* mem ctx. */ ev, /* event ctx. */ cli, /* cli_state. */ @@ -5561,13 +5572,25 @@ struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx, cli_set_timeout(cli, old_timeout); - if (tevent_req_nomem(subreq, req)) { + if (tevent_req_nomem(state->subreq, req)) { return tevent_req_post(req, ev); } - tevent_req_set_callback(subreq, cli_notify_done, req); + tevent_req_set_callback(state->subreq, cli_notify_done, req); +done: + tevent_req_set_cancel_fn(req, cli_notify_cancel); return req; } +static bool cli_notify_cancel(struct tevent_req *req) +{ + struct cli_notify_state *state = tevent_req_data( + req, struct cli_notify_state); + bool ok; + + ok = tevent_req_cancel(state->subreq); + return ok; +} + static void cli_notify_done(struct tevent_req *subreq) { struct tevent_req *req = tevent_req_callback_data( @@ -5582,6 +5605,7 @@ static void cli_notify_done(struct tevent_req *subreq) status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL, ¶ms, 0, &num_params, NULL, 0, NULL); TALLOC_FREE(subreq); + state->subreq = NULL; if (tevent_req_nterror(req, status)) { DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status))); return; -- 2.22.0.410.gd8fdbe21b5-goog