2 Unix SMB/CIFS implementation.
3 Infrastructure for async SMB client requests
4 Copyright (C) Volker Lendecke 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libsmb/libsmb.h"
22 #include "../lib/util/tevent_ntstatus.h"
23 #include "async_smb.h"
24 #include "../libcli/smb/smbXcli_base.h"
27 * Fetch a smb request's mid. Only valid after the request has been sent by
30 uint16_t cli_smb_req_mid(struct tevent_req
*req
)
32 return smb1cli_req_mid(req
);
35 void cli_smb_req_set_mid(struct tevent_req
*req
, uint16_t mid
)
37 smb1cli_req_set_mid(req
, mid
);
40 uint32_t cli_smb_req_seqnum(struct tevent_req
*req
)
42 return smb1cli_req_seqnum(req
);
45 void cli_smb_req_set_seqnum(struct tevent_req
*req
, uint32_t seqnum
)
47 smb1cli_req_set_seqnum(req
, seqnum
);
50 struct cli_smb_req_state
{
51 struct cli_state
*cli
;
53 struct tevent_req
*req
;
54 struct cli_smb_req_state
**ptr
;
57 static int cli_smb_req_state_destructor(struct cli_smb_req_state
*state
)
59 talloc_set_destructor(state
->ptr
, NULL
);
60 talloc_free(state
->ptr
);
64 static int cli_smb_req_state_ptr_destructor(struct cli_smb_req_state
**ptr
)
66 struct cli_smb_req_state
*state
= *ptr
;
67 void *parent
= talloc_parent(state
);
69 talloc_set_destructor(state
, NULL
);
71 talloc_reparent(state
, parent
, state
->req
);
76 struct tevent_req
*cli_smb_req_create(TALLOC_CTX
*mem_ctx
,
77 struct tevent_context
*ev
,
78 struct cli_state
*cli
,
80 uint8_t additional_flags
,
81 uint8_t wct
, uint16_t *vwv
,
83 struct iovec
*bytes_iov
)
85 struct cli_smb_req_state
*state
;
86 uint8_t clear_flags
= 0;
87 uint16_t additional_flags2
= 0;
88 uint16_t clear_flags2
= 0;
90 state
= talloc_zero(mem_ctx
, struct cli_smb_req_state
);
95 state
->smb_command
= smb_command
;
96 state
->ptr
= talloc(state
, struct cli_smb_req_state
*);
97 if (state
->ptr
== NULL
) {
103 if (cli
->case_sensitive
) {
104 clear_flags
|= FLAG_CASELESS_PATHNAMES
;
106 /* Default setting, case insensitive. */
107 additional_flags
|= FLAG_CASELESS_PATHNAMES
;
110 if ((smb1cli_conn_capabilities(cli
->conn
) & CAP_DFS
) && cli
->dfsroot
) {
111 additional_flags2
|= FLAGS2_DFS_PATHNAMES
;
114 state
->req
= smb1cli_req_create(state
, ev
, cli
->conn
, smb_command
,
115 additional_flags
, clear_flags
,
116 additional_flags2
, clear_flags2
,
121 wct
, vwv
, iov_count
, bytes_iov
);
122 if (state
->req
== NULL
) {
127 talloc_reparent(state
, state
->req
, state
->ptr
);
128 talloc_set_destructor(state
, cli_smb_req_state_destructor
);
129 talloc_set_destructor(state
->ptr
, cli_smb_req_state_ptr_destructor
);
134 NTSTATUS
cli_smb_req_send(struct tevent_req
*req
)
136 return smb1cli_req_chain_submit(&req
, 1);
139 struct tevent_req
*cli_smb_send(TALLOC_CTX
*mem_ctx
,
140 struct tevent_context
*ev
,
141 struct cli_state
*cli
,
143 uint8_t additional_flags
,
144 uint8_t wct
, uint16_t *vwv
,
146 const uint8_t *bytes
)
148 struct cli_smb_req_state
*state
;
149 uint8_t clear_flags
= 0;
150 uint16_t additional_flags2
= 0;
151 uint16_t clear_flags2
= 0;
153 state
= talloc_zero(mem_ctx
, struct cli_smb_req_state
);
158 state
->smb_command
= smb_command
;
159 state
->ptr
= talloc(state
, struct cli_smb_req_state
*);
160 if (state
->ptr
== NULL
) {
166 if (cli
->case_sensitive
) {
167 clear_flags
|= FLAG_CASELESS_PATHNAMES
;
169 /* Default setting, case insensitive. */
170 additional_flags
|= FLAG_CASELESS_PATHNAMES
;
173 if ((smb1cli_conn_capabilities(cli
->conn
) & CAP_DFS
) && cli
->dfsroot
) {
174 additional_flags2
|= FLAGS2_DFS_PATHNAMES
;
177 state
->req
= smb1cli_req_send(state
, ev
, cli
->conn
, smb_command
,
178 additional_flags
, clear_flags
,
179 additional_flags2
, clear_flags2
,
184 wct
, vwv
, num_bytes
, bytes
);
185 if (state
->req
== NULL
) {
190 talloc_reparent(state
, state
->req
, state
->ptr
);
191 talloc_set_destructor(state
, cli_smb_req_state_destructor
);
192 talloc_set_destructor(state
->ptr
, cli_smb_req_state_ptr_destructor
);
197 NTSTATUS
cli_smb_recv(struct tevent_req
*req
,
198 TALLOC_CTX
*mem_ctx
, uint8_t **pinbuf
,
199 uint8_t min_wct
, uint8_t *pwct
, uint16_t **pvwv
,
200 uint32_t *pnum_bytes
, uint8_t **pbytes
)
203 void *parent
= talloc_parent(req
);
204 struct cli_smb_req_state
*state
=
205 talloc_get_type(parent
,
206 struct cli_smb_req_state
);
207 struct iovec
*recv_iov
= NULL
;
209 uint16_t *vwv
= NULL
;
211 uint8_t *bytes
= NULL
;
213 bool is_expected
= false;
214 bool map_dos_errors
= true;
216 if (pinbuf
!= NULL
) {
225 if (pnum_bytes
!= NULL
) {
228 if (pbytes
!= NULL
) {
232 status
= smb1cli_req_recv(req
, req
,
237 NULL
, /* pvwv_offset */
240 NULL
, /* pbytes_offset */
242 NULL
, 0); /* expected */
245 if ((state
->smb_command
== SMBsesssetupX
) &&
246 NT_STATUS_EQUAL(status
,
247 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
249 * NT_STATUS_MORE_PROCESSING_REQUIRED is a
250 * valid return code for session setup
255 map_dos_errors
= state
->cli
->map_dos_errors
;
256 state
->cli
->raw_status
= status
;
257 talloc_free(state
->ptr
);
261 if (NT_STATUS_IS_DOS(status
) && map_dos_errors
) {
262 uint8_t eclass
= NT_STATUS_DOS_CLASS(status
);
263 uint16_t ecode
= NT_STATUS_DOS_CODE(status
);
265 * TODO: is it really a good idea to do a mapping here?
267 * The old cli_pull_error() also does it, so I do not change
270 status
= dos_to_ntstatus(eclass
, ecode
);
273 if (!NT_STATUS_IS_ERR(status
)) {
278 TALLOC_FREE(recv_iov
);
283 TALLOC_FREE(recv_iov
);
284 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
293 if (pnum_bytes
!= NULL
) {
294 *pnum_bytes
= num_bytes
;
296 if (pbytes
!= NULL
) {
300 if (pinbuf
!= NULL
&& mem_ctx
!= NULL
) {
301 if (talloc_reference_count(inbuf
) == 0) {
302 *pinbuf
= talloc_move(mem_ctx
, &inbuf
);
303 TALLOC_FREE(recv_iov
);
312 size_t cli_smb_wct_ofs(struct tevent_req
**reqs
, int num_reqs
)
314 return smb1cli_req_wct_ofs(reqs
, num_reqs
);
317 NTSTATUS
cli_smb_chain_send(struct tevent_req
**reqs
, int num_reqs
)
319 return smb1cli_req_chain_submit(reqs
, num_reqs
);