doc: Remove all references to 'printer admin' option.
[Samba/gbeck.git] / source4 / libcli / raw / rawtrans.c
blob8e16e5b911316cd658c41737c7bb120f56388110
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 uint16_t tid;
40 uint16_t uid;
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;
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]);
69 memcpy(req->out.data,
70 parms->in.params.data,
71 parms->in.params.length);
72 memcpy(req->out.data + parms->in.params.length,
73 parms->in.data.data,
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,
81 req->transport->ev,
82 req->transport->conn,
83 command,
84 additional_flags,
85 clear_flags,
86 additional_flags2,
87 clear_flags2,
88 timeout_msec,
89 pid, tid, uid,
90 pipe_name,
91 0xFFFF, /* fid */
92 0, /* function */
93 parms->in.flags,
94 (uint16_t *)req->out.vwv,
95 parms->in.setup_count,
96 parms->in.max_setup,
97 req->out.data,
98 parms->in.params.length,
99 parms->in.max_param,
100 req->out.data+
101 parms->in.params.length,
102 parms->in.data.length,
103 parms->in.max_data);
104 if (req->subreqs[0] == NULL) {
105 talloc_free(req);
106 return NULL;
108 tevent_req_set_callback(req->subreqs[0],
109 smb_raw_trans_backend_done,
110 req);
112 return req;
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;
123 uint8_t s;
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,
130 &req->flags2,
131 &setup,
132 0, /* min_setup */
133 &num_setup,
134 &param,
135 0, /* min_param */
136 &num_param,
137 &data,
138 0, /* min_data */
139 &num_data);
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;
145 if (req->async.fn) {
146 req->async.fn(req);
148 return;
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;
158 if (req->async.fn) {
159 req->async.fn(req);
161 return;
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;
176 } else {
177 transport->error.etype = ETYPE_SMB;
180 req->state = SMBCLI_REQUEST_DONE;
181 if (req->async.fn) {
182 req->async.fn(req);
186 static NTSTATUS smb_raw_trans_backend_recv(struct smbcli_request *req,
187 TALLOC_CTX *mem_ctx,
188 struct smb_trans2 *parms)
190 if (!smbcli_request_receive(req) ||
191 smbcli_request_is_error(req)) {
192 goto failed;
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);
200 failed:
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,
211 TALLOC_CTX *mem_ctx,
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,
218 TALLOC_CTX *mem_ctx,
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,
234 TALLOC_CTX *mem_ctx,
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,
241 TALLOC_CTX *mem_ctx,
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;
257 uint8_t clear_flags;
258 uint16_t additional_flags2;
259 uint16_t clear_flags2;
260 uint32_t pid;
261 uint16_t tid;
262 uint16_t uid;
263 uint32_t timeout_msec;
264 uint32_t tmp;
266 tmp = parms->in.params.length + parms->in.data.length;
268 req = smbcli_request_setup(tree, SMBnttrans, parms->in.setup_count, tmp);
269 if (req == NULL) {
270 return NULL;
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;
285 memcpy(req->out.vwv,
286 parms->in.setup,
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,
293 parms->in.data.data,
294 parms->in.data.length);
296 req->subreqs[0] = smb1cli_trans_send(req,
297 req->transport->ev,
298 req->transport->conn,
299 SMBnttrans,
300 additional_flags,
301 clear_flags,
302 additional_flags2,
303 clear_flags2,
304 timeout_msec,
305 pid, tid, uid,
306 NULL, /* pipe_name */
307 0xFFFF, /* fid */
308 parms->in.function,
309 0, /* flags */
310 (uint16_t *)req->out.vwv,
311 parms->in.setup_count,
312 parms->in.max_setup,
313 req->out.data,
314 parms->in.params.length,
315 parms->in.max_param,
316 req->out.data+
317 parms->in.params.length,
318 parms->in.data.length,
319 parms->in.max_data);
320 if (req->subreqs[0] == NULL) {
321 talloc_free(req);
322 return NULL;
324 tevent_req_set_callback(req->subreqs[0],
325 smb_raw_nttrans_done,
326 req);
328 return req;
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,
345 &req->flags2,
346 &setup,
347 0, /* min_setup */
348 &num_setup,
349 &param,
350 0, /* min_param */
351 &num_param,
352 &data,
353 0, /* min_data */
354 &num_data);
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;
360 if (req->async.fn) {
361 req->async.fn(req);
363 return;
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;
378 } else {
379 transport->error.etype = ETYPE_SMB;
382 req->state = SMBCLI_REQUEST_DONE;
383 if (req->async.fn) {
384 req->async.fn(req);
388 NTSTATUS smb_raw_nttrans_recv(struct smbcli_request *req,
389 TALLOC_CTX *mem_ctx,
390 struct smb_nttrans *parms)
392 if (!smbcli_request_receive(req) ||
393 smbcli_request_is_error(req)) {
394 goto failed;
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);
402 failed:
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,
410 TALLOC_CTX *mem_ctx,
411 struct smb_nttrans *parms)
413 struct smbcli_request *req;
415 req = smb_raw_nttrans_send(tree, parms);
416 if (!req) {
417 return NT_STATUS_UNSUCCESSFUL;
420 return smb_raw_nttrans_recv(req, mem_ctx, parms);