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
]);
76 parms
->in
.params
.data
,
77 parms
->in
.params
.length
);
78 memcpy(req
->out
.data
+ parms
->in
.params
.length
,
80 parms
->in
.data
.length
);
82 if (command
== SMBtrans
&& parms
->in
.trans_name
) {
83 pipe_name
= parms
->in
.trans_name
;
86 req
->subreqs
[0] = smb1cli_trans_send(req
,
102 (uint16_t *)req
->out
.vwv
,
103 parms
->in
.setup_count
,
106 parms
->in
.params
.length
,
109 parms
->in
.params
.length
,
110 parms
->in
.data
.length
,
112 if (req
->subreqs
[0] == NULL
) {
116 tevent_req_set_callback(req
->subreqs
[0],
117 smb_raw_trans_backend_done
,
123 static void smb_raw_trans_backend_done(struct tevent_req
*subreq
)
125 struct smbcli_request
*req
=
126 tevent_req_callback_data(subreq
,
127 struct smbcli_request
);
128 struct smbcli_transport
*transport
= req
->transport
;
129 uint16_t *setup
= NULL
;
130 uint8_t num_setup
= 0;
132 uint8_t *param
= NULL
;
133 uint32_t num_param
= 0;
134 uint8_t *data
= NULL
;
135 uint32_t num_data
= 0;
137 req
->status
= smb1cli_trans_recv(req
->subreqs
[0], req
,
148 TALLOC_FREE(req
->subreqs
[0]);
149 if (NT_STATUS_IS_ERR(req
->status
)) {
150 req
->state
= SMBCLI_REQUEST_ERROR
;
151 transport
->error
.e
.nt_status
= req
->status
;
152 transport
->error
.etype
= ETYPE_SMB
;
159 req
->trans2
.out
.setup_count
= num_setup
;
160 req
->trans2
.out
.setup
= talloc_array(req
, uint16_t, num_setup
);
161 if (req
->trans2
.out
.setup
== NULL
) {
162 req
->state
= SMBCLI_REQUEST_ERROR
;
163 req
->status
= NT_STATUS_NO_MEMORY
;
164 transport
->error
.e
.nt_status
= req
->status
;
165 transport
->error
.etype
= ETYPE_SMB
;
171 for (s
= 0; s
< num_setup
; s
++) {
172 req
->trans2
.out
.setup
[s
] = SVAL(setup
, VWV(s
));
175 req
->trans2
.out
.params
.data
= param
;
176 req
->trans2
.out
.params
.length
= num_param
;
178 req
->trans2
.out
.data
.data
= data
;
179 req
->trans2
.out
.data
.length
= num_data
;
181 transport
->error
.e
.nt_status
= req
->status
;
182 if (NT_STATUS_IS_OK(req
->status
)) {
183 transport
->error
.etype
= ETYPE_NONE
;
185 transport
->error
.etype
= ETYPE_SMB
;
188 req
->state
= SMBCLI_REQUEST_DONE
;
194 static NTSTATUS
smb_raw_trans_backend_recv(struct smbcli_request
*req
,
196 struct smb_trans2
*parms
)
198 if (!smbcli_request_receive(req
) ||
199 smbcli_request_is_error(req
)) {
203 parms
->out
= req
->trans2
.out
;
204 talloc_steal(mem_ctx
, parms
->out
.setup
);
205 talloc_steal(mem_ctx
, parms
->out
.params
.data
);
206 talloc_steal(mem_ctx
, parms
->out
.data
.data
);
209 return smbcli_request_destroy(req
);
212 _PUBLIC_
struct smbcli_request
*smb_raw_trans_send(struct smbcli_tree
*tree
,
213 struct smb_trans2
*parms
)
215 return smb_raw_trans_backend_send(tree
, parms
, SMBtrans
);
218 _PUBLIC_ NTSTATUS
smb_raw_trans_recv(struct smbcli_request
*req
,
220 struct smb_trans2
*parms
)
222 return smb_raw_trans_backend_recv(req
, mem_ctx
, parms
);
225 _PUBLIC_ NTSTATUS
smb_raw_trans(struct smbcli_tree
*tree
,
227 struct smb_trans2
*parms
)
229 struct smbcli_request
*req
;
230 req
= smb_raw_trans_send(tree
, parms
);
231 if (!req
) return NT_STATUS_UNSUCCESSFUL
;
232 return smb_raw_trans_recv(req
, mem_ctx
, parms
);
235 struct smbcli_request
*smb_raw_trans2_send(struct smbcli_tree
*tree
,
236 struct smb_trans2
*parms
)
238 return smb_raw_trans_backend_send(tree
, parms
, SMBtrans2
);
241 NTSTATUS
smb_raw_trans2_recv(struct smbcli_request
*req
,
243 struct smb_trans2
*parms
)
245 return smb_raw_trans_backend_recv(req
, mem_ctx
, parms
);
248 NTSTATUS
smb_raw_trans2(struct smbcli_tree
*tree
,
250 struct smb_trans2
*parms
)
252 struct smbcli_request
*req
;
253 req
= smb_raw_trans2_send(tree
, parms
);
254 if (!req
) return NT_STATUS_UNSUCCESSFUL
;
255 return smb_raw_trans2_recv(req
, mem_ctx
, parms
);
258 static void smb_raw_nttrans_done(struct tevent_req
*subreq
);
260 struct smbcli_request
*smb_raw_nttrans_send(struct smbcli_tree
*tree
,
261 struct smb_nttrans
*parms
)
263 struct smbcli_request
*req
;
264 uint8_t additional_flags
;
266 uint16_t additional_flags2
;
267 uint16_t clear_flags2
;
269 struct smbXcli_tcon
*tcon
= NULL
;
270 struct smbXcli_session
*session
= NULL
;
271 uint32_t timeout_msec
;
274 tmp
= parms
->in
.params
.length
+ parms
->in
.data
.length
;
276 req
= smbcli_request_setup(tree
, SMBnttrans
, parms
->in
.setup_count
, tmp
);
281 additional_flags
= CVAL(req
->out
.hdr
, HDR_FLG
);
282 additional_flags2
= SVAL(req
->out
.hdr
, HDR_FLG2
);
283 pid
= SVAL(req
->out
.hdr
, HDR_PID
);
284 pid
|= SVAL(req
->out
.hdr
, HDR_PIDHIGH
)<<16;
287 session
= req
->session
->smbXcli
;
291 tcon
= req
->tree
->smbXcli
;
294 clear_flags
= ~additional_flags
;
295 clear_flags2
= ~additional_flags2
;
297 timeout_msec
= req
->transport
->options
.request_timeout
* 1000;
301 parms
->in
.setup_count
* 2);
303 memcpy(req
->out
.data
,
304 parms
->in
.params
.data
,
305 parms
->in
.params
.length
);
306 memcpy(req
->out
.data
+ parms
->in
.params
.length
,
308 parms
->in
.data
.length
);
310 req
->subreqs
[0] = smb1cli_trans_send(req
,
312 req
->transport
->conn
,
322 NULL
, /* pipe_name */
326 (uint16_t *)req
->out
.vwv
,
327 parms
->in
.setup_count
,
330 parms
->in
.params
.length
,
333 parms
->in
.params
.length
,
334 parms
->in
.data
.length
,
336 if (req
->subreqs
[0] == NULL
) {
340 tevent_req_set_callback(req
->subreqs
[0],
341 smb_raw_nttrans_done
,
347 static void smb_raw_nttrans_done(struct tevent_req
*subreq
)
349 struct smbcli_request
*req
=
350 tevent_req_callback_data(subreq
,
351 struct smbcli_request
);
352 struct smbcli_transport
*transport
= req
->transport
;
353 uint16_t *setup
= NULL
;
354 uint8_t num_setup
= 0;
355 uint8_t *param
= NULL
;
356 uint32_t num_param
= 0;
357 uint8_t *data
= NULL
;
358 uint32_t num_data
= 0;
360 req
->status
= smb1cli_trans_recv(req
->subreqs
[0], req
,
371 TALLOC_FREE(req
->subreqs
[0]);
372 if (NT_STATUS_IS_ERR(req
->status
)) {
373 req
->state
= SMBCLI_REQUEST_ERROR
;
374 transport
->error
.e
.nt_status
= req
->status
;
375 transport
->error
.etype
= ETYPE_SMB
;
382 req
->nttrans
.out
.setup_count
= num_setup
;
383 req
->nttrans
.out
.setup
= (uint8_t *)setup
;
385 req
->nttrans
.out
.params
.data
= param
;
386 req
->nttrans
.out
.params
.length
= num_param
;
388 req
->nttrans
.out
.data
.data
= data
;
389 req
->nttrans
.out
.data
.length
= num_data
;
391 transport
->error
.e
.nt_status
= req
->status
;
392 if (NT_STATUS_IS_OK(req
->status
)) {
393 transport
->error
.etype
= ETYPE_NONE
;
395 transport
->error
.etype
= ETYPE_SMB
;
398 req
->state
= SMBCLI_REQUEST_DONE
;
404 NTSTATUS
smb_raw_nttrans_recv(struct smbcli_request
*req
,
406 struct smb_nttrans
*parms
)
408 if (!smbcli_request_receive(req
) ||
409 smbcli_request_is_error(req
)) {
413 parms
->out
= req
->nttrans
.out
;
414 talloc_steal(mem_ctx
, parms
->out
.setup
);
415 talloc_steal(mem_ctx
, parms
->out
.params
.data
);
416 talloc_steal(mem_ctx
, parms
->out
.data
.data
);
419 return smbcli_request_destroy(req
);
422 /****************************************************************************
423 receive a SMB nttrans response allocating the necessary memory
424 ****************************************************************************/
425 NTSTATUS
smb_raw_nttrans(struct smbcli_tree
*tree
,
427 struct smb_nttrans
*parms
)
429 struct smbcli_request
*req
;
431 req
= smb_raw_nttrans_send(tree
, parms
);
433 return NT_STATUS_UNSUCCESSFUL
;
436 return smb_raw_nttrans_recv(req
, mem_ctx
, parms
);