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