2 Unix SMB/CIFS implementation.
3 raw trans/trans2/nttrans operations
5 Copyright (C) James Myers 2003 <myersjj@samba.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "../libcli/smb/smbXcli_base.h"
27 static void smb_raw_trans_backend_done(struct tevent_req
*subreq
);
29 static struct smbcli_request
*smb_raw_trans_backend_send(struct smbcli_tree
*tree
,
30 struct smb_trans2
*parms
,
33 struct smbcli_request
*req
;
34 uint8_t additional_flags
;
36 uint16_t additional_flags2
;
37 uint16_t clear_flags2
;
39 struct smbXcli_tcon
*tcon
= NULL
;
40 struct smbXcli_session
*session
= NULL
;
41 const char *pipe_name
= NULL
;
43 uint32_t timeout_msec
;
46 tmp
= parms
->in
.params
.length
+ parms
->in
.data
.length
;
48 req
= smbcli_request_setup(tree
, command
, parms
->in
.setup_count
, tmp
);
53 additional_flags
= CVAL(req
->out
.hdr
, HDR_FLG
);
54 additional_flags2
= SVAL(req
->out
.hdr
, HDR_FLG2
);
55 pid
= SVAL(req
->out
.hdr
, HDR_PID
);
56 pid
|= SVAL(req
->out
.hdr
, HDR_PIDHIGH
)<<16;
59 session
= req
->session
->smbXcli
;
63 tcon
= req
->tree
->smbXcli
;
66 clear_flags
= ~additional_flags
;
67 clear_flags2
= ~additional_flags2
;
69 timeout_msec
= req
->transport
->options
.request_timeout
* 1000;
71 for (s
=0; s
< parms
->in
.setup_count
; s
++) {
72 SSVAL(req
->out
.vwv
, VWV(s
), parms
->in
.setup
[s
]);
75 if (parms
->in
.params
.length
> 0) {
77 parms
->in
.params
.data
,
78 parms
->in
.params
.length
);
80 if (parms
->in
.data
.length
> 0) {
81 memcpy(req
->out
.data
+ parms
->in
.params
.length
,
83 parms
->in
.data
.length
);
86 if (command
== SMBtrans
&& parms
->in
.trans_name
) {
87 pipe_name
= parms
->in
.trans_name
;
90 req
->subreqs
[0] = smb1cli_trans_send(req
,
106 (uint16_t *)req
->out
.vwv
,
107 parms
->in
.setup_count
,
110 parms
->in
.params
.length
,
113 parms
->in
.params
.length
,
114 parms
->in
.data
.length
,
116 if (req
->subreqs
[0] == NULL
) {
120 tevent_req_set_callback(req
->subreqs
[0],
121 smb_raw_trans_backend_done
,
127 static void smb_raw_trans_backend_done(struct tevent_req
*subreq
)
129 struct smbcli_request
*req
=
130 tevent_req_callback_data(subreq
,
131 struct smbcli_request
);
132 struct smbcli_transport
*transport
= req
->transport
;
133 uint16_t *setup
= NULL
;
134 uint8_t num_setup
= 0;
136 uint8_t *param
= NULL
;
137 uint32_t num_param
= 0;
138 uint8_t *data
= NULL
;
139 uint32_t num_data
= 0;
141 req
->status
= smb1cli_trans_recv(req
->subreqs
[0], req
,
152 TALLOC_FREE(req
->subreqs
[0]);
153 if (NT_STATUS_IS_ERR(req
->status
)) {
154 req
->state
= SMBCLI_REQUEST_ERROR
;
155 transport
->error
.e
.nt_status
= req
->status
;
156 transport
->error
.etype
= ETYPE_SMB
;
163 req
->trans2
.out
.setup_count
= num_setup
;
164 req
->trans2
.out
.setup
= talloc_array(req
, uint16_t, num_setup
);
165 if (req
->trans2
.out
.setup
== NULL
) {
166 req
->state
= SMBCLI_REQUEST_ERROR
;
167 req
->status
= NT_STATUS_NO_MEMORY
;
168 transport
->error
.e
.nt_status
= req
->status
;
169 transport
->error
.etype
= ETYPE_SMB
;
175 for (s
= 0; s
< num_setup
; s
++) {
176 req
->trans2
.out
.setup
[s
] = SVAL(setup
, VWV(s
));
179 req
->trans2
.out
.params
.data
= param
;
180 req
->trans2
.out
.params
.length
= num_param
;
182 req
->trans2
.out
.data
.data
= data
;
183 req
->trans2
.out
.data
.length
= num_data
;
185 transport
->error
.e
.nt_status
= req
->status
;
186 if (NT_STATUS_IS_OK(req
->status
)) {
187 transport
->error
.etype
= ETYPE_NONE
;
189 transport
->error
.etype
= ETYPE_SMB
;
192 req
->state
= SMBCLI_REQUEST_DONE
;
198 static NTSTATUS
smb_raw_trans_backend_recv(struct smbcli_request
*req
,
200 struct smb_trans2
*parms
)
202 if (!smbcli_request_receive(req
) ||
203 smbcli_request_is_error(req
)) {
207 parms
->out
= req
->trans2
.out
;
208 talloc_steal(mem_ctx
, parms
->out
.setup
);
209 talloc_steal(mem_ctx
, parms
->out
.params
.data
);
210 talloc_steal(mem_ctx
, parms
->out
.data
.data
);
213 return smbcli_request_destroy(req
);
216 _PUBLIC_
struct smbcli_request
*smb_raw_trans_send(struct smbcli_tree
*tree
,
217 struct smb_trans2
*parms
)
219 return smb_raw_trans_backend_send(tree
, parms
, SMBtrans
);
222 _PUBLIC_ NTSTATUS
smb_raw_trans_recv(struct smbcli_request
*req
,
224 struct smb_trans2
*parms
)
226 return smb_raw_trans_backend_recv(req
, mem_ctx
, parms
);
229 _PUBLIC_ NTSTATUS
smb_raw_trans(struct smbcli_tree
*tree
,
231 struct smb_trans2
*parms
)
233 struct smbcli_request
*req
;
234 req
= smb_raw_trans_send(tree
, parms
);
235 if (!req
) return NT_STATUS_UNSUCCESSFUL
;
236 return smb_raw_trans_recv(req
, mem_ctx
, parms
);
239 struct smbcli_request
*smb_raw_trans2_send(struct smbcli_tree
*tree
,
240 struct smb_trans2
*parms
)
242 return smb_raw_trans_backend_send(tree
, parms
, SMBtrans2
);
245 NTSTATUS
smb_raw_trans2_recv(struct smbcli_request
*req
,
247 struct smb_trans2
*parms
)
249 return smb_raw_trans_backend_recv(req
, mem_ctx
, parms
);
252 NTSTATUS
smb_raw_trans2(struct smbcli_tree
*tree
,
254 struct smb_trans2
*parms
)
256 struct smbcli_request
*req
;
257 req
= smb_raw_trans2_send(tree
, parms
);
258 if (!req
) return NT_STATUS_UNSUCCESSFUL
;
259 return smb_raw_trans2_recv(req
, mem_ctx
, parms
);
262 static void smb_raw_nttrans_done(struct tevent_req
*subreq
);
264 struct smbcli_request
*smb_raw_nttrans_send(struct smbcli_tree
*tree
,
265 struct smb_nttrans
*parms
)
267 struct smbcli_request
*req
;
268 uint8_t additional_flags
;
270 uint16_t additional_flags2
;
271 uint16_t clear_flags2
;
273 struct smbXcli_tcon
*tcon
= NULL
;
274 struct smbXcli_session
*session
= NULL
;
275 uint32_t timeout_msec
;
278 tmp
= parms
->in
.params
.length
+ parms
->in
.data
.length
;
280 req
= smbcli_request_setup(tree
, SMBnttrans
, parms
->in
.setup_count
, tmp
);
285 additional_flags
= CVAL(req
->out
.hdr
, HDR_FLG
);
286 additional_flags2
= SVAL(req
->out
.hdr
, HDR_FLG2
);
287 pid
= SVAL(req
->out
.hdr
, HDR_PID
);
288 pid
|= SVAL(req
->out
.hdr
, HDR_PIDHIGH
)<<16;
291 session
= req
->session
->smbXcli
;
295 tcon
= req
->tree
->smbXcli
;
298 clear_flags
= ~additional_flags
;
299 clear_flags2
= ~additional_flags2
;
301 timeout_msec
= req
->transport
->options
.request_timeout
* 1000;
303 if (parms
->in
.setup_count
> 0) {
305 req
->out
.vwv
, parms
->in
.setup
, parms
->in
.setup_count
* 2);
308 if (parms
->in
.params
.length
> 0) {
309 memcpy(req
->out
.data
,
310 parms
->in
.params
.data
,
311 parms
->in
.params
.length
);
313 if (parms
->in
.data
.length
> 0) {
314 memcpy(req
->out
.data
+ parms
->in
.params
.length
,
316 parms
->in
.data
.length
);
319 req
->subreqs
[0] = smb1cli_trans_send(req
,
321 req
->transport
->conn
,
331 NULL
, /* pipe_name */
335 (uint16_t *)req
->out
.vwv
,
336 parms
->in
.setup_count
,
339 parms
->in
.params
.length
,
342 parms
->in
.params
.length
,
343 parms
->in
.data
.length
,
345 if (req
->subreqs
[0] == NULL
) {
349 tevent_req_set_callback(req
->subreqs
[0],
350 smb_raw_nttrans_done
,
356 static void smb_raw_nttrans_done(struct tevent_req
*subreq
)
358 struct smbcli_request
*req
=
359 tevent_req_callback_data(subreq
,
360 struct smbcli_request
);
361 struct smbcli_transport
*transport
= req
->transport
;
362 uint16_t *setup
= NULL
;
363 uint8_t num_setup
= 0;
364 uint8_t *param
= NULL
;
365 uint32_t num_param
= 0;
366 uint8_t *data
= NULL
;
367 uint32_t num_data
= 0;
369 req
->status
= smb1cli_trans_recv(req
->subreqs
[0], req
,
380 TALLOC_FREE(req
->subreqs
[0]);
381 if (NT_STATUS_IS_ERR(req
->status
)) {
382 req
->state
= SMBCLI_REQUEST_ERROR
;
383 transport
->error
.e
.nt_status
= req
->status
;
384 transport
->error
.etype
= ETYPE_SMB
;
391 req
->nttrans
.out
.setup_count
= num_setup
;
392 req
->nttrans
.out
.setup
= (uint8_t *)setup
;
394 req
->nttrans
.out
.params
.data
= param
;
395 req
->nttrans
.out
.params
.length
= num_param
;
397 req
->nttrans
.out
.data
.data
= data
;
398 req
->nttrans
.out
.data
.length
= num_data
;
400 transport
->error
.e
.nt_status
= req
->status
;
401 if (NT_STATUS_IS_OK(req
->status
)) {
402 transport
->error
.etype
= ETYPE_NONE
;
404 transport
->error
.etype
= ETYPE_SMB
;
407 req
->state
= SMBCLI_REQUEST_DONE
;
413 NTSTATUS
smb_raw_nttrans_recv(struct smbcli_request
*req
,
415 struct smb_nttrans
*parms
)
417 if (!smbcli_request_receive(req
) ||
418 smbcli_request_is_error(req
)) {
422 parms
->out
= req
->nttrans
.out
;
423 talloc_steal(mem_ctx
, parms
->out
.setup
);
424 talloc_steal(mem_ctx
, parms
->out
.params
.data
);
425 talloc_steal(mem_ctx
, parms
->out
.data
.data
);
428 return smbcli_request_destroy(req
);
431 /****************************************************************************
432 receive a SMB nttrans response allocating the necessary memory
433 ****************************************************************************/
434 NTSTATUS
smb_raw_nttrans(struct smbcli_tree
*tree
,
436 struct smb_nttrans
*parms
)
438 struct smbcli_request
*req
;
440 req
= smb_raw_nttrans_send(tree
, parms
);
442 return NT_STATUS_UNSUCCESSFUL
;
445 return smb_raw_nttrans_recv(req
, mem_ctx
, parms
);