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