From: Volker Lendecke Date: Fri, 16 Nov 2018 20:01:19 +0000 (+0100) Subject: libsmb: Make cli_trans a normal subreq function X-Git-Tag: tdb-1.3.17~687 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bb843be3bfe4a9e15f345edb8acb290d63b28781;p=thirdparty%2Fsamba.git 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 --- 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; }