docs: Allow smb.conf.5 to still be generated outside the waf build
[Samba.git] / source4 / libcli / raw / rawtrans.c
blob3a12fd30d5773f5918c2c096b90c30a9bad3651f
1 /*
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/>.
21 #include "includes.h"
22 #include <tevent.h>
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,
31 uint8_t command)
33 struct smbcli_request *req;
34 uint8_t additional_flags;
35 uint8_t clear_flags;
36 uint16_t additional_flags2;
37 uint16_t clear_flags2;
38 uint32_t pid;
39 struct smbXcli_tcon *tcon = NULL;
40 struct smbXcli_session *session = NULL;
41 const char *pipe_name = NULL;
42 uint8_t s;
43 uint32_t timeout_msec;
44 uint32_t tmp;
46 tmp = parms->in.params.length + parms->in.data.length;
48 req = smbcli_request_setup(tree, command, parms->in.setup_count, tmp);
49 if (req == NULL) {
50 return NULL;
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;
58 if (req->session) {
59 session = req->session->smbXcli;
62 if (req->tree) {
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 memcpy(req->out.data,
76 parms->in.params.data,
77 parms->in.params.length);
78 memcpy(req->out.data + parms->in.params.length,
79 parms->in.data.data,
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,
87 req->transport->ev,
88 req->transport->conn,
89 command,
90 additional_flags,
91 clear_flags,
92 additional_flags2,
93 clear_flags2,
94 timeout_msec,
95 pid,
96 tcon,
97 session,
98 pipe_name,
99 0xFFFF, /* fid */
100 0, /* function */
101 parms->in.flags,
102 (uint16_t *)req->out.vwv,
103 parms->in.setup_count,
104 parms->in.max_setup,
105 req->out.data,
106 parms->in.params.length,
107 parms->in.max_param,
108 req->out.data+
109 parms->in.params.length,
110 parms->in.data.length,
111 parms->in.max_data);
112 if (req->subreqs[0] == NULL) {
113 talloc_free(req);
114 return NULL;
116 tevent_req_set_callback(req->subreqs[0],
117 smb_raw_trans_backend_done,
118 req);
120 return req;
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;
131 uint8_t s;
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,
138 &req->flags2,
139 &setup,
140 0, /* min_setup */
141 &num_setup,
142 &param,
143 0, /* min_param */
144 &num_param,
145 &data,
146 0, /* min_data */
147 &num_data);
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;
153 if (req->async.fn) {
154 req->async.fn(req);
156 return;
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;
166 if (req->async.fn) {
167 req->async.fn(req);
169 return;
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;
184 } else {
185 transport->error.etype = ETYPE_SMB;
188 req->state = SMBCLI_REQUEST_DONE;
189 if (req->async.fn) {
190 req->async.fn(req);
194 static NTSTATUS smb_raw_trans_backend_recv(struct smbcli_request *req,
195 TALLOC_CTX *mem_ctx,
196 struct smb_trans2 *parms)
198 if (!smbcli_request_receive(req) ||
199 smbcli_request_is_error(req)) {
200 goto failed;
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);
208 failed:
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,
219 TALLOC_CTX *mem_ctx,
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,
226 TALLOC_CTX *mem_ctx,
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,
242 TALLOC_CTX *mem_ctx,
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,
249 TALLOC_CTX *mem_ctx,
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;
265 uint8_t clear_flags;
266 uint16_t additional_flags2;
267 uint16_t clear_flags2;
268 uint32_t pid;
269 struct smbXcli_tcon *tcon = NULL;
270 struct smbXcli_session *session = NULL;
271 uint32_t timeout_msec;
272 uint32_t tmp;
274 tmp = parms->in.params.length + parms->in.data.length;
276 req = smbcli_request_setup(tree, SMBnttrans, parms->in.setup_count, tmp);
277 if (req == NULL) {
278 return NULL;
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;
286 if (req->session) {
287 session = req->session->smbXcli;
290 if (req->tree) {
291 tcon = req->tree->smbXcli;
294 clear_flags = ~additional_flags;
295 clear_flags2 = ~additional_flags2;
297 timeout_msec = req->transport->options.request_timeout * 1000;
299 memcpy(req->out.vwv,
300 parms->in.setup,
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,
307 parms->in.data.data,
308 parms->in.data.length);
310 req->subreqs[0] = smb1cli_trans_send(req,
311 req->transport->ev,
312 req->transport->conn,
313 SMBnttrans,
314 additional_flags,
315 clear_flags,
316 additional_flags2,
317 clear_flags2,
318 timeout_msec,
319 pid,
320 tcon,
321 session,
322 NULL, /* pipe_name */
323 0xFFFF, /* fid */
324 parms->in.function,
325 0, /* flags */
326 (uint16_t *)req->out.vwv,
327 parms->in.setup_count,
328 parms->in.max_setup,
329 req->out.data,
330 parms->in.params.length,
331 parms->in.max_param,
332 req->out.data+
333 parms->in.params.length,
334 parms->in.data.length,
335 parms->in.max_data);
336 if (req->subreqs[0] == NULL) {
337 talloc_free(req);
338 return NULL;
340 tevent_req_set_callback(req->subreqs[0],
341 smb_raw_nttrans_done,
342 req);
344 return req;
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,
361 &req->flags2,
362 &setup,
363 0, /* min_setup */
364 &num_setup,
365 &param,
366 0, /* min_param */
367 &num_param,
368 &data,
369 0, /* min_data */
370 &num_data);
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;
376 if (req->async.fn) {
377 req->async.fn(req);
379 return;
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;
394 } else {
395 transport->error.etype = ETYPE_SMB;
398 req->state = SMBCLI_REQUEST_DONE;
399 if (req->async.fn) {
400 req->async.fn(req);
404 NTSTATUS smb_raw_nttrans_recv(struct smbcli_request *req,
405 TALLOC_CTX *mem_ctx,
406 struct smb_nttrans *parms)
408 if (!smbcli_request_receive(req) ||
409 smbcli_request_is_error(req)) {
410 goto failed;
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);
418 failed:
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,
426 TALLOC_CTX *mem_ctx,
427 struct smb_nttrans *parms)
429 struct smbcli_request *req;
431 req = smb_raw_nttrans_send(tree, parms);
432 if (!req) {
433 return NT_STATUS_UNSUCCESSFUL;
436 return smb_raw_nttrans_recv(req, mem_ctx, parms);