From f9ad5cd133b57b66a3b71ede7829ef8c226f2224 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 12 Nov 2009 23:07:21 +0100 Subject: s3: Convert cli_unix_extensions_version to async --- source3/client/client.c | 17 +++-- source3/include/proto.h | 12 +++- source3/libsmb/clidfs.c | 6 +- source3/libsmb/clifsinfo.c | 164 +++++++++++++++++++++++++++++++++------------ source3/torture/torture.c | 15 +++-- 5 files changed, 159 insertions(+), 55 deletions(-) diff --git a/source3/client/client.c b/source3/client/client.c index 6a3e73c710..f81762a563 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -2449,14 +2449,18 @@ static int cmd_posix(void) uint16 major, minor; uint32 caplow, caphigh; char *caps; + NTSTATUS status; if (!SERVER_HAS_UNIX_CIFS(cli)) { d_printf("Server doesn't support UNIX CIFS extensions.\n"); return 1; } - if (!cli_unix_extensions_version(cli, &major, &minor, &caplow, &caphigh)) { - d_printf("Can't get UNIX CIFS extensions version from server.\n"); + status = cli_unix_extensions_version(cli, &major, &minor, &caplow, + &caphigh); + if (!NT_STATUS_IS_OK(status)) { + d_printf("Can't get UNIX CIFS extensions version from " + "server: %s\n", nt_errstr(status)); return 1; } @@ -2983,6 +2987,7 @@ static int cmd_getfacl(void) uint16 num_file_acls = 0; uint16 num_dir_acls = 0; uint16 i; + NTSTATUS status; if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) { d_printf("getfacl filename\n"); @@ -3006,9 +3011,11 @@ static int cmd_getfacl(void) return 1; } - if (!cli_unix_extensions_version(targetcli, &major, &minor, - &caplow, &caphigh)) { - d_printf("Can't get UNIX CIFS version from server.\n"); + status = cli_unix_extensions_version(targetcli, &major, &minor, + &caplow, &caphigh); + if (!NT_STATUS_IS_OK(status)) { + d_printf("Can't get UNIX CIFS version from server: %s.\n", + nt_errstr(status)); return 1; } diff --git a/source3/include/proto.h b/source3/include/proto.h index 0eb5815f64..f9a2a50ec2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2682,8 +2682,16 @@ NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, /* The following definitions come from libsmb/clifsinfo.c */ -bool cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, uint16 *pminor, - uint32 *pcaplow, uint32 *pcaphigh); +struct tevent_req *cli_unix_extensions_version_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli); +NTSTATUS cli_unix_extensions_version_recv(struct tevent_req *req, + uint16_t *pmajor, uint16_t *pminor, + uint32_t *pcaplow, + uint32_t *pcaphigh); +NTSTATUS cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, + uint16 *pminor, uint32 *pcaplow, + uint32 *pcaphigh); bool cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, uint16 minor, uint32 caplow, uint32 caphigh); bool cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr); diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 33529595a2..0afb75975e 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -322,8 +322,10 @@ static struct cli_state *cli_cm_connect(TALLOC_CTX *ctx, if (referring_cli && referring_cli->posix_capabilities) { uint16 major, minor; uint32 caplow, caphigh; - if (cli_unix_extensions_version(cli, &major, - &minor, &caplow, &caphigh)) { + NTSTATUS status; + status = cli_unix_extensions_version(cli, &major, &minor, + &caplow, &caphigh); + if (NT_STATUS_IS_OK(status)) { cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh); diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 308a6f7215..03ec54ab8c 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -25,59 +25,136 @@ Get UNIX extensions version info. ****************************************************************************/ -bool cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, uint16 *pminor, - uint32 *pcaplow, uint32 *pcaphigh) +struct cli_unix_extensions_version_state { + uint16_t setup[1]; + uint8_t param[2]; + uint16_t major, minor; + uint32_t caplow, caphigh; +}; + +static void cli_unix_extensions_version_done(struct tevent_req *subreq); + +struct tevent_req *cli_unix_extensions_version_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct cli_state *cli) { - bool ret = False; - uint16 setup; - char param[2]; - char *rparam=NULL, *rdata=NULL; - unsigned int rparam_count=0, rdata_count=0; - - setup = TRANSACT2_QFSINFO; - - SSVAL(param,0,SMB_QUERY_CIFS_UNIX_INFO); + struct tevent_req *req, *subreq; + struct cli_unix_extensions_version_state *state; - if (!cli_send_trans(cli, SMBtrans2, - NULL, - 0, 0, - &setup, 1, 0, - param, 2, 0, - NULL, 0, 560)) { - goto cleanup; + req = tevent_req_create(mem_ctx, &state, + struct cli_unix_extensions_version_state); + if (req == NULL) { + return NULL; } + SSVAL(state->setup, 0, TRANSACT2_QFSINFO); + SSVAL(state->param, 0, SMB_QUERY_CIFS_UNIX_INFO); - if (!cli_receive_trans(cli, SMBtrans2, - &rparam, &rparam_count, - &rdata, &rdata_count)) { - goto cleanup; + subreq = cli_trans_send(state, ev, cli, SMBtrans2, + NULL, 0, 0, 0, + state->setup, 1, 0, + state->param, 2, 0, + NULL, 0, 560); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, cli_unix_extensions_version_done, req); + return req; +} - if (cli_is_error(cli)) { - ret = False; - goto cleanup; - } else { - ret = True; +static void cli_unix_extensions_version_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_unix_extensions_version_state *state = tevent_req_data( + req, struct cli_unix_extensions_version_state); + uint8_t *data; + uint32_t num_data; + NTSTATUS status; + + status = cli_trans_recv(subreq, state, NULL, NULL, NULL, NULL, + &data, &num_data); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + if (num_data < 12) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; } - if (rdata_count < 12) { - goto cleanup; + state->major = SVAL(data, 0); + state->minor = SVAL(data, 2); + state->caplow = IVAL(data, 4); + state->caphigh = IVAL(data, 8); + TALLOC_FREE(data); + tevent_req_done(req); +} + +NTSTATUS cli_unix_extensions_version_recv(struct tevent_req *req, + uint16_t *pmajor, uint16_t *pminor, + uint32_t *pcaplow, + uint32_t *pcaphigh) +{ + struct cli_unix_extensions_version_state *state = tevent_req_data( + req, struct cli_unix_extensions_version_state); + NTSTATUS status; + + if (tevent_req_is_nterror(req, &status)) { + return status; + } + *pmajor = state->major; + *pminor = state->minor; + *pcaplow = state->caplow; + *pcaphigh = state->caphigh; + return NT_STATUS_OK; +} + +NTSTATUS cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, + uint16 *pminor, uint32 *pcaplow, + uint32 *pcaphigh) +{ + TALLOC_CTX *frame = talloc_stackframe(); + struct event_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_OK; + + if (cli_has_async_calls(cli)) { + /* + * Can't use sync call while an async call is in flight + */ + status = NT_STATUS_INVALID_PARAMETER; + goto fail; } - *pmajor = SVAL(rdata,0); - *pminor = SVAL(rdata,2); - cli->posix_capabilities = *pcaplow = IVAL(rdata,4); - *pcaphigh = IVAL(rdata,8); + ev = event_context_init(frame); + if (ev == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } - /* todo: but not yet needed - * return the other stuff - */ + req = cli_unix_extensions_version_send(frame, ev, cli); + if (req == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } -cleanup: - SAFE_FREE(rparam); - SAFE_FREE(rdata); + if (!tevent_req_poll(req, ev)) { + status = map_nt_error_from_unix(errno); + goto fail; + } - return ret; + status = cli_unix_extensions_version_recv(req, pmajor, pminor, pcaplow, + pcaphigh); + if (NT_STATUS_IS_OK(status)) { + cli->posix_capabilities = *pcaplow; + } + fail: + TALLOC_FREE(frame); + if (!NT_STATUS_IS_OK(status)) { + cli_set_error(cli, status); + } + return status; } /**************************************************************************** @@ -789,12 +866,17 @@ NTSTATUS cli_force_encryption(struct cli_state *c, { uint16 major, minor; uint32 caplow, caphigh; + NTSTATUS status; if (!SERVER_HAS_UNIX_CIFS(c)) { return NT_STATUS_NOT_SUPPORTED; } - if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) { + status = cli_unix_extensions_version(c, &major, &minor, &caplow, + &caphigh); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("cli_force_encryption: cli_unix_extensions_version " + "returned %s\n", nt_errstr(status))); return NT_STATUS_UNKNOWN_REVISION; } diff --git a/source3/torture/torture.c b/source3/torture/torture.c index bda82f2b74..9abcabde89 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -136,10 +136,12 @@ static bool force_cli_encryption(struct cli_state *c, return false; } - if (!cli_unix_extensions_version(c, &major, &minor, &caplow, &caphigh)) { + status = cli_unix_extensions_version(c, &major, &minor, &caplow, + &caphigh); + if (!NT_STATUS_IS_OK(status)) { d_printf("Encryption required and " "can't get UNIX CIFS extensions " - "version from server.\n"); + "version from server: %s\n", nt_errstr(status)); return false; } @@ -4367,6 +4369,7 @@ static bool run_simple_posix_open_test(int dummy) uint16_t fnum1 = (uint16_t)-1; SMB_STRUCT_STAT sbuf; bool correct = false; + NTSTATUS status; printf("Starting simple POSIX open test\n"); @@ -4381,9 +4384,11 @@ static bool run_simple_posix_open_test(int dummy) return false; } - if (!cli_unix_extensions_version(cli1, &major, - &minor, &caplow, &caphigh)) { - printf("Server didn't return UNIX CIFS extensions.\n"); + status = cli_unix_extensions_version(cli1, &major, &minor, &caplow, + &caphigh); + if (!NT_STATUS_IS_OK(status)) { + printf("Server didn't return UNIX CIFS extensions: %s\n", + nt_errstr(status)); return false; } -- cgit