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);