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
;
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;
57 tid
= SVAL(req
->out
.hdr
, HDR_TID
);
58 uid
= SVAL(req
->out
.hdr
, HDR_UID
);
60 clear_flags
= ~additional_flags
;
61 clear_flags2
= ~additional_flags2
;
63 timeout_msec
= req
->transport
->options
.request_timeout
* 1000;
65 for (s
=0; s
< parms
->in
.setup_count
; s
++) {
66 SSVAL(req
->out
.vwv
, VWV(s
), parms
->in
.setup
[s
]);
70 parms
->in
.params
.data
,
71 parms
->in
.params
.length
);
72 memcpy(req
->out
.data
+ parms
->in
.params
.length
,
74 parms
->in
.data
.length
);
76 if (command
== SMBtrans
&& parms
->in
.trans_name
) {
77 pipe_name
= parms
->in
.trans_name
;
80 req
->subreqs
[0] = smb1cli_trans_send(req
,
94 (uint16_t *)req
->out
.vwv
,
95 parms
->in
.setup_count
,
98 parms
->in
.params
.length
,
101 parms
->in
.params
.length
,
102 parms
->in
.data
.length
,
104 if (req
->subreqs
[0] == NULL
) {
108 tevent_req_set_callback(req
->subreqs
[0],
109 smb_raw_trans_backend_done
,
115 static void smb_raw_trans_backend_done(struct tevent_req
*subreq
)
117 struct smbcli_request
*req
=
118 tevent_req_callback_data(subreq
,
119 struct smbcli_request
);
120 struct smbcli_transport
*transport
= req
->transport
;
121 uint16_t *setup
= NULL
;
122 uint8_t num_setup
= 0;
124 uint8_t *param
= NULL
;
125 uint32_t num_param
= 0;
126 uint8_t *data
= NULL
;
127 uint32_t num_data
= 0;
129 req
->status
= smb1cli_trans_recv(req
->subreqs
[0], req
,
140 TALLOC_FREE(req
->subreqs
[0]);
141 if (NT_STATUS_IS_ERR(req
->status
)) {
142 req
->state
= SMBCLI_REQUEST_ERROR
;
143 transport
->error
.e
.nt_status
= req
->status
;
144 transport
->error
.etype
= ETYPE_SMB
;
151 req
->trans2
.out
.setup_count
= num_setup
;
152 req
->trans2
.out
.setup
= talloc_array(req
, uint16_t, num_setup
);
153 if (req
->trans2
.out
.setup
== NULL
) {
154 req
->state
= SMBCLI_REQUEST_ERROR
;
155 req
->status
= NT_STATUS_NO_MEMORY
;
156 transport
->error
.e
.nt_status
= req
->status
;
157 transport
->error
.etype
= ETYPE_SMB
;
163 for (s
= 0; s
< num_setup
; s
++) {
164 req
->trans2
.out
.setup
[s
] = SVAL(setup
, VWV(s
));
167 req
->trans2
.out
.params
.data
= param
;
168 req
->trans2
.out
.params
.length
= num_param
;
170 req
->trans2
.out
.data
.data
= data
;
171 req
->trans2
.out
.data
.length
= num_data
;
173 transport
->error
.e
.nt_status
= req
->status
;
174 if (NT_STATUS_IS_OK(req
->status
)) {
175 transport
->error
.etype
= ETYPE_NONE
;
177 transport
->error
.etype
= ETYPE_SMB
;
180 req
->state
= SMBCLI_REQUEST_DONE
;
186 static NTSTATUS
smb_raw_trans_backend_recv(struct smbcli_request
*req
,
188 struct smb_trans2
*parms
)
190 if (!smbcli_request_receive(req
) ||
191 smbcli_request_is_error(req
)) {
195 parms
->out
= req
->trans2
.out
;
196 talloc_steal(mem_ctx
, parms
->out
.setup
);
197 talloc_steal(mem_ctx
, parms
->out
.params
.data
);
198 talloc_steal(mem_ctx
, parms
->out
.data
.data
);
201 return smbcli_request_destroy(req
);
204 _PUBLIC_
struct smbcli_request
*smb_raw_trans_send(struct smbcli_tree
*tree
,
205 struct smb_trans2
*parms
)
207 return smb_raw_trans_backend_send(tree
, parms
, SMBtrans
);
210 _PUBLIC_ NTSTATUS
smb_raw_trans_recv(struct smbcli_request
*req
,
212 struct smb_trans2
*parms
)
214 return smb_raw_trans_backend_recv(req
, mem_ctx
, parms
);
217 _PUBLIC_ NTSTATUS
smb_raw_trans(struct smbcli_tree
*tree
,
219 struct smb_trans2
*parms
)
221 struct smbcli_request
*req
;
222 req
= smb_raw_trans_send(tree
, parms
);
223 if (!req
) return NT_STATUS_UNSUCCESSFUL
;
224 return smb_raw_trans_recv(req
, mem_ctx
, parms
);
227 struct smbcli_request
*smb_raw_trans2_send(struct smbcli_tree
*tree
,
228 struct smb_trans2
*parms
)
230 return smb_raw_trans_backend_send(tree
, parms
, SMBtrans2
);
233 NTSTATUS
smb_raw_trans2_recv(struct smbcli_request
*req
,
235 struct smb_trans2
*parms
)
237 return smb_raw_trans_backend_recv(req
, mem_ctx
, parms
);
240 NTSTATUS
smb_raw_trans2(struct smbcli_tree
*tree
,
242 struct smb_trans2
*parms
)
244 struct smbcli_request
*req
;
245 req
= smb_raw_trans2_send(tree
, parms
);
246 if (!req
) return NT_STATUS_UNSUCCESSFUL
;
247 return smb_raw_trans2_recv(req
, mem_ctx
, parms
);
250 static void smb_raw_nttrans_done(struct tevent_req
*subreq
);
252 struct smbcli_request
*smb_raw_nttrans_send(struct smbcli_tree
*tree
,
253 struct smb_nttrans
*parms
)
255 struct smbcli_request
*req
;
256 uint8_t additional_flags
;
258 uint16_t additional_flags2
;
259 uint16_t clear_flags2
;
263 uint32_t timeout_msec
;
266 tmp
= parms
->in
.params
.length
+ parms
->in
.data
.length
;
268 req
= smbcli_request_setup(tree
, SMBnttrans
, parms
->in
.setup_count
, tmp
);
273 additional_flags
= CVAL(req
->out
.hdr
, HDR_FLG
);
274 additional_flags2
= SVAL(req
->out
.hdr
, HDR_FLG2
);
275 pid
= SVAL(req
->out
.hdr
, HDR_PID
);
276 pid
|= SVAL(req
->out
.hdr
, HDR_PIDHIGH
)<<16;
277 tid
= SVAL(req
->out
.hdr
, HDR_TID
);
278 uid
= SVAL(req
->out
.hdr
, HDR_UID
);
280 clear_flags
= ~additional_flags
;
281 clear_flags2
= ~additional_flags2
;
283 timeout_msec
= req
->transport
->options
.request_timeout
* 1000;
287 parms
->in
.setup_count
* 2);
289 memcpy(req
->out
.data
,
290 parms
->in
.params
.data
,
291 parms
->in
.params
.length
);
292 memcpy(req
->out
.data
+ parms
->in
.params
.length
,
294 parms
->in
.data
.length
);
296 req
->subreqs
[0] = smb1cli_trans_send(req
,
298 req
->transport
->conn
,
306 NULL
, /* pipe_name */
310 (uint16_t *)req
->out
.vwv
,
311 parms
->in
.setup_count
,
314 parms
->in
.params
.length
,
317 parms
->in
.params
.length
,
318 parms
->in
.data
.length
,
320 if (req
->subreqs
[0] == NULL
) {
324 tevent_req_set_callback(req
->subreqs
[0],
325 smb_raw_nttrans_done
,
331 static void smb_raw_nttrans_done(struct tevent_req
*subreq
)
333 struct smbcli_request
*req
=
334 tevent_req_callback_data(subreq
,
335 struct smbcli_request
);
336 struct smbcli_transport
*transport
= req
->transport
;
337 uint16_t *setup
= NULL
;
338 uint8_t num_setup
= 0;
339 uint8_t *param
= NULL
;
340 uint32_t num_param
= 0;
341 uint8_t *data
= NULL
;
342 uint32_t num_data
= 0;
344 req
->status
= smb1cli_trans_recv(req
->subreqs
[0], req
,
355 TALLOC_FREE(req
->subreqs
[0]);
356 if (NT_STATUS_IS_ERR(req
->status
)) {
357 req
->state
= SMBCLI_REQUEST_ERROR
;
358 transport
->error
.e
.nt_status
= req
->status
;
359 transport
->error
.etype
= ETYPE_SMB
;
366 req
->nttrans
.out
.setup_count
= num_setup
;
367 req
->nttrans
.out
.setup
= (uint8_t *)setup
;
369 req
->nttrans
.out
.params
.data
= param
;
370 req
->nttrans
.out
.params
.length
= num_param
;
372 req
->nttrans
.out
.data
.data
= data
;
373 req
->nttrans
.out
.data
.length
= num_data
;
375 transport
->error
.e
.nt_status
= req
->status
;
376 if (NT_STATUS_IS_OK(req
->status
)) {
377 transport
->error
.etype
= ETYPE_NONE
;
379 transport
->error
.etype
= ETYPE_SMB
;
382 req
->state
= SMBCLI_REQUEST_DONE
;
388 NTSTATUS
smb_raw_nttrans_recv(struct smbcli_request
*req
,
390 struct smb_nttrans
*parms
)
392 if (!smbcli_request_receive(req
) ||
393 smbcli_request_is_error(req
)) {
397 parms
->out
= req
->nttrans
.out
;
398 talloc_steal(mem_ctx
, parms
->out
.setup
);
399 talloc_steal(mem_ctx
, parms
->out
.params
.data
);
400 talloc_steal(mem_ctx
, parms
->out
.data
.data
);
403 return smbcli_request_destroy(req
);
406 /****************************************************************************
407 receive a SMB nttrans response allocating the necessary memory
408 ****************************************************************************/
409 NTSTATUS
smb_raw_nttrans(struct smbcli_tree
*tree
,
411 struct smb_nttrans
*parms
)
413 struct smbcli_request
*req
;
415 req
= smb_raw_nttrans_send(tree
, parms
);
417 return NT_STATUS_UNSUCCESSFUL
;
420 return smb_raw_nttrans_recv(req
, mem_ctx
, parms
);