65976fd38574a10e59b7cf2db410584995e12f6c
[gd/samba-autobuild/.git] / source4 / smb_server / smb / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-2003
5    Copyright (C) James J Myers 2003 <myersjj@samba.org>
6
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 2 of the License, or
10    (at your option) any later version.
11    
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.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /*
22    This file handles most of the reply_ calls that the server
23    makes to handle specific protocols
24 */
25
26 #include "includes.h"
27 #include "smb_server/smb_server.h"
28 #include "ntvfs/ntvfs.h"
29 #include "librpc/gen_ndr/ndr_nbt.h"
30
31
32 /****************************************************************************
33  Reply to a simple request (async send)
34 ****************************************************************************/
35 static void reply_simple_send(struct ntvfs_request *ntvfs)
36 {
37         struct smbsrv_request *req;
38
39         SMBSRV_CHECK_ASYNC_STATUS_SIMPLE;
40
41         smbsrv_setup_reply(req, 0, 0);
42         smbsrv_send_reply(req);
43 }
44
45
46 /****************************************************************************
47  Reply to a tcon.
48 ****************************************************************************/
49 void smbsrv_reply_tcon(struct smbsrv_request *req)
50 {
51         union smb_tcon con;
52         NTSTATUS status;
53         uint8_t *p;
54         
55         /* parse request */
56         SMBSRV_CHECK_WCT(req, 0);
57
58         con.tcon.level = RAW_TCON_TCON;
59
60         p = req->in.data;       
61         p += req_pull_ascii4(req, &con.tcon.in.service, p, STR_TERMINATE);
62         p += req_pull_ascii4(req, &con.tcon.in.password, p, STR_TERMINATE);
63         p += req_pull_ascii4(req, &con.tcon.in.dev, p, STR_TERMINATE);
64
65         if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
66                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
67                 return;
68         }
69
70         /* call backend */
71         status = smbsrv_tcon_backend(req, &con);
72
73         if (!NT_STATUS_IS_OK(status)) {
74                 smbsrv_send_error(req, status);
75                 return;
76         }
77
78         /* construct reply */
79         smbsrv_setup_reply(req, 2, 0);
80
81         SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
82         SSVAL(req->out.vwv, VWV(1), con.tcon.out.tid);
83         SSVAL(req->out.hdr, HDR_TID, req->tcon->tid);
84   
85         smbsrv_send_reply(req);
86 }
87
88
89 /****************************************************************************
90  Reply to a tcon and X.
91 ****************************************************************************/
92 void smbsrv_reply_tcon_and_X(struct smbsrv_request *req)
93 {
94         NTSTATUS status;
95         union smb_tcon con;
96         uint8_t *p;
97         uint16_t passlen;
98
99         con.tconx.level = RAW_TCON_TCONX;
100
101         /* parse request */
102         SMBSRV_CHECK_WCT(req, 4);
103
104         con.tconx.in.flags  = SVAL(req->in.vwv, VWV(2));
105         passlen             = SVAL(req->in.vwv, VWV(3));
106
107         p = req->in.data;
108
109         if (!req_pull_blob(req, p, passlen, &con.tconx.in.password)) {
110                 smbsrv_send_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
111                 return;
112         }
113         p += passlen;
114
115         p += req_pull_string(req, &con.tconx.in.path, p, -1, STR_TERMINATE);
116         p += req_pull_string(req, &con.tconx.in.device, p, -1, STR_ASCII);
117
118         if (!con.tconx.in.path || !con.tconx.in.device) {
119                 smbsrv_send_error(req, NT_STATUS_BAD_DEVICE_TYPE);
120                 return;
121         }
122
123         /* call backend */
124         status = smbsrv_tcon_backend(req, &con);
125
126         if (!NT_STATUS_IS_OK(status)) {
127                 smbsrv_send_error(req, status);
128                 return;
129         }
130
131         /* construct reply - two variants */
132         if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
133                 smbsrv_setup_reply(req, 2, 0);
134
135                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
136                 SSVAL(req->out.vwv, VWV(1), 0);
137
138                 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
139         } else {
140                 smbsrv_setup_reply(req, 3, 0);
141
142                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
143                 SSVAL(req->out.vwv, VWV(1), 0);
144                 SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
145
146                 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
147                 req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
148         }
149
150         /* set the incoming and outgoing tid to the just created one */
151         SSVAL(req->in.hdr, HDR_TID, con.tconx.out.tid);
152         SSVAL(req->out.hdr,HDR_TID, con.tconx.out.tid);
153
154         smbsrv_chain_reply(req);
155 }
156
157
158 /****************************************************************************
159  Reply to an unknown request
160 ****************************************************************************/
161 void smbsrv_reply_unknown(struct smbsrv_request *req)
162 {
163         int type;
164
165         type = CVAL(req->in.hdr, HDR_COM);
166   
167         DEBUG(0,("unknown command type %d (0x%X)\n", type, type));
168
169         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRunknownsmb));
170 }
171
172
173 /****************************************************************************
174  Reply to an ioctl (async reply)
175 ****************************************************************************/
176 static void reply_ioctl_send(struct ntvfs_request *ntvfs)
177 {
178         struct smbsrv_request *req;
179         union smb_ioctl *io;
180
181         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_ioctl);
182
183         /* the +1 is for nicer alignment */
184         smbsrv_setup_reply(req, 8, io->ioctl.out.blob.length+1);
185         SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length);
186         SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length);
187         SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1);
188
189         memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length);
190
191         smbsrv_send_reply(req);
192 }
193
194 /****************************************************************************
195  Reply to an ioctl.
196 ****************************************************************************/
197 void smbsrv_reply_ioctl(struct smbsrv_request *req)
198 {
199         union smb_ioctl *io;
200
201         /* parse request */
202         SMBSRV_CHECK_WCT(req, 3);
203         SMBSRV_TALLOC_IO_PTR(io, union smb_ioctl);
204         SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
205
206         io->ioctl.level         = RAW_IOCTL_IOCTL;
207         io->ioctl.in.file.fnum  = req_fnum(req, req->in.vwv, VWV(0));
208         io->ioctl.in.request    = IVAL(req->in.vwv, VWV(1));
209
210         /* call backend */
211         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io));
212 }
213
214
215 /****************************************************************************
216  Reply to a chkpth.
217 ****************************************************************************/
218 void smbsrv_reply_chkpth(struct smbsrv_request *req)
219 {
220         union smb_chkpath *io;
221
222         SMBSRV_TALLOC_IO_PTR(io, union smb_chkpath);
223         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
224
225         req_pull_ascii4(req, &io->chkpath.in.path, req->in.data, STR_TERMINATE);
226
227         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_chkpath(req->ntvfs, io));
228 }
229
230 /****************************************************************************
231  Reply to a getatr (async reply)
232 ****************************************************************************/
233 static void reply_getatr_send(struct ntvfs_request *ntvfs)
234 {
235         struct smbsrv_request *req;
236         union smb_fileinfo *st;
237
238         SMBSRV_CHECK_ASYNC_STATUS(st, union smb_fileinfo);
239
240         /* construct reply */
241         smbsrv_setup_reply(req, 10, 0);
242
243         SSVAL(req->out.vwv,         VWV(0), st->getattr.out.attrib);
244         srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
245         SIVAL(req->out.vwv,         VWV(3), st->getattr.out.size);
246
247         SMBSRV_VWV_RESERVED(5, 5);
248
249         smbsrv_send_reply(req);
250 }
251
252
253 /****************************************************************************
254  Reply to a getatr.
255 ****************************************************************************/
256 void smbsrv_reply_getatr(struct smbsrv_request *req)
257 {
258         union smb_fileinfo *st;
259
260         SMBSRV_TALLOC_IO_PTR(st, union smb_fileinfo);
261         SMBSRV_SETUP_NTVFS_REQUEST(reply_getatr_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
262         
263         st->getattr.level = RAW_FILEINFO_GETATTR;
264
265         /* parse request */
266         req_pull_ascii4(req, &st->getattr.in.file.path, req->in.data, STR_TERMINATE);
267         if (!st->getattr.in.file.path) {
268                 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
269                 return;
270         }
271
272         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qpathinfo(req->ntvfs, st));
273 }
274
275
276 /****************************************************************************
277  Reply to a setatr.
278 ****************************************************************************/
279 void smbsrv_reply_setatr(struct smbsrv_request *req)
280 {
281         union smb_setfileinfo *st;
282
283         /* parse request */
284         SMBSRV_CHECK_WCT(req, 8);
285         SMBSRV_TALLOC_IO_PTR(st, union smb_setfileinfo);
286         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
287
288         st->setattr.level = RAW_SFILEINFO_SETATTR;
289         st->setattr.in.attrib     = SVAL(req->in.vwv, VWV(0));
290         st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
291         
292         req_pull_ascii4(req, &st->setattr.in.file.path, req->in.data, STR_TERMINATE);
293
294         if (!st->setattr.in.file.path) {
295                 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
296                 return;
297         }
298         
299         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setpathinfo(req->ntvfs, st));
300 }
301
302
303 /****************************************************************************
304  Reply to a dskattr (async reply)
305 ****************************************************************************/
306 static void reply_dskattr_send(struct ntvfs_request *ntvfs)
307 {
308         struct smbsrv_request *req;
309         union smb_fsinfo *fs;
310
311         SMBSRV_CHECK_ASYNC_STATUS(fs, union smb_fsinfo);
312
313         /* construct reply */
314         smbsrv_setup_reply(req, 5, 0);
315
316         SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total);
317         SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit);
318         SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size);
319         SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free);
320
321         SMBSRV_VWV_RESERVED(4, 1);
322
323         smbsrv_send_reply(req);
324 }
325
326
327 /****************************************************************************
328  Reply to a dskattr.
329 ****************************************************************************/
330 void smbsrv_reply_dskattr(struct smbsrv_request *req)
331 {
332         union smb_fsinfo *fs;
333
334         SMBSRV_TALLOC_IO_PTR(fs, union smb_fsinfo);
335         SMBSRV_SETUP_NTVFS_REQUEST(reply_dskattr_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
336         
337         fs->dskattr.level = RAW_QFS_DSKATTR;
338
339         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_fsinfo(req->ntvfs, fs));
340 }
341
342
343 /****************************************************************************
344  Reply to an open (async reply)
345 ****************************************************************************/
346 static void reply_open_send(struct ntvfs_request *ntvfs)
347 {
348         struct smbsrv_request *req;
349         union smb_open *oi;
350
351         SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
352
353         /* construct reply */
354         smbsrv_setup_reply(req, 7, 0);
355
356         SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum);
357         SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
358         srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
359         SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
360         SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
361
362         smbsrv_send_reply(req);
363 }
364
365 /****************************************************************************
366  Reply to an open.
367 ****************************************************************************/
368 void smbsrv_reply_open(struct smbsrv_request *req)
369 {
370         union smb_open *oi;
371
372         /* parse request */
373         SMBSRV_CHECK_WCT(req, 2);
374         SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
375         SMBSRV_SETUP_NTVFS_REQUEST(reply_open_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
376
377         oi->openold.level = RAW_OPEN_OPEN;
378         oi->openold.in.open_mode = SVAL(req->in.vwv, VWV(0));
379         oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
380
381         req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
382
383         if (!oi->openold.in.fname) {
384                 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
385                 return;
386         }
387
388         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
389 }
390
391
392 /****************************************************************************
393  Reply to an open and X (async reply)
394 ****************************************************************************/
395 static void reply_open_and_X_send(struct ntvfs_request *ntvfs)
396 {
397         struct smbsrv_request *req;
398         union smb_open *oi;
399
400         SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
401
402         /* build the reply */
403         if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
404                 smbsrv_setup_reply(req, 19, 0);
405         } else {
406                 smbsrv_setup_reply(req, 15, 0);
407         }
408
409         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
410         SSVAL(req->out.vwv, VWV(1), 0);
411         SSVAL(req->out.vwv, VWV(2), oi->openx.out.file.fnum);
412         SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
413         srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
414         SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
415         SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
416         SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
417         SSVAL(req->out.vwv, VWV(10),oi->openx.out.devstate);
418         SSVAL(req->out.vwv, VWV(11),oi->openx.out.action);
419         SIVAL(req->out.vwv, VWV(12),oi->openx.out.unique_fid);
420         SSVAL(req->out.vwv, VWV(14),0); /* reserved */
421         if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
422                 SIVAL(req->out.vwv, VWV(15),oi->openx.out.access_mask);
423                 SMBSRV_VWV_RESERVED(17, 2);
424         }
425
426         req->chained_fnum = oi->openx.out.file.fnum;
427
428         smbsrv_chain_reply(req);
429 }
430
431
432 /****************************************************************************
433  Reply to an open and X.
434 ****************************************************************************/
435 void smbsrv_reply_open_and_X(struct smbsrv_request *req)
436 {
437         union smb_open *oi;
438
439         /* parse the request */
440         SMBSRV_CHECK_WCT(req, 15);
441         SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
442         SMBSRV_SETUP_NTVFS_REQUEST(reply_open_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
443
444         oi->openx.level = RAW_OPEN_OPENX;
445         oi->openx.in.flags        = SVAL(req->in.vwv, VWV(2));
446         oi->openx.in.open_mode    = SVAL(req->in.vwv, VWV(3));
447         oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
448         oi->openx.in.file_attrs   = SVAL(req->in.vwv, VWV(5));
449         oi->openx.in.write_time   = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
450         oi->openx.in.open_func    = SVAL(req->in.vwv, VWV(8));
451         oi->openx.in.size         = IVAL(req->in.vwv, VWV(9));
452         oi->openx.in.timeout      = IVAL(req->in.vwv, VWV(11));
453
454         req_pull_ascii4(req, &oi->openx.in.fname, req->in.data, STR_TERMINATE);
455
456         if (!oi->openx.in.fname) {
457                 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
458                 return;
459         }
460
461         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
462 }
463
464
465 /****************************************************************************
466  Reply to a mknew or a create.
467 ****************************************************************************/
468 static void reply_mknew_send(struct ntvfs_request *ntvfs)
469 {
470         struct smbsrv_request *req;
471         union smb_open *oi;
472
473         SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
474
475         /* build the reply */
476         smbsrv_setup_reply(req, 1, 0);
477
478         SSVAL(req->out.vwv, VWV(0), oi->mknew.out.file.fnum);
479
480         smbsrv_send_reply(req);
481 }
482
483
484 /****************************************************************************
485  Reply to a mknew or a create.
486 ****************************************************************************/
487 void smbsrv_reply_mknew(struct smbsrv_request *req)
488 {
489         union smb_open *oi;
490
491         /* parse the request */
492         SMBSRV_CHECK_WCT(req, 3);
493         SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
494         SMBSRV_SETUP_NTVFS_REQUEST(reply_mknew_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
495
496         if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
497                 oi->mknew.level = RAW_OPEN_MKNEW;
498         } else {
499                 oi->mknew.level = RAW_OPEN_CREATE;
500         }
501         oi->mknew.in.attrib  = SVAL(req->in.vwv, VWV(0));
502         oi->mknew.in.write_time  = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
503
504         req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
505
506         if (!oi->mknew.in.fname) {
507                 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
508                 return;
509         }
510
511         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
512 }
513
514 /****************************************************************************
515  Reply to a create temporary file (async reply)
516 ****************************************************************************/
517 static void reply_ctemp_send(struct ntvfs_request *ntvfs)
518 {
519         struct smbsrv_request *req;
520         union smb_open *oi;
521
522         SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
523
524         /* build the reply */
525         smbsrv_setup_reply(req, 1, 0);
526
527         SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.file.fnum);
528
529         /* the returned filename is relative to the directory */
530         req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
531
532         smbsrv_send_reply(req);
533 }
534
535 /****************************************************************************
536  Reply to a create temporary file.
537 ****************************************************************************/
538 void smbsrv_reply_ctemp(struct smbsrv_request *req)
539 {
540         union smb_open *oi;
541
542         /* parse the request */
543         SMBSRV_CHECK_WCT(req, 3);
544         SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
545         SMBSRV_SETUP_NTVFS_REQUEST(reply_ctemp_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
546
547         oi->ctemp.level = RAW_OPEN_CTEMP;
548         oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
549         oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
550
551         /* the filename is actually a directory name, the server provides a filename
552            in that directory */
553         req_pull_ascii4(req, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
554
555         if (!oi->ctemp.in.directory) {
556                 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
557                 return;
558         }
559
560         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
561 }
562
563
564 /****************************************************************************
565  Reply to a unlink
566 ****************************************************************************/
567 void smbsrv_reply_unlink(struct smbsrv_request *req)
568 {
569         union smb_unlink *unl;
570
571         /* parse the request */
572         SMBSRV_CHECK_WCT(req, 1);
573         SMBSRV_TALLOC_IO_PTR(unl, union smb_unlink);
574         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
575         
576         unl->unlink.in.attrib = SVAL(req->in.vwv, VWV(0));
577
578         req_pull_ascii4(req, &unl->unlink.in.pattern, req->in.data, STR_TERMINATE);
579         
580         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_unlink(req->ntvfs, unl));
581 }
582
583
584 /****************************************************************************
585  Reply to a readbraw (core+ protocol).
586  this is a strange packet because it doesn't use a standard SMB header in the reply,
587  only the 4 byte NBT header
588  This command must be replied to synchronously
589 ****************************************************************************/
590 void smbsrv_reply_readbraw(struct smbsrv_request *req)
591 {
592         NTSTATUS status;
593         union smb_read io;
594
595         io.readbraw.level = RAW_READ_READBRAW;
596
597         /* there are two variants, one with 10 and one with 8 command words */
598         if (req->in.wct < 8) {
599                 goto failed;
600         }
601
602         io.readbraw.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
603         io.readbraw.in.offset  = IVAL(req->in.vwv, VWV(1));
604         io.readbraw.in.maxcnt  = SVAL(req->in.vwv, VWV(3));
605         io.readbraw.in.mincnt  = SVAL(req->in.vwv, VWV(4));
606         io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
607
608         /* the 64 bit variant */
609         if (req->in.wct == 10) {
610                 uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
611                 io.readbraw.in.offset |= (((off_t)offset_high) << 32);
612         }
613
614         /* before calling the backend we setup the raw buffer. This
615          * saves a copy later */
616         req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
617         req->out.buffer = talloc_size(req, req->out.size);
618         if (req->out.buffer == NULL) {
619                 goto failed;
620         }
621         SIVAL(req->out.buffer, 0, 0); /* init NBT header */
622
623         /* tell the backend where to put the data */
624         io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
625
626         /* prepare the ntvfs request */
627         req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req,
628                                           req->session->session_info,
629                                           SVAL(req->in.hdr,HDR_PID),
630                                           SVAL(req->in.hdr,HDR_MID),
631                                           req->request_time,
632                                           req, NULL, 0);
633         if (!req->ntvfs) {
634                 goto failed;
635         }
636
637         /* call the backend */
638         status = ntvfs_read(req->ntvfs, &io);
639         if (!NT_STATUS_IS_OK(status)) {
640                 goto failed;
641         }
642
643         req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
644
645         smbsrv_send_reply_nosign(req);
646         return;
647
648 failed:
649         /* any failure in readbraw is equivalent to reading zero bytes */
650         req->out.size = 4;
651         req->out.buffer = talloc_size(req, req->out.size);
652         SIVAL(req->out.buffer, 0, 0); /* init NBT header */
653
654         smbsrv_send_reply_nosign(req);
655 }
656
657
658 /****************************************************************************
659  Reply to a lockread (async reply)
660 ****************************************************************************/
661 static void reply_lockread_send(struct ntvfs_request *ntvfs)
662 {
663         struct smbsrv_request *req;
664         union smb_read *io;
665
666         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
667
668         /* trim packet */
669         io->lockread.out.nread = MIN(io->lockread.out.nread,
670                 req_max_data(req) - 3);
671         req_grow_data(req, 3 + io->lockread.out.nread);
672
673         /* construct reply */
674         SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
675         SMBSRV_VWV_RESERVED(1, 4);
676
677         SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
678         SSVAL(req->out.data, 1, io->lockread.out.nread);
679
680         smbsrv_send_reply(req);
681 }
682
683
684 /****************************************************************************
685  Reply to a lockread (core+ protocol).
686  note that the lock is a write lock, not a read lock!
687 ****************************************************************************/
688 void smbsrv_reply_lockread(struct smbsrv_request *req)
689 {
690         union smb_read *io;
691         
692         /* parse request */
693         SMBSRV_CHECK_WCT(req, 5);
694         SMBSRV_TALLOC_IO_PTR(io, union smb_read);
695         SMBSRV_SETUP_NTVFS_REQUEST(reply_lockread_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
696
697         io->lockread.level = RAW_READ_LOCKREAD;
698         io->lockread.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
699         io->lockread.in.count     = SVAL(req->in.vwv, VWV(1));
700         io->lockread.in.offset    = IVAL(req->in.vwv, VWV(2));
701         io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
702         
703         /* setup the reply packet assuming the maximum possible read */
704         smbsrv_setup_reply(req, 5, 3 + io->lockread.in.count);
705
706         /* tell the backend where to put the data */
707         io->lockread.out.data = req->out.data + 3;
708
709         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
710 }
711
712
713
714 /****************************************************************************
715  Reply to a read (async reply)
716 ****************************************************************************/
717 static void reply_read_send(struct ntvfs_request *ntvfs)
718 {
719         struct smbsrv_request *req;
720         union smb_read *io;
721
722         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
723
724         /* trim packet */
725         io->read.out.nread = MIN(io->read.out.nread,
726                 req_max_data(req) - 3);
727         req_grow_data(req, 3 + io->read.out.nread);
728
729         /* construct reply */
730         SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
731         SMBSRV_VWV_RESERVED(1, 4);
732
733         SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
734         SSVAL(req->out.data, 1, io->read.out.nread);
735
736         smbsrv_send_reply(req);
737 }
738
739 /****************************************************************************
740  Reply to a read.
741 ****************************************************************************/
742 void smbsrv_reply_read(struct smbsrv_request *req)
743 {
744         union smb_read *io;
745
746         /* parse request */
747         SMBSRV_CHECK_WCT(req, 5);
748         SMBSRV_TALLOC_IO_PTR(io, union smb_read);
749         SMBSRV_SETUP_NTVFS_REQUEST(reply_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
750
751         io->read.level = RAW_READ_READ;
752         io->read.in.file.fnum     = req_fnum(req, req->in.vwv, VWV(0));
753         io->read.in.count         = SVAL(req->in.vwv, VWV(1));
754         io->read.in.offset        = IVAL(req->in.vwv, VWV(2));
755         io->read.in.remaining     = SVAL(req->in.vwv, VWV(4));
756         
757         /* setup the reply packet assuming the maximum possible read */
758         smbsrv_setup_reply(req, 5, 3 + io->read.in.count);
759
760         /* tell the backend where to put the data */
761         io->read.out.data = req->out.data + 3;
762
763         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
764 }
765
766 /****************************************************************************
767  Reply to a read and X (async reply)
768 ****************************************************************************/
769 static void reply_read_and_X_send(struct ntvfs_request *ntvfs)
770 {
771         struct smbsrv_request *req;
772         union smb_read *io;
773
774         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
775
776         /* readx reply packets can be over-sized */
777         req->control_flags |= SMBSRV_REQ_CONTROL_LARGE;
778         if (io->readx.in.maxcnt != 0xFFFF &&
779             io->readx.in.mincnt != 0xFFFF) {
780                 req_grow_data(req, 1 + io->readx.out.nread);
781                 SCVAL(req->out.data, 0, 0); /* padding */
782         } else {
783                 req_grow_data(req, io->readx.out.nread);
784         }
785
786         /* construct reply */
787         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
788         SSVAL(req->out.vwv, VWV(1), 0);
789         SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
790         SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
791         SMBSRV_VWV_RESERVED(4, 1);
792         SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
793         SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
794         SMBSRV_VWV_RESERVED(7, 5);
795
796         smbsrv_chain_reply(req);
797 }
798
799 /****************************************************************************
800  Reply to a read and X.
801 ****************************************************************************/
802 void smbsrv_reply_read_and_X(struct smbsrv_request *req)
803 {
804         union smb_read *io;
805
806         /* parse request */
807         if (req->in.wct != 12) {
808                 SMBSRV_CHECK_WCT(req, 10);
809         }
810
811         SMBSRV_TALLOC_IO_PTR(io, union smb_read);
812         SMBSRV_SETUP_NTVFS_REQUEST(reply_read_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
813
814         io->readx.level = RAW_READ_READX;
815         io->readx.in.file.fnum     = req_fnum(req, req->in.vwv, VWV(2));
816         io->readx.in.offset        = IVAL(req->in.vwv, VWV(3));
817         io->readx.in.maxcnt        = SVAL(req->in.vwv, VWV(5));
818         io->readx.in.mincnt        = SVAL(req->in.vwv, VWV(6));
819         io->readx.in.remaining     = SVAL(req->in.vwv, VWV(9));
820         if (req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) {
821                 io->readx.in.read_for_execute = True;
822         } else {
823                 io->readx.in.read_for_execute = False;
824         }
825
826         if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
827                 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
828                 if (high_part == 1) {
829                         io->readx.in.maxcnt |= high_part << 16;
830                 }
831         }
832         
833         /* the 64 bit variant */
834         if (req->in.wct == 12) {
835                 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
836                 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
837         }
838
839         /* setup the reply packet assuming the maximum possible read */
840         smbsrv_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
841
842         /* tell the backend where to put the data. Notice the pad byte. */
843         if (io->readx.in.maxcnt != 0xFFFF &&
844             io->readx.in.mincnt != 0xFFFF) {
845                 io->readx.out.data = req->out.data + 1;
846         } else {
847                 io->readx.out.data = req->out.data;
848         }
849
850         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
851 }
852
853
854 /****************************************************************************
855  Reply to a writebraw (core+ or LANMAN1.0 protocol).
856 ****************************************************************************/
857 void smbsrv_reply_writebraw(struct smbsrv_request *req)
858 {
859         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
860 }
861
862
863 /****************************************************************************
864  Reply to a writeunlock (async reply)
865 ****************************************************************************/
866 static void reply_writeunlock_send(struct ntvfs_request *ntvfs)
867 {
868         struct smbsrv_request *req;
869         union smb_write *io;
870
871         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
872
873         /* construct reply */
874         smbsrv_setup_reply(req, 1, 0);
875
876         SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
877
878         smbsrv_send_reply(req);
879 }
880
881 /****************************************************************************
882  Reply to a writeunlock (core+).
883 ****************************************************************************/
884 void smbsrv_reply_writeunlock(struct smbsrv_request *req)
885 {
886         union smb_write *io;
887
888         SMBSRV_CHECK_WCT(req, 5);
889         SMBSRV_TALLOC_IO_PTR(io, union smb_write);
890         SMBSRV_SETUP_NTVFS_REQUEST(reply_writeunlock_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
891
892         io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
893         io->writeunlock.in.file.fnum   = req_fnum(req, req->in.vwv, VWV(0));
894         io->writeunlock.in.count       = SVAL(req->in.vwv, VWV(1));
895         io->writeunlock.in.offset      = IVAL(req->in.vwv, VWV(2));
896         io->writeunlock.in.remaining   = SVAL(req->in.vwv, VWV(4));
897         io->writeunlock.in.data        = req->in.data + 3;
898
899         /* make sure they gave us the data they promised */
900         if (io->writeunlock.in.count+3 > req->in.data_size) {
901                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
902                 return;
903         }
904
905         /* make sure the data block is big enough */
906         if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
907                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
908                 return;
909         }
910
911         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
912 }
913
914
915
916 /****************************************************************************
917  Reply to a write (async reply)
918 ****************************************************************************/
919 static void reply_write_send(struct ntvfs_request *ntvfs)
920 {
921         struct smbsrv_request *req;
922         union smb_write *io;
923         
924         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
925
926         /* construct reply */
927         smbsrv_setup_reply(req, 1, 0);
928
929         SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
930
931         smbsrv_send_reply(req);
932 }
933
934 /****************************************************************************
935  Reply to a write
936 ****************************************************************************/
937 void smbsrv_reply_write(struct smbsrv_request *req)
938 {
939         union smb_write *io;
940
941         SMBSRV_CHECK_WCT(req, 5);
942         SMBSRV_TALLOC_IO_PTR(io, union smb_write);
943         SMBSRV_SETUP_NTVFS_REQUEST(reply_write_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
944
945         io->write.level = RAW_WRITE_WRITE;
946         io->write.in.file.fnum   = req_fnum(req, req->in.vwv, VWV(0));
947         io->write.in.count       = SVAL(req->in.vwv, VWV(1));
948         io->write.in.offset      = IVAL(req->in.vwv, VWV(2));
949         io->write.in.remaining   = SVAL(req->in.vwv, VWV(4));
950         io->write.in.data        = req->in.data + 3;
951
952         /* make sure they gave us the data they promised */
953         if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
954                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
955                 return;
956         }
957
958         /* make sure the data block is big enough */
959         if (SVAL(req->in.data, 1) < io->write.in.count) {
960                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
961                 return;
962         }
963
964         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
965 }
966
967
968 /****************************************************************************
969  Reply to a write and X (async reply)
970 ****************************************************************************/
971 static void reply_write_and_X_send(struct ntvfs_request *ntvfs)
972 {
973         struct smbsrv_request *req;
974         union smb_write *io;
975
976         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
977
978         /* construct reply */
979         smbsrv_setup_reply(req, 6, 0);
980
981         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
982         SSVAL(req->out.vwv, VWV(1), 0);
983         SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
984         SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
985         SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
986         SMBSRV_VWV_RESERVED(5, 1);
987
988         smbsrv_chain_reply(req);
989 }
990
991 /****************************************************************************
992  Reply to a write and X.
993 ****************************************************************************/
994 void smbsrv_reply_write_and_X(struct smbsrv_request *req)
995 {
996         union smb_write *io;
997         
998         if (req->in.wct != 14) {
999                 SMBSRV_CHECK_WCT(req, 12);
1000         }
1001
1002         SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1003         SMBSRV_SETUP_NTVFS_REQUEST(reply_write_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1004
1005         io->writex.level = RAW_WRITE_WRITEX;
1006         io->writex.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
1007         io->writex.in.offset    = IVAL(req->in.vwv, VWV(3));
1008         io->writex.in.wmode     = SVAL(req->in.vwv, VWV(7));
1009         io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1010         io->writex.in.count     = SVAL(req->in.vwv, VWV(10));
1011         io->writex.in.data      = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1012
1013         if (req->in.wct == 14) {
1014                 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1015                 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1016                 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1017                 io->writex.in.count |= ((uint32_t)count_high) << 16;
1018         }
1019
1020         /* make sure the data is in bounds */
1021         if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1022                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1023                 return;
1024         } 
1025
1026         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1027 }
1028
1029
1030 /****************************************************************************
1031  Reply to a lseek (async reply)
1032 ****************************************************************************/
1033 static void reply_lseek_send(struct ntvfs_request *ntvfs)
1034 {
1035         struct smbsrv_request *req;
1036         union smb_seek *io;
1037
1038         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_seek);
1039
1040         /* construct reply */
1041         smbsrv_setup_reply(req, 2, 0);
1042
1043         SIVALS(req->out.vwv, VWV(0), io->lseek.out.offset);
1044
1045         smbsrv_send_reply(req);
1046 }
1047
1048 /****************************************************************************
1049  Reply to a lseek.
1050 ****************************************************************************/
1051 void smbsrv_reply_lseek(struct smbsrv_request *req)
1052 {
1053         union smb_seek *io;
1054
1055         SMBSRV_CHECK_WCT(req, 4);
1056         SMBSRV_TALLOC_IO_PTR(io, union smb_seek);
1057         SMBSRV_SETUP_NTVFS_REQUEST(reply_lseek_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1058
1059         io->lseek.in.file.fnum  = req_fnum(req, req->in.vwv,  VWV(0));
1060         io->lseek.in.mode       = SVAL(req->in.vwv,  VWV(1));
1061         io->lseek.in.offset     = IVALS(req->in.vwv, VWV(2));
1062
1063         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_seek(req->ntvfs, io));
1064 }
1065
1066 /****************************************************************************
1067  Reply to a flush.
1068 ****************************************************************************/
1069 void smbsrv_reply_flush(struct smbsrv_request *req)
1070 {
1071         union smb_flush *io;
1072
1073         /* parse request */
1074         SMBSRV_CHECK_WCT(req, 1);
1075         SMBSRV_TALLOC_IO_PTR(io, union smb_flush);
1076         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1077
1078         io->flush.in.file.fnum = req_fnum(req, req->in.vwv,  VWV(0));
1079
1080         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_flush(req->ntvfs, io));
1081 }
1082
1083
1084 /****************************************************************************
1085  Reply to a exit. This closes all files open by a smbpid
1086 ****************************************************************************/
1087 void smbsrv_reply_exit(struct smbsrv_request *req)
1088 {
1089         NTSTATUS status;
1090         struct smbsrv_tcon *tcon;
1091         SMBSRV_CHECK_WCT(req, 0);
1092
1093         for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
1094                 req->tcon = tcon;
1095                 SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
1096                 status = ntvfs_exit(req->ntvfs);
1097                 talloc_free(req->ntvfs);
1098                 req->ntvfs = NULL;
1099                 req->tcon = NULL;
1100                 if (!NT_STATUS_IS_OK(status)) {
1101                         smbsrv_send_error(req, status);
1102                         return;
1103                 }
1104         }
1105
1106         smbsrv_setup_reply(req, 0, 0);
1107         smbsrv_send_reply(req);
1108 }
1109
1110
1111 /****************************************************************************
1112  Reply to a close 
1113
1114  Note that this has to deal with closing a directory opened by NT SMB's.
1115 ****************************************************************************/
1116 void smbsrv_reply_close(struct smbsrv_request *req)
1117 {
1118         union smb_close *io;
1119
1120         /* parse request */
1121         SMBSRV_CHECK_WCT(req, 3);
1122         SMBSRV_TALLOC_IO_PTR(io, union smb_close);
1123         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1124
1125         io->close.level = RAW_CLOSE_CLOSE;
1126         io->close.in.file.fnum  = req_fnum(req, req->in.vwv,  VWV(0));
1127         io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1128
1129         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
1130 }
1131
1132
1133 /****************************************************************************
1134  Reply to a writeclose (async reply)
1135 ****************************************************************************/
1136 static void reply_writeclose_send(struct ntvfs_request *ntvfs)
1137 {
1138         struct smbsrv_request *req;
1139         union smb_write *io;
1140
1141         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
1142
1143         /* construct reply */
1144         smbsrv_setup_reply(req, 1, 0);
1145
1146         SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1147
1148         smbsrv_send_reply(req);
1149 }
1150
1151 /****************************************************************************
1152  Reply to a writeclose (Core+ protocol).
1153 ****************************************************************************/
1154 void smbsrv_reply_writeclose(struct smbsrv_request *req)
1155 {
1156         union smb_write *io;
1157
1158         /* this one is pretty weird - the wct can be 6 or 12 */
1159         if (req->in.wct != 12) {
1160                 SMBSRV_CHECK_WCT(req, 6);
1161         }
1162
1163         SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1164         SMBSRV_SETUP_NTVFS_REQUEST(reply_writeclose_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1165
1166         io->writeclose.level = RAW_WRITE_WRITECLOSE;
1167         io->writeclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1168         io->writeclose.in.count  = SVAL(req->in.vwv, VWV(1));
1169         io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1170         io->writeclose.in.mtime  = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1171         io->writeclose.in.data   = req->in.data + 1;
1172
1173         /* make sure they gave us the data they promised */
1174         if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1175                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1176                 return;
1177         }
1178
1179         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1180 }
1181
1182 /****************************************************************************
1183  Reply to a lock.
1184 ****************************************************************************/
1185 void smbsrv_reply_lock(struct smbsrv_request *req)
1186 {
1187         union smb_lock *lck;
1188
1189         /* parse request */
1190         SMBSRV_CHECK_WCT(req, 5);
1191         SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1192         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1193
1194         lck->lock.level         = RAW_LOCK_LOCK;
1195         lck->lock.in.file.fnum  = req_fnum(req, req->in.vwv, VWV(0));
1196         lck->lock.in.count      = IVAL(req->in.vwv, VWV(1));
1197         lck->lock.in.offset     = IVAL(req->in.vwv, VWV(3));
1198
1199         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1200 }
1201
1202
1203 /****************************************************************************
1204  Reply to a unlock.
1205 ****************************************************************************/
1206 void smbsrv_reply_unlock(struct smbsrv_request *req)
1207 {
1208         union smb_lock *lck;
1209
1210         /* parse request */
1211         SMBSRV_CHECK_WCT(req, 5);
1212         SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1213         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1214
1215         lck->unlock.level               = RAW_LOCK_UNLOCK;
1216         lck->unlock.in.file.fnum        = req_fnum(req, req->in.vwv, VWV(0));
1217         lck->unlock.in.count            = IVAL(req->in.vwv, VWV(1));
1218         lck->unlock.in.offset           = IVAL(req->in.vwv, VWV(3));
1219
1220         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1221 }
1222
1223
1224 /****************************************************************************
1225  Reply to a tdis.
1226 ****************************************************************************/
1227 void smbsrv_reply_tdis(struct smbsrv_request *req)
1228 {
1229         SMBSRV_CHECK_WCT(req, 0);
1230
1231         talloc_free(req->tcon);
1232         req->tcon = NULL;
1233
1234         /* construct reply */
1235         smbsrv_setup_reply(req, 0, 0);
1236
1237         smbsrv_send_reply(req);
1238 }
1239
1240
1241 /****************************************************************************
1242  Reply to a echo. This is one of the few calls that is handled directly (the
1243  backends don't see it at all)
1244 ****************************************************************************/
1245 void smbsrv_reply_echo(struct smbsrv_request *req)
1246 {
1247         uint16_t count;
1248         int i;
1249
1250         SMBSRV_CHECK_WCT(req, 0);
1251
1252         count = SVAL(req->in.vwv, VWV(0));
1253
1254         smbsrv_setup_reply(req, 1, req->in.data_size);
1255
1256         memcpy(req->out.data, req->in.data, req->in.data_size);
1257
1258         for (i=1; i <= count;i++) {
1259                 struct smbsrv_request *this_req;
1260                 
1261                 if (i != count) {
1262                         this_req = smbsrv_setup_secondary_request(req);
1263                 } else {
1264                         this_req = req;
1265                 }
1266
1267                 SSVAL(this_req->out.vwv, VWV(0), i);
1268                 smbsrv_send_reply(this_req);
1269         }
1270 }
1271
1272
1273
1274 /****************************************************************************
1275  Reply to a printopen (async reply)
1276 ****************************************************************************/
1277 static void reply_printopen_send(struct ntvfs_request *ntvfs)
1278 {
1279         struct smbsrv_request *req;
1280         union smb_open *oi;
1281
1282         SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
1283
1284         /* construct reply */
1285         smbsrv_setup_reply(req, 1, 0);
1286
1287         SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum);
1288
1289         smbsrv_send_reply(req);
1290 }
1291
1292 /****************************************************************************
1293  Reply to a printopen.
1294 ****************************************************************************/
1295 void smbsrv_reply_printopen(struct smbsrv_request *req)
1296 {
1297         union smb_open *oi;
1298
1299         /* parse request */
1300         SMBSRV_CHECK_WCT(req, 2);
1301         SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
1302         SMBSRV_SETUP_NTVFS_REQUEST(reply_printopen_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1303
1304         oi->splopen.level = RAW_OPEN_SPLOPEN;
1305         oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1306         oi->splopen.in.mode         = SVAL(req->in.vwv, VWV(1));
1307
1308         req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1309
1310         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
1311 }
1312
1313 /****************************************************************************
1314  Reply to a printclose.
1315 ****************************************************************************/
1316 void smbsrv_reply_printclose(struct smbsrv_request *req)
1317 {
1318         union smb_close *io;
1319
1320         /* parse request */
1321         SMBSRV_CHECK_WCT(req, 3);
1322         SMBSRV_TALLOC_IO_PTR(io, union smb_close);
1323         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1324
1325         io->splclose.level = RAW_CLOSE_SPLCLOSE;
1326         io->splclose.in.file.fnum = req_fnum(req, req->in.vwv,  VWV(0));
1327
1328         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
1329 }
1330
1331 /****************************************************************************
1332  Reply to a printqueue.
1333 ****************************************************************************/
1334 static void reply_printqueue_send(struct ntvfs_request *ntvfs)
1335 {
1336         struct smbsrv_request *req;
1337         union smb_lpq *lpq;
1338         int i, maxcount;
1339         const uint_t el_size = 28;
1340
1341         SMBSRV_CHECK_ASYNC_STATUS(lpq,union smb_lpq);
1342
1343         /* construct reply */
1344         smbsrv_setup_reply(req, 2, 0);
1345
1346         /* truncate the returned list to fit in the negotiated buffer size */
1347         maxcount = (req_max_data(req) - 3) / el_size;
1348         if (maxcount < lpq->retq.out.count) {
1349                 lpq->retq.out.count = maxcount;
1350         }
1351
1352         /* setup enough space in the reply */
1353         req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1354         
1355         /* and fill it in */
1356         SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1357         SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1358
1359         SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1360         SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1361
1362         req->out.ptr = req->out.data + 3;
1363
1364         for (i=0;i<lpq->retq.out.count;i++) {
1365                 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1366                 SCVAL(req->out.ptr,  4, lpq->retq.out.queue[i].status);
1367                 SSVAL(req->out.ptr,  5, lpq->retq.out.queue[i].job);
1368                 SIVAL(req->out.ptr,  7, lpq->retq.out.queue[i].size);
1369                 SCVAL(req->out.ptr, 11, 0); /* reserved */
1370                 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1371                 req->out.ptr += el_size;
1372         }
1373
1374         smbsrv_send_reply(req);
1375 }
1376
1377 /****************************************************************************
1378  Reply to a printqueue.
1379 ****************************************************************************/
1380 void smbsrv_reply_printqueue(struct smbsrv_request *req)
1381 {
1382         union smb_lpq *lpq;
1383
1384         /* parse request */
1385         SMBSRV_CHECK_WCT(req, 2);
1386         SMBSRV_TALLOC_IO_PTR(lpq, union smb_lpq);
1387         SMBSRV_SETUP_NTVFS_REQUEST(reply_printqueue_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1388
1389         lpq->retq.level = RAW_LPQ_RETQ;
1390         lpq->retq.in.maxcount = SVAL(req->in.vwv,  VWV(0));
1391         lpq->retq.in.startidx = SVAL(req->in.vwv,  VWV(1));
1392
1393         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lpq(req->ntvfs, lpq));
1394 }
1395
1396
1397 /****************************************************************************
1398  Reply to a printwrite.
1399 ****************************************************************************/
1400 void smbsrv_reply_printwrite(struct smbsrv_request *req)
1401 {
1402         union smb_write *io;
1403
1404         /* parse request */
1405         SMBSRV_CHECK_WCT(req, 1);
1406         SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1407         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1408
1409         io->splwrite.level = RAW_WRITE_SPLWRITE;
1410
1411         if (req->in.data_size < 3) {
1412                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1413                 return;
1414         }
1415
1416         io->splwrite.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1417         io->splwrite.in.count = SVAL(req->in.data, 1);
1418         io->splwrite.in.data  = req->in.data + 3;
1419
1420         /* make sure they gave us the data they promised */
1421         if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1422                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1423                 return;
1424         }
1425
1426         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1427 }
1428
1429
1430 /****************************************************************************
1431  Reply to a mkdir.
1432 ****************************************************************************/
1433 void smbsrv_reply_mkdir(struct smbsrv_request *req)
1434 {
1435         union smb_mkdir *io;
1436
1437         /* parse the request */
1438         SMBSRV_CHECK_WCT(req, 0);
1439         SMBSRV_TALLOC_IO_PTR(io, union smb_mkdir);
1440         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1441
1442         io->generic.level = RAW_MKDIR_MKDIR;
1443         req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1444
1445         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_mkdir(req->ntvfs, io));
1446 }
1447
1448
1449 /****************************************************************************
1450  Reply to a rmdir.
1451 ****************************************************************************/
1452 void smbsrv_reply_rmdir(struct smbsrv_request *req)
1453 {
1454         struct smb_rmdir *io;
1455  
1456         /* parse the request */
1457         SMBSRV_CHECK_WCT(req, 0);
1458         SMBSRV_TALLOC_IO_PTR(io, struct smb_rmdir);
1459         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1460
1461         req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1462
1463         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rmdir(req->ntvfs, io));
1464 }
1465
1466
1467 /****************************************************************************
1468  Reply to a mv.
1469 ****************************************************************************/
1470 void smbsrv_reply_mv(struct smbsrv_request *req)
1471 {
1472         union smb_rename *io;
1473         uint8_t *p;
1474  
1475         /* parse the request */
1476         SMBSRV_CHECK_WCT(req, 1);
1477         SMBSRV_TALLOC_IO_PTR(io, union smb_rename);
1478         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1479
1480         io->generic.level = RAW_RENAME_RENAME;
1481         io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1482
1483         p = req->in.data;
1484         p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1485         p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1486
1487         if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1488                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1489                 return;
1490         }
1491
1492         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req->ntvfs, io));
1493 }
1494
1495
1496 /****************************************************************************
1497  Reply to an NT rename.
1498 ****************************************************************************/
1499 void smbsrv_reply_ntrename(struct smbsrv_request *req)
1500 {
1501         union smb_rename *io;
1502         uint8_t *p;
1503  
1504         /* parse the request */
1505         SMBSRV_CHECK_WCT(req, 4);
1506         SMBSRV_TALLOC_IO_PTR(io, union smb_rename);
1507         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1508
1509         io->generic.level = RAW_RENAME_NTRENAME;
1510         io->ntrename.in.attrib  = SVAL(req->in.vwv, VWV(0));
1511         io->ntrename.in.flags   = SVAL(req->in.vwv, VWV(1));
1512         io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1513
1514         p = req->in.data;
1515         p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1516         p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1517
1518         if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1519                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1520                 return;
1521         }
1522
1523         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req->ntvfs, io));
1524 }
1525
1526 /****************************************************************************
1527  Reply to a file copy (async reply)
1528 ****************************************************************************/
1529 static void reply_copy_send(struct ntvfs_request *ntvfs)
1530 {
1531         struct smbsrv_request *req;
1532         struct smb_copy *cp;
1533
1534         SMBSRV_CHECK_ASYNC_STATUS(cp, struct smb_copy);
1535
1536         /* build the reply */
1537         smbsrv_setup_reply(req, 1, 0);
1538
1539         SSVAL(req->out.vwv, VWV(0), cp->out.count);
1540
1541         smbsrv_send_reply(req);
1542 }
1543
1544 /****************************************************************************
1545  Reply to a file copy.
1546 ****************************************************************************/
1547 void smbsrv_reply_copy(struct smbsrv_request *req)
1548 {
1549         struct smb_copy *cp;
1550         uint8_t *p;
1551
1552         /* parse request */
1553         SMBSRV_CHECK_WCT(req, 3);
1554         SMBSRV_TALLOC_IO_PTR(cp, struct smb_copy);
1555         SMBSRV_SETUP_NTVFS_REQUEST(reply_copy_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1556
1557         cp->in.tid2  = SVAL(req->in.vwv, VWV(0));
1558         cp->in.ofun  = SVAL(req->in.vwv, VWV(1));
1559         cp->in.flags = SVAL(req->in.vwv, VWV(2));
1560
1561         p = req->in.data;
1562         p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1563         p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1564
1565         if (!cp->in.path1 || !cp->in.path2) {
1566                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1567                 return;
1568         }
1569
1570         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_copy(req->ntvfs, cp));
1571 }
1572
1573 /****************************************************************************
1574  Reply to a lockingX request (async send)
1575 ****************************************************************************/
1576 static void reply_lockingX_send(struct ntvfs_request *ntvfs)
1577 {
1578         struct smbsrv_request *req;
1579         union smb_lock *lck;
1580
1581         SMBSRV_CHECK_ASYNC_STATUS(lck, union smb_lock);
1582
1583         /* if it was an oplock break ack then we only send a reply if
1584            there was an error */
1585         if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1586                 talloc_free(req);
1587                 return;
1588         }
1589
1590         /* construct reply */
1591         smbsrv_setup_reply(req, 2, 0);
1592         
1593         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1594         SSVAL(req->out.vwv, VWV(1), 0);
1595
1596         smbsrv_chain_reply(req);
1597 }
1598
1599
1600 /****************************************************************************
1601  Reply to a lockingX request.
1602 ****************************************************************************/
1603 void smbsrv_reply_lockingX(struct smbsrv_request *req)
1604 {
1605         union smb_lock *lck;
1606         uint_t total_locks, i;
1607         uint_t lck_size;
1608         uint8_t *p;
1609
1610         /* parse request */
1611         SMBSRV_CHECK_WCT(req, 8);
1612         SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1613         SMBSRV_SETUP_NTVFS_REQUEST(reply_lockingX_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1614
1615         lck->lockx.level = RAW_LOCK_LOCKX;
1616         lck->lockx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
1617         lck->lockx.in.mode      = SVAL(req->in.vwv, VWV(3));
1618         lck->lockx.in.timeout   = IVAL(req->in.vwv, VWV(4));
1619         lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1620         lck->lockx.in.lock_cnt  = SVAL(req->in.vwv, VWV(7));
1621
1622         total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1623
1624         /* there are two variants, one with 64 bit offsets and counts */
1625         if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1626                 lck_size = 20;
1627         } else {
1628                 lck_size = 10;          
1629         }
1630
1631         /* make sure we got the promised data */
1632         if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1633                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1634                 return;
1635         }
1636
1637         /* allocate the locks array */
1638         if (total_locks) {
1639                 lck->lockx.in.locks = talloc_array(req, struct smb_lock_entry, 
1640                                                    total_locks);
1641                 if (lck->lockx.in.locks == NULL) {
1642                         smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1643                         return;
1644                 }
1645         }
1646
1647         p = req->in.data;
1648
1649         /* construct the locks array */
1650         for (i=0;i<total_locks;i++) {
1651                 uint32_t ofs_high=0, count_high=0;
1652
1653                 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1654
1655                 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1656                         ofs_high   = IVAL(p, 4);
1657                         lck->lockx.in.locks[i].offset = IVAL(p, 8);
1658                         count_high = IVAL(p, 12);
1659                         lck->lockx.in.locks[i].count  = IVAL(p, 16);
1660                 } else {
1661                         lck->lockx.in.locks[i].offset = IVAL(p, 2);
1662                         lck->lockx.in.locks[i].count  = IVAL(p, 6);
1663                 }
1664                 if (ofs_high != 0 || count_high != 0) {
1665                         lck->lockx.in.locks[i].count  |= ((uint64_t)count_high) << 32;
1666                         lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1667                 }
1668                 p += lck_size;
1669         }
1670
1671         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1672 }
1673
1674 /****************************************************************************
1675  Reply to a SMBreadbmpx (read block multiplex) request.
1676 ****************************************************************************/
1677 void smbsrv_reply_readbmpx(struct smbsrv_request *req)
1678 {
1679         /* tell the client to not use a multiplexed read - its too broken to use */
1680         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1681 }
1682
1683
1684 /****************************************************************************
1685  Reply to a SMBsetattrE.
1686 ****************************************************************************/
1687 void smbsrv_reply_setattrE(struct smbsrv_request *req)
1688 {
1689         union smb_setfileinfo *info;
1690
1691         /* parse request */
1692         SMBSRV_CHECK_WCT(req, 7);
1693         SMBSRV_TALLOC_IO_PTR(info, union smb_setfileinfo);
1694         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1695
1696         info->setattre.level = RAW_SFILEINFO_SETATTRE;
1697         info->setattre.in.file.fnum   = req_fnum(req, req->in.vwv,    VWV(0));
1698         info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1699         info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1700         info->setattre.in.write_time  = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1701
1702         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setfileinfo(req->ntvfs, info));
1703 }
1704
1705
1706 /****************************************************************************
1707  Reply to a SMBwritebmpx (write block multiplex primary) request.
1708 ****************************************************************************/
1709 void smbsrv_reply_writebmpx(struct smbsrv_request *req)
1710 {
1711         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1712 }
1713
1714
1715 /****************************************************************************
1716  Reply to a SMBwritebs (write block multiplex secondary) request.
1717 ****************************************************************************/
1718 void smbsrv_reply_writebs(struct smbsrv_request *req)
1719 {
1720         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1721 }
1722
1723
1724
1725 /****************************************************************************
1726  Reply to a SMBgetattrE (async reply)
1727 ****************************************************************************/
1728 static void reply_getattrE_send(struct ntvfs_request *ntvfs)
1729 {
1730         struct smbsrv_request *req;
1731         union smb_fileinfo *info;
1732
1733         SMBSRV_CHECK_ASYNC_STATUS(info, union smb_fileinfo);
1734
1735         /* setup reply */
1736         smbsrv_setup_reply(req, 11, 0);
1737
1738         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1739         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1740         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1741         SIVAL(req->out.vwv,         VWV(6), info->getattre.out.size);
1742         SIVAL(req->out.vwv,         VWV(8), info->getattre.out.alloc_size);
1743         SSVAL(req->out.vwv,        VWV(10), info->getattre.out.attrib);
1744
1745         smbsrv_send_reply(req);
1746 }
1747
1748 /****************************************************************************
1749  Reply to a SMBgetattrE.
1750 ****************************************************************************/
1751 void smbsrv_reply_getattrE(struct smbsrv_request *req)
1752 {
1753         union smb_fileinfo *info;
1754
1755         /* parse request */
1756         SMBSRV_CHECK_WCT(req, 1);
1757         SMBSRV_TALLOC_IO_PTR(info, union smb_fileinfo);
1758         SMBSRV_SETUP_NTVFS_REQUEST(reply_getattrE_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1759
1760         info->getattr.level = RAW_FILEINFO_GETATTRE;
1761         info->getattr.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1762
1763         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qfileinfo(req->ntvfs, info));
1764 }
1765
1766
1767 /****************************************************************************
1768 reply to an old style session setup command
1769 ****************************************************************************/
1770 static void reply_sesssetup_old(struct smbsrv_request *req)
1771 {
1772         NTSTATUS status;
1773         union smb_sesssetup sess;
1774         uint8_t *p;
1775         uint16_t passlen;
1776
1777         sess.old.level = RAW_SESSSETUP_OLD;
1778
1779         /* parse request */
1780         sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1781         sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1782         sess.old.in.vc_num  = SVAL(req->in.vwv, VWV(4));
1783         sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1784         passlen             = SVAL(req->in.vwv, VWV(7));
1785
1786         /* check the request isn't malformed */
1787         if (req_data_oob(req, req->in.data, passlen)) {
1788                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1789                 return;
1790         }
1791         
1792         p = req->in.data;
1793         if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1794                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1795                 return;
1796         }
1797         p += passlen;
1798         
1799         p += req_pull_string(req, &sess.old.in.user,   p, -1, STR_TERMINATE);
1800         p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1801         p += req_pull_string(req, &sess.old.in.os,     p, -1, STR_TERMINATE);
1802         p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
1803
1804         /* call the generic handler */
1805         status = smbsrv_sesssetup_backend(req, &sess);
1806
1807         if (!NT_STATUS_IS_OK(status)) {
1808                 smbsrv_send_error(req, status);
1809                 return;
1810         }
1811
1812         /* construct reply */
1813         smbsrv_setup_reply(req, 3, 0);
1814
1815         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1816         SSVAL(req->out.vwv, VWV(1), 0);
1817         SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
1818
1819         SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
1820
1821         smbsrv_chain_reply(req);
1822 }
1823
1824
1825 /****************************************************************************
1826 reply to an NT1 style session setup command
1827 ****************************************************************************/
1828 static void reply_sesssetup_nt1(struct smbsrv_request *req)
1829 {
1830         NTSTATUS status;
1831         union smb_sesssetup sess;
1832         uint8_t *p;
1833         uint16_t passlen1, passlen2;
1834
1835         sess.nt1.level = RAW_SESSSETUP_NT1;
1836
1837         /* parse request */
1838         sess.nt1.in.bufsize      = SVAL(req->in.vwv, VWV(2));
1839         sess.nt1.in.mpx_max      = SVAL(req->in.vwv, VWV(3));
1840         sess.nt1.in.vc_num       = SVAL(req->in.vwv, VWV(4));
1841         sess.nt1.in.sesskey      = IVAL(req->in.vwv, VWV(5));
1842         passlen1                 = SVAL(req->in.vwv, VWV(7));
1843         passlen2                 = SVAL(req->in.vwv, VWV(8));
1844         sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
1845
1846         /* check the request isn't malformed */
1847         if (req_data_oob(req, req->in.data, passlen1) ||
1848             req_data_oob(req, req->in.data + passlen1, passlen2)) {
1849                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1850                 return;
1851         }
1852         
1853         p = req->in.data;
1854         if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
1855                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1856                 return;
1857         }
1858         p += passlen1;
1859         if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
1860                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1861                 return;
1862         }
1863         p += passlen2;
1864         
1865         p += req_pull_string(req, &sess.nt1.in.user,   p, -1, STR_TERMINATE);
1866         p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
1867         p += req_pull_string(req, &sess.nt1.in.os,     p, -1, STR_TERMINATE);
1868         p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
1869
1870         /* call the generic handler */
1871         status = smbsrv_sesssetup_backend(req, &sess);
1872
1873         if (!NT_STATUS_IS_OK(status)) {
1874                 smbsrv_send_error(req, status);
1875                 return;
1876         }
1877
1878         /* construct reply */
1879         smbsrv_setup_reply(req, 3, 0);
1880
1881         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1882         SSVAL(req->out.vwv, VWV(1), 0);
1883         SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
1884
1885         SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
1886
1887         req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
1888         req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
1889         req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
1890
1891         smbsrv_chain_reply(req);
1892 }
1893
1894
1895 /****************************************************************************
1896 reply to an SPNEGO style session setup command
1897 ****************************************************************************/
1898 static void reply_sesssetup_spnego(struct smbsrv_request *req)
1899 {
1900         NTSTATUS status;
1901         union smb_sesssetup sess;
1902         uint8_t *p;
1903         uint16_t blob_len;
1904
1905         sess.spnego.level = RAW_SESSSETUP_SPNEGO;
1906
1907         /* parse request */
1908         sess.spnego.in.bufsize      = SVAL(req->in.vwv, VWV(2));
1909         sess.spnego.in.mpx_max      = SVAL(req->in.vwv, VWV(3));
1910         sess.spnego.in.vc_num       = SVAL(req->in.vwv, VWV(4));
1911         sess.spnego.in.sesskey      = IVAL(req->in.vwv, VWV(5));
1912         blob_len                    = SVAL(req->in.vwv, VWV(7));
1913         sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
1914
1915         p = req->in.data;
1916         if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
1917                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1918                 return;
1919         }
1920         p += blob_len;
1921         
1922         p += req_pull_string(req, &sess.spnego.in.os,        p, -1, STR_TERMINATE);
1923         p += req_pull_string(req, &sess.spnego.in.lanman,    p, -1, STR_TERMINATE);
1924         p += req_pull_string(req, &sess.spnego.in.workgroup, p, -1, STR_TERMINATE);
1925
1926         /* call the generic handler */
1927         status = smbsrv_sesssetup_backend(req, &sess);
1928
1929         if (!NT_STATUS_IS_OK(status) && 
1930             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1931                 smbsrv_send_error(req, status);
1932                 return;
1933         }
1934
1935         /* construct reply */
1936         smbsrv_setup_reply(req, 4, sess.spnego.out.secblob.length);
1937
1938         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1939                 smbsrv_setup_error(req, status);
1940         }
1941
1942         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1943         SSVAL(req->out.vwv, VWV(1), 0);
1944         SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
1945         SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
1946
1947         SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
1948
1949         memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
1950         req_push_str(req, NULL, sess.spnego.out.os,        -1, STR_TERMINATE);
1951         req_push_str(req, NULL, sess.spnego.out.lanman,    -1, STR_TERMINATE);
1952         req_push_str(req, NULL, sess.spnego.out.workgroup, -1, STR_TERMINATE);
1953
1954         smbsrv_chain_reply(req);
1955 }
1956
1957
1958 /****************************************************************************
1959 reply to a session setup command
1960 ****************************************************************************/
1961 void smbsrv_reply_sesssetup(struct smbsrv_request *req)
1962 {
1963         switch (req->in.wct) {
1964         case 10:
1965                 /* a pre-NT1 call */
1966                 reply_sesssetup_old(req);
1967                 return;
1968         case 13:
1969                 /* a NT1 call */
1970                 reply_sesssetup_nt1(req);
1971                 return;
1972         case 12:
1973                 /* a SPNEGO call */
1974                 reply_sesssetup_spnego(req);
1975                 return;
1976         }
1977
1978         /* unsupported variant */
1979         smbsrv_send_error(req, NT_STATUS_FOOBAR);
1980 }
1981
1982 /****************************************************************************
1983  Reply to a SMBulogoffX.
1984 ****************************************************************************/
1985 void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
1986 {
1987         struct smbsrv_tcon *tcon;
1988         NTSTATUS status;
1989
1990         /* in user level security we are supposed to close any files
1991            open by this user on all open tree connects */
1992         for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
1993                 req->tcon = tcon;
1994                 SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
1995                 status = ntvfs_logoff(req->ntvfs);
1996                 talloc_free(req->ntvfs);
1997                 req->ntvfs = NULL;
1998                 req->tcon = NULL;
1999                 if (!NT_STATUS_IS_OK(status)) {
2000                         smbsrv_send_error(req, status);
2001                         return;
2002                 }
2003         }
2004
2005         talloc_free(req->session);
2006         req->session = NULL; /* it is now invalid, don't use on 
2007                                 any chained packets */
2008
2009         smbsrv_setup_reply(req, 2, 0);
2010
2011         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2012         SSVAL(req->out.vwv, VWV(1), 0); 
2013         
2014         smbsrv_chain_reply(req);
2015 }
2016
2017 /****************************************************************************
2018  Reply to an SMBfindclose request
2019 ****************************************************************************/
2020 void smbsrv_reply_findclose(struct smbsrv_request *req)
2021 {
2022         union smb_search_close *io;
2023
2024         /* parse request */
2025         SMBSRV_CHECK_WCT(req, 1);
2026         SMBSRV_TALLOC_IO_PTR(io, union smb_search_close);
2027         SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
2028
2029         io->findclose.level     = RAW_FINDCLOSE_FINDCLOSE;
2030         io->findclose.in.handle = SVAL(req->in.vwv, VWV(0));
2031
2032         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_close(req->ntvfs, io));
2033 }
2034
2035 /****************************************************************************
2036  Reply to an SMBfindnclose request
2037 ****************************************************************************/
2038 void smbsrv_reply_findnclose(struct smbsrv_request *req)
2039 {
2040         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2041 }
2042
2043
2044 /****************************************************************************
2045  Reply to an SMBntcreateX request (async send)
2046 ****************************************************************************/
2047 static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs)
2048 {
2049         struct smbsrv_request *req;
2050         union smb_open *io;
2051
2052         SMBSRV_CHECK_ASYNC_STATUS(io, union smb_open);
2053
2054         /* construct reply */
2055         smbsrv_setup_reply(req, 34, 0);
2056
2057         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2058         SSVAL(req->out.vwv, VWV(1), 0); 
2059         SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2060
2061         /* the rest of the parameters are not aligned! */
2062         SSVAL(req->out.vwv,        5, io->ntcreatex.out.file.fnum);
2063         SIVAL(req->out.vwv,        7, io->ntcreatex.out.create_action);
2064         push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2065         push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2066         push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2067         push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2068         SIVAL(req->out.vwv,       43, io->ntcreatex.out.attrib);
2069         SBVAL(req->out.vwv,       47, io->ntcreatex.out.alloc_size);
2070         SBVAL(req->out.vwv,       55, io->ntcreatex.out.size);
2071         SSVAL(req->out.vwv,       63, io->ntcreatex.out.file_type);
2072         SSVAL(req->out.vwv,       65, io->ntcreatex.out.ipc_state);
2073         SCVAL(req->out.vwv,       67, io->ntcreatex.out.is_directory);
2074
2075         req->chained_fnum = io->ntcreatex.out.file.fnum;
2076
2077         smbsrv_chain_reply(req);
2078 }
2079
2080 /****************************************************************************
2081  Reply to an SMBntcreateX request
2082 ****************************************************************************/
2083 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request *req)
2084 {
2085         union smb_open *io;
2086         uint16_t fname_len;
2087
2088         /* parse the request */
2089         SMBSRV_CHECK_WCT(req, 24);
2090         SMBSRV_TALLOC_IO_PTR(io, union smb_open);
2091         SMBSRV_SETUP_NTVFS_REQUEST(reply_ntcreate_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
2092
2093         io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2094
2095         /* notice that the word parameters are not word aligned, so we don't use VWV() */
2096         fname_len =                         SVAL(req->in.vwv, 5);
2097         io->ntcreatex.in.flags =            IVAL(req->in.vwv, 7);
2098         io->ntcreatex.in.root_fid =         IVAL(req->in.vwv, 11);
2099         io->ntcreatex.in.access_mask =      IVAL(req->in.vwv, 15);
2100         io->ntcreatex.in.alloc_size =       BVAL(req->in.vwv, 19);
2101         io->ntcreatex.in.file_attr =        IVAL(req->in.vwv, 27);
2102         io->ntcreatex.in.share_access =     IVAL(req->in.vwv, 31);
2103         io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2104         io->ntcreatex.in.create_options =   IVAL(req->in.vwv, 39);
2105         io->ntcreatex.in.impersonation =    IVAL(req->in.vwv, 43);
2106         io->ntcreatex.in.security_flags =   CVAL(req->in.vwv, 47);
2107         io->ntcreatex.in.ea_list          = NULL;
2108         io->ntcreatex.in.sec_desc         = NULL;
2109
2110         /* we need a neater way to handle this alignment */
2111         if ((req->flags2 & FLAGS2_UNICODE_STRINGS) && 
2112             ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2113                 fname_len++;
2114         }
2115
2116         req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2117         if (!io->ntcreatex.in.fname) {
2118                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2119                 return;
2120         }
2121
2122         SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, io));
2123 }
2124
2125
2126 /****************************************************************************
2127  Reply to an SMBntcancel request
2128 ****************************************************************************/
2129 void smbsrv_reply_ntcancel(struct smbsrv_request *req)
2130 {
2131         /* NOTE: this request does not generate a reply */
2132         SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
2133         ntvfs_cancel(req->ntvfs);
2134         talloc_free(req);
2135 }
2136
2137 /*
2138   parse the called/calling names from session request
2139 */
2140 static NTSTATUS parse_session_request(struct smbsrv_request *req)
2141 {
2142         DATA_BLOB blob;
2143         NTSTATUS status;
2144         
2145         blob.data = req->in.buffer + 4;
2146         blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2147         if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2148
2149         req->smb_conn->negotiate.called_name  = talloc(req->smb_conn, struct nbt_name);
2150         req->smb_conn->negotiate.calling_name = talloc(req->smb_conn, struct nbt_name);
2151         if (req->smb_conn->negotiate.called_name == NULL ||
2152             req->smb_conn->negotiate.calling_name == NULL) {
2153                 return NT_STATUS_NO_MEMORY;
2154         }
2155
2156         status = nbt_name_from_blob(req->smb_conn, &blob,
2157                                     req->smb_conn->negotiate.called_name);
2158         NT_STATUS_NOT_OK_RETURN(status);
2159
2160         blob.data += blob.length;
2161         blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2162         if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2163
2164         status = nbt_name_from_blob(req->smb_conn, &blob,
2165                                     req->smb_conn->negotiate.calling_name);
2166         NT_STATUS_NOT_OK_RETURN(status);
2167
2168         req->smb_conn->negotiate.done_nbt_session = True;
2169
2170         return NT_STATUS_OK;
2171 }       
2172
2173
2174
2175 /****************************************************************************
2176  Reply to a special message - a SMB packet with non zero NBT message type
2177 ****************************************************************************/
2178 void smbsrv_reply_special(struct smbsrv_request *req)
2179 {
2180         uint8_t msg_type;
2181         uint8_t *buf = talloc_zero_array(req, uint8_t, 4);
2182
2183         msg_type = CVAL(req->in.buffer,0);
2184
2185         SIVAL(buf, 0, 0);
2186         
2187         switch (msg_type) {
2188         case 0x81: /* session request */
2189                 if (req->smb_conn->negotiate.done_nbt_session) {
2190                         DEBUG(0,("Warning: ignoring secondary session request\n"));
2191                         return;
2192                 }
2193                 
2194                 SCVAL(buf,0,0x82);
2195                 SCVAL(buf,3,0);
2196
2197                 /* we don't check the status - samba always accepts session
2198                    requests for any name */
2199                 parse_session_request(req);
2200
2201                 req->out.buffer = buf;
2202                 req->out.size = 4;
2203                 smbsrv_send_reply_nosign(req);
2204                 return;
2205                 
2206         case 0x89: /* session keepalive request 
2207                       (some old clients produce this?) */
2208                 SCVAL(buf, 0, SMBkeepalive);
2209                 SCVAL(buf, 3, 0);
2210                 req->out.buffer = buf;
2211                 req->out.size = 4;
2212                 smbsrv_send_reply_nosign(req);
2213                 return;
2214                 
2215         case SMBkeepalive: 
2216                 /* session keepalive - swallow it */
2217                 talloc_free(req);
2218                 return;
2219         }
2220
2221         DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));
2222         talloc_free(req);
2223 }