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