2 Unix SMB/CIFS implementation.
3 client transaction calls
4 Copyright (C) Andrew Tridgell 1994-1998
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 "system/network.h"
22 #include "../lib/util/tevent_ntstatus.h"
23 #include "../libcli/smb/smb_common.h"
24 #include "../libcli/smb/smbXcli_base.h"
26 struct trans_recvblob
{
28 uint32_t max
, total
, received
;
31 struct smb1cli_trans_state
{
32 struct smbXcli_conn
*conn
;
33 struct tevent_context
*ev
;
35 uint8_t additional_flags
;
37 uint16_t additional_flags2
;
38 uint16_t clear_flags2
;
39 uint32_t timeout_msec
;
43 struct smbXcli_session
*session
;
44 const char *pipe_name
;
45 uint8_t *pipe_name_conv
;
46 size_t pipe_name_conv_len
;
51 uint8_t num_setup
, max_setup
;
53 uint32_t num_param
, param_sent
;
55 uint32_t num_data
, data_sent
;
59 struct trans_recvblob rparam
;
60 struct trans_recvblob rdata
;
70 struct tevent_req
*primary_subreq
;
73 static void smb1cli_trans_cleanup_primary(struct smb1cli_trans_state
*state
)
75 if (state
->primary_subreq
) {
76 smb1cli_req_set_mid(state
->primary_subreq
, 0);
77 smbXcli_req_unset_pending(state
->primary_subreq
);
78 TALLOC_FREE(state
->primary_subreq
);
82 static int smb1cli_trans_state_destructor(struct smb1cli_trans_state
*state
)
84 smb1cli_trans_cleanup_primary(state
);
88 static NTSTATUS
smb1cli_pull_trans(uint8_t *inhdr
,
95 uint8_t smb_cmd
, bool expect_first_reply
,
96 uint8_t *pnum_setup
, uint16_t **psetup
,
97 uint32_t *ptotal_param
, uint32_t *pnum_param
,
98 uint32_t *pparam_disp
, uint8_t **pparam
,
99 uint32_t *ptotal_data
, uint32_t *pnum_data
,
100 uint32_t *pdata_disp
, uint8_t **pdata
)
102 uint32_t param_ofs
, data_ofs
;
103 uint8_t expected_num_setup
;
104 uint32_t max_bytes
= UINT32_MAX
- bytes_ofs
;
107 if (num_bytes
> max_bytes
) {
108 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
111 bytes_end
= bytes_ofs
+ num_bytes
;
113 if (expect_first_reply
) {
114 if ((wct
!= 0) || (num_bytes
!= 0)) {
115 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
124 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
126 expected_num_setup
= wct
- 10;
127 *ptotal_param
= SVAL(vwv
+ 0, 0);
128 *ptotal_data
= SVAL(vwv
+ 1, 0);
129 *pnum_param
= SVAL(vwv
+ 3, 0);
130 param_ofs
= SVAL(vwv
+ 4, 0);
131 *pparam_disp
= SVAL(vwv
+ 5, 0);
132 *pnum_data
= SVAL(vwv
+ 6, 0);
133 data_ofs
= SVAL(vwv
+ 7, 0);
134 *pdata_disp
= SVAL(vwv
+ 8, 0);
135 *pnum_setup
= CVAL(vwv
+ 9, 0);
136 if (expected_num_setup
< (*pnum_setup
)) {
137 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
144 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
146 expected_num_setup
= wct
- 18;
147 *ptotal_param
= IVAL(vwv
, 3);
148 *ptotal_data
= IVAL(vwv
, 7);
149 *pnum_param
= IVAL(vwv
, 11);
150 param_ofs
= IVAL(vwv
, 15);
151 *pparam_disp
= IVAL(vwv
, 19);
152 *pnum_data
= IVAL(vwv
, 23);
153 data_ofs
= IVAL(vwv
, 27);
154 *pdata_disp
= IVAL(vwv
, 31);
155 *pnum_setup
= CVAL(vwv
, 35);
156 if (expected_num_setup
< (*pnum_setup
)) {
157 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
163 return NT_STATUS_INTERNAL_ERROR
;
167 * Check for buffer overflows. data_ofs needs to be checked against
168 * the incoming buffer length, data_disp against the total
169 * length. Likewise for param_ofs/param_disp.
172 if (smb_buffer_oob(bytes_end
, param_ofs
, *pnum_param
)
173 || smb_buffer_oob(*ptotal_param
, *pparam_disp
, *pnum_param
)
174 || smb_buffer_oob(bytes_end
, data_ofs
, *pnum_data
)
175 || smb_buffer_oob(*ptotal_data
, *pdata_disp
, *pnum_data
)) {
176 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
179 *pparam
= (uint8_t *)inhdr
+ param_ofs
;
180 *pdata
= (uint8_t *)inhdr
+ data_ofs
;
185 static NTSTATUS
smb1cli_trans_pull_blob(TALLOC_CTX
*mem_ctx
,
186 struct trans_recvblob
*blob
,
187 uint32_t total
, uint32_t thistime
,
188 uint8_t *buf
, uint32_t displacement
)
190 if (blob
->data
== NULL
) {
191 if (total
> blob
->max
) {
192 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
195 blob
->data
= talloc_array(mem_ctx
, uint8_t, total
);
196 if (blob
->data
== NULL
) {
197 return NT_STATUS_NO_MEMORY
;
201 if (total
> blob
->total
) {
202 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
206 memcpy(blob
->data
+ displacement
, buf
, thistime
);
207 blob
->received
+= thistime
;
213 static void smb1cli_trans_format(struct smb1cli_trans_state
*state
,
218 struct iovec
*iov
= state
->iov
;
219 uint8_t *pad
= state
->pad
;
220 uint16_t *vwv
= state
->vwv
;
221 uint32_t param_offset
;
222 uint32_t this_param
= 0;
224 uint32_t data_offset
;
225 uint32_t this_data
= 0;
227 uint32_t useable_space
;
229 uint32_t max_trans
= smb1cli_conn_max_xmit(state
->conn
);
233 if ((state
->param_sent
!= 0) || (state
->data_sent
!= 0)) {
234 /* The secondary commands are one after the primary ones */
238 param_offset
= MIN_SMB_SIZE
;
242 if (smbXcli_conn_use_unicode(state
->conn
)) {
244 iov
[0].iov_base
= (void *)pad
;
249 iov
[0].iov_base
= (void *)state
->pipe_name_conv
;
250 iov
[0].iov_len
= state
->pipe_name_conv_len
;
251 wct
= 14 + state
->num_setup
;
252 param_offset
+= iov
[0].iov_len
;
257 pad
[1] = 'D'; /* Copy this from "old" 3.0 behaviour */
259 iov
[0].iov_base
= (void *)pad
;
261 wct
= 14 + state
->num_setup
;
272 wct
= 19 + state
->num_setup
;
279 param_offset
+= wct
* sizeof(uint16_t);
280 useable_space
= max_trans
- param_offset
;
282 param_pad
= param_offset
% 4;
284 param_pad
= MIN(param_pad
, useable_space
);
285 iov
[0].iov_base
= (void *)state
->zero_pad
;
286 iov
[0].iov_len
= param_pad
;
288 param_offset
+= param_pad
;
290 useable_space
= max_trans
- param_offset
;
292 if (state
->param_sent
< state
->num_param
) {
293 this_param
= MIN(state
->num_param
- state
->param_sent
,
295 iov
[0].iov_base
= (void *)(state
->param
+ state
->param_sent
);
296 iov
[0].iov_len
= this_param
;
300 data_offset
= param_offset
+ this_param
;
301 useable_space
= max_trans
- data_offset
;
303 data_pad
= data_offset
% 4;
305 data_pad
= MIN(data_pad
, useable_space
);
306 iov
[0].iov_base
= (void *)state
->zero_pad
;
307 iov
[0].iov_len
= data_pad
;
309 data_offset
+= data_pad
;
311 useable_space
= max_trans
- data_offset
;
313 if (state
->data_sent
< state
->num_data
) {
314 this_data
= MIN(state
->num_data
- state
->data_sent
,
316 iov
[0].iov_base
= (void *)(state
->data
+ state
->data_sent
);
317 iov
[0].iov_len
= this_data
;
321 DEBUG(10, ("num_setup=%u, max_setup=%u, "
322 "param_total=%u, this_param=%u, max_param=%u, "
323 "data_total=%u, this_data=%u, max_data=%u, "
324 "param_offset=%u, param_pad=%u, param_disp=%u, "
325 "data_offset=%u, data_pad=%u, data_disp=%u\n",
326 (unsigned)state
->num_setup
, (unsigned)state
->max_setup
,
327 (unsigned)state
->num_param
, (unsigned)this_param
,
328 (unsigned)state
->rparam
.max
,
329 (unsigned)state
->num_data
, (unsigned)this_data
,
330 (unsigned)state
->rdata
.max
,
331 (unsigned)param_offset
, (unsigned)param_pad
,
332 (unsigned)state
->param_sent
,
333 (unsigned)data_offset
, (unsigned)data_pad
,
334 (unsigned)state
->data_sent
));
339 SSVAL(vwv
+ 0, 0, state
->num_param
);
340 SSVAL(vwv
+ 1, 0, state
->num_data
);
341 SSVAL(vwv
+ 2, 0, state
->rparam
.max
);
342 SSVAL(vwv
+ 3, 0, state
->rdata
.max
);
343 SCVAL(vwv
+ 4, 0, state
->max_setup
);
344 SCVAL(vwv
+ 4, 1, 0); /* reserved */
345 SSVAL(vwv
+ 5, 0, state
->flags
);
346 SIVAL(vwv
+ 6, 0, 0); /* timeout */
347 SSVAL(vwv
+ 8, 0, 0); /* reserved */
348 SSVAL(vwv
+ 9, 0, this_param
);
349 SSVAL(vwv
+10, 0, param_offset
);
350 SSVAL(vwv
+11, 0, this_data
);
351 SSVAL(vwv
+12, 0, data_offset
);
352 SCVAL(vwv
+13, 0, state
->num_setup
);
353 SCVAL(vwv
+13, 1, 0); /* reserved */
354 memcpy(vwv
+ 14, state
->setup
,
355 sizeof(uint16_t) * state
->num_setup
);
359 SSVAL(vwv
+ 0, 0, state
->num_param
);
360 SSVAL(vwv
+ 1, 0, state
->num_data
);
361 SSVAL(vwv
+ 2, 0, this_param
);
362 SSVAL(vwv
+ 3, 0, param_offset
);
363 SSVAL(vwv
+ 4, 0, state
->param_sent
);
364 SSVAL(vwv
+ 5, 0, this_data
);
365 SSVAL(vwv
+ 6, 0, data_offset
);
366 SSVAL(vwv
+ 7, 0, state
->data_sent
);
367 if (cmd
== SMBtranss2
) {
368 SSVAL(vwv
+ 8, 0, state
->fid
);
372 SCVAL(vwv
+ 0, 0, state
->max_setup
);
373 SSVAL(vwv
+ 0, 1, 0); /* reserved */
374 SIVAL(vwv
+ 1, 1, state
->num_param
);
375 SIVAL(vwv
+ 3, 1, state
->num_data
);
376 SIVAL(vwv
+ 5, 1, state
->rparam
.max
);
377 SIVAL(vwv
+ 7, 1, state
->rdata
.max
);
378 SIVAL(vwv
+ 9, 1, this_param
);
379 SIVAL(vwv
+11, 1, param_offset
);
380 SIVAL(vwv
+13, 1, this_data
);
381 SIVAL(vwv
+15, 1, data_offset
);
382 SCVAL(vwv
+17, 1, state
->num_setup
);
383 SSVAL(vwv
+18, 0, state
->function
);
384 memcpy(vwv
+ 19, state
->setup
,
385 sizeof(uint16_t) * state
->num_setup
);
388 SSVAL(vwv
+ 0, 0, 0); /* reserved */
389 SCVAL(vwv
+ 1, 0, 0); /* reserved */
390 SIVAL(vwv
+ 1, 1, state
->num_param
);
391 SIVAL(vwv
+ 3, 1, state
->num_data
);
392 SIVAL(vwv
+ 5, 1, this_param
);
393 SIVAL(vwv
+ 7, 1, param_offset
);
394 SIVAL(vwv
+ 9, 1, state
->param_sent
);
395 SIVAL(vwv
+11, 1, this_data
);
396 SIVAL(vwv
+13, 1, data_offset
);
397 SIVAL(vwv
+15, 1, state
->data_sent
);
398 SCVAL(vwv
+17, 1, 0); /* reserved */
402 state
->param_sent
+= this_param
;
403 state
->data_sent
+= this_data
;
406 *piov_count
= iov
- state
->iov
;
409 static bool smb1cli_trans_cancel(struct tevent_req
*req
);
410 static void smb1cli_trans_done(struct tevent_req
*subreq
);
412 struct tevent_req
*smb1cli_trans_send(
413 TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
414 struct smbXcli_conn
*conn
, uint8_t cmd
,
415 uint8_t additional_flags
, uint8_t clear_flags
,
416 uint16_t additional_flags2
, uint16_t clear_flags2
,
417 uint32_t timeout_msec
,
418 uint32_t pid
, uint16_t tid
,
419 struct smbXcli_session
*session
,
420 const char *pipe_name
, uint16_t fid
, uint16_t function
, int flags
,
421 uint16_t *setup
, uint8_t num_setup
, uint8_t max_setup
,
422 uint8_t *param
, uint32_t num_param
, uint32_t max_param
,
423 uint8_t *data
, uint32_t num_data
, uint32_t max_data
)
425 struct tevent_req
*req
, *subreq
;
426 struct smb1cli_trans_state
*state
;
432 req
= tevent_req_create(mem_ctx
, &state
,
433 struct smb1cli_trans_state
);
438 if ((cmd
== SMBtrans
) || (cmd
== SMBtrans2
)) {
439 if ((num_param
> 0xffff) || (max_param
> 0xffff)
440 || (num_data
> 0xffff) || (max_data
> 0xffff)) {
441 DEBUG(3, ("Attempt to send invalid trans2 request "
442 "(setup %u, params %u/%u, data %u/%u)\n",
444 (unsigned)num_param
, (unsigned)max_param
,
445 (unsigned)num_data
, (unsigned)max_data
));
446 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
447 return tevent_req_post(req
, ev
);
452 * The largest wct will be for nttrans (19+num_setup). Make sure we
453 * don't overflow state->vwv in smb1cli_trans_format.
456 if ((num_setup
+ 19) > ARRAY_SIZE(state
->vwv
)) {
457 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER_MIX
);
458 return tevent_req_post(req
, ev
);
464 state
->additional_flags
= additional_flags
;
465 state
->clear_flags
= clear_flags
;
466 state
->additional_flags2
= additional_flags2
;
467 state
->clear_flags2
= clear_flags2
;
468 state
->timeout_msec
= timeout_msec
;
469 state
->flags
= flags
;
470 state
->num_rsetup
= 0;
471 state
->rsetup
= NULL
;
474 state
->session
= session
;
475 ZERO_STRUCT(state
->rparam
);
476 ZERO_STRUCT(state
->rdata
);
478 if (smbXcli_conn_use_unicode(conn
)) {
479 charset
= CH_UTF16LE
;
484 if ((pipe_name
!= NULL
)
485 && (!convert_string_talloc(state
, CH_UNIX
, charset
,
486 pipe_name
, strlen(pipe_name
) + 1,
487 &state
->pipe_name_conv
,
488 &state
->pipe_name_conv_len
))) {
489 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
490 return tevent_req_post(req
, ev
);
492 state
->fid
= fid
; /* trans2 */
493 state
->function
= function
; /* nttrans */
495 state
->setup
= setup
;
496 state
->num_setup
= num_setup
;
497 state
->max_setup
= max_setup
;
499 state
->param
= param
;
500 state
->num_param
= num_param
;
501 state
->param_sent
= 0;
502 state
->rparam
.max
= max_param
;
505 state
->num_data
= num_data
;
506 state
->data_sent
= 0;
507 state
->rdata
.max
= max_data
;
509 smb1cli_trans_format(state
, &wct
, &iov_count
);
511 subreq
= smb1cli_req_create(state
, ev
, conn
, cmd
,
512 state
->additional_flags
,
514 state
->additional_flags2
,
517 state
->pid
, state
->tid
,
520 iov_count
, state
->iov
);
521 if (tevent_req_nomem(subreq
, req
)) {
522 return tevent_req_post(req
, ev
);
524 status
= smb1cli_req_chain_submit(&subreq
, 1);
525 if (tevent_req_nterror(req
, status
)) {
526 return tevent_req_post(req
, state
->ev
);
528 tevent_req_set_callback(subreq
, smb1cli_trans_done
, req
);
531 * Now get the MID of the primary request
532 * and mark it as persistent. This means
533 * we will able to send and receive multiple
534 * SMB pdus using this MID in both directions
535 * (including correct SMB signing).
537 state
->mid
= smb1cli_req_mid(subreq
);
538 smb1cli_req_set_mid(subreq
, state
->mid
);
539 state
->primary_subreq
= subreq
;
540 talloc_set_destructor(state
, smb1cli_trans_state_destructor
);
542 tevent_req_set_cancel_fn(req
, smb1cli_trans_cancel
);
547 static bool smb1cli_trans_cancel(struct tevent_req
*req
)
549 struct smb1cli_trans_state
*state
=
551 struct smb1cli_trans_state
);
553 if (state
->primary_subreq
== NULL
) {
557 return tevent_req_cancel(state
->primary_subreq
);
560 static void smb1cli_trans_done2(struct tevent_req
*subreq
);
562 static void smb1cli_trans_done(struct tevent_req
*subreq
)
564 struct tevent_req
*req
=
565 tevent_req_callback_data(subreq
,
567 struct smb1cli_trans_state
*state
=
569 struct smb1cli_trans_state
);
572 struct iovec
*recv_iov
= NULL
;
580 uint8_t num_setup
= 0;
581 uint16_t *setup
= NULL
;
582 uint32_t total_param
= 0;
583 uint32_t num_param
= 0;
584 uint32_t param_disp
= 0;
585 uint32_t total_data
= 0;
586 uint32_t num_data
= 0;
587 uint32_t data_disp
= 0;
588 uint8_t *param
= NULL
;
589 uint8_t *data
= NULL
;
591 status
= smb1cli_req_recv(subreq
, state
,
601 NULL
, 0); /* expected */
603 * Do not TALLOC_FREE(subreq) here, we might receive more than
604 * one response for the same mid.
608 * We can receive something like STATUS_MORE_ENTRIES, so don't use
609 * !NT_STATUS_IS_OK(status) here.
612 if (NT_STATUS_IS_ERR(status
)) {
616 if (recv_iov
== NULL
) {
617 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
620 state
->status
= status
;
622 sent_all
= ((state
->param_sent
== state
->num_param
)
623 && (state
->data_sent
== state
->num_data
));
625 status
= smb1cli_pull_trans(
626 inhdr
, wct
, vwv
, vwv_ofs
,
627 num_bytes
, bytes
, bytes_ofs
,
628 state
->cmd
, !sent_all
, &num_setup
, &setup
,
629 &total_param
, &num_param
, ¶m_disp
, ¶m
,
630 &total_data
, &num_data
, &data_disp
, &data
);
632 if (!NT_STATUS_IS_OK(status
)) {
638 struct tevent_req
*subreq2
;
640 smb1cli_trans_format(state
, &wct
, &iov_count
);
642 subreq2
= smb1cli_req_create(state
, state
->ev
, state
->conn
,
644 state
->additional_flags
,
646 state
->additional_flags2
,
649 state
->pid
, state
->tid
,
652 iov_count
, state
->iov
);
653 if (tevent_req_nomem(subreq2
, req
)) {
656 smb1cli_req_set_mid(subreq2
, state
->mid
);
658 status
= smb1cli_req_chain_submit(&subreq2
, 1);
660 if (!NT_STATUS_IS_OK(status
)) {
663 tevent_req_set_callback(subreq2
, smb1cli_trans_done2
, req
);
668 status
= smb1cli_trans_pull_blob(
669 state
, &state
->rparam
, total_param
, num_param
, param
,
672 if (!NT_STATUS_IS_OK(status
)) {
673 DEBUG(10, ("Pulling params failed: %s\n", nt_errstr(status
)));
677 status
= smb1cli_trans_pull_blob(
678 state
, &state
->rdata
, total_data
, num_data
, data
,
681 if (!NT_STATUS_IS_OK(status
)) {
682 DEBUG(10, ("Pulling data failed: %s\n", nt_errstr(status
)));
686 if ((state
->rparam
.total
== state
->rparam
.received
)
687 && (state
->rdata
.total
== state
->rdata
.received
)) {
688 state
->recv_flags2
= SVAL(inhdr
, HDR_FLG2
);
689 smb1cli_trans_cleanup_primary(state
);
690 tevent_req_done(req
);
694 TALLOC_FREE(recv_iov
);
699 smb1cli_trans_cleanup_primary(state
);
700 tevent_req_nterror(req
, status
);
703 static void smb1cli_trans_done2(struct tevent_req
*subreq2
)
705 struct tevent_req
*req
=
706 tevent_req_callback_data(subreq2
,
708 struct smb1cli_trans_state
*state
=
710 struct smb1cli_trans_state
);
716 * First backup the seqnum of the secondary request
717 * and attach it to the primary request.
719 seqnum
= smb1cli_req_seqnum(subreq2
);
720 smb1cli_req_set_seqnum(state
->primary_subreq
, seqnum
);
722 /* This was a one way request */
723 status
= smb1cli_req_recv(subreq2
, state
,
728 NULL
, /* pvwv_offset */
729 NULL
, /* pnum_bytes */
731 NULL
, /* pbytes_offset */
733 NULL
, 0); /* expected */
734 TALLOC_FREE(subreq2
);
736 if (!NT_STATUS_IS_OK(status
)) {
740 sent_all
= ((state
->param_sent
== state
->num_param
)
741 && (state
->data_sent
== state
->num_data
));
747 smb1cli_trans_format(state
, &wct
, &iov_count
);
749 subreq2
= smb1cli_req_create(state
, state
->ev
, state
->conn
,
751 state
->additional_flags
,
753 state
->additional_flags2
,
756 state
->pid
, state
->tid
,
759 iov_count
, state
->iov
);
760 if (tevent_req_nomem(subreq2
, req
)) {
763 smb1cli_req_set_mid(subreq2
, state
->mid
);
765 status
= smb1cli_req_chain_submit(&subreq2
, 1);
767 if (!NT_STATUS_IS_OK(status
)) {
770 tevent_req_set_callback(subreq2
, smb1cli_trans_done2
, req
);
777 smb1cli_trans_cleanup_primary(state
);
778 tevent_req_nterror(req
, status
);
781 NTSTATUS
smb1cli_trans_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
782 uint16_t *recv_flags2
,
783 uint16_t **setup
, uint8_t min_setup
,
785 uint8_t **param
, uint32_t min_param
,
787 uint8_t **data
, uint32_t min_data
,
790 struct smb1cli_trans_state
*state
=
792 struct smb1cli_trans_state
);
795 smb1cli_trans_cleanup_primary(state
);
797 if (tevent_req_is_nterror(req
, &status
)) {
798 if (!NT_STATUS_IS_ERR(status
)) {
799 status
= NT_STATUS_INVALID_NETWORK_RESPONSE
;
801 tevent_req_received(req
);
805 if ((state
->num_rsetup
< min_setup
)
806 || (state
->rparam
.total
< min_param
)
807 || (state
->rdata
.total
< min_data
)) {
808 tevent_req_received(req
);
809 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
812 if (recv_flags2
!= NULL
) {
813 *recv_flags2
= state
->recv_flags2
;
817 *setup
= talloc_move(mem_ctx
, &state
->rsetup
);
818 *num_setup
= state
->num_rsetup
;
820 TALLOC_FREE(state
->rsetup
);
824 *param
= talloc_move(mem_ctx
, &state
->rparam
.data
);
825 *num_param
= state
->rparam
.total
;
827 TALLOC_FREE(state
->rparam
.data
);
831 *data
= talloc_move(mem_ctx
, &state
->rdata
.data
);
832 *num_data
= state
->rdata
.total
;
834 TALLOC_FREE(state
->rdata
.data
);
837 status
= state
->status
;
838 tevent_req_received(req
);
842 NTSTATUS
smb1cli_trans(TALLOC_CTX
*mem_ctx
, struct smbXcli_conn
*conn
,
844 uint8_t additional_flags
, uint8_t clear_flags
,
845 uint16_t additional_flags2
, uint16_t clear_flags2
,
846 uint32_t timeout_msec
,
847 uint32_t pid
, uint16_t tid
,
848 struct smbXcli_session
*session
,
849 const char *pipe_name
, uint16_t fid
, uint16_t function
,
851 uint16_t *setup
, uint8_t num_setup
, uint8_t max_setup
,
852 uint8_t *param
, uint32_t num_param
, uint32_t max_param
,
853 uint8_t *data
, uint32_t num_data
, uint32_t max_data
,
854 uint16_t *recv_flags2
,
855 uint16_t **rsetup
, uint8_t min_rsetup
, uint8_t *num_rsetup
,
856 uint8_t **rparam
, uint32_t min_rparam
, uint32_t *num_rparam
,
857 uint8_t **rdata
, uint32_t min_rdata
, uint32_t *num_rdata
)
859 TALLOC_CTX
*frame
= talloc_stackframe();
860 struct tevent_context
*ev
;
861 struct tevent_req
*req
;
862 NTSTATUS status
= NT_STATUS_OK
;
864 if (smbXcli_conn_has_async_calls(conn
)) {
866 * Can't use sync call while an async call is in flight
868 status
= NT_STATUS_INVALID_PARAMETER_MIX
;
872 ev
= tevent_context_init(frame
);
874 status
= NT_STATUS_NO_MEMORY
;
878 req
= smb1cli_trans_send(frame
, ev
, conn
, trans_cmd
,
879 additional_flags
, clear_flags
,
880 additional_flags2
, clear_flags2
,
883 pipe_name
, fid
, function
, flags
,
884 setup
, num_setup
, max_setup
,
885 param
, num_param
, max_param
,
886 data
, num_data
, max_data
);
888 status
= NT_STATUS_NO_MEMORY
;
892 if (!tevent_req_poll(req
, ev
)) {
893 status
= map_nt_error_from_unix_common(errno
);
897 status
= smb1cli_trans_recv(req
, mem_ctx
, recv_flags2
,
898 rsetup
, min_rsetup
, num_rsetup
,
899 rparam
, min_rparam
, num_rparam
,
900 rdata
, min_rdata
, num_rdata
);