93697afd4aeb255ca62c8d0d5b3dfe0bbdda5ea8
[jelmer/samba4-debian.git] / source / 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                 smbsrv_send_error(req, NT_STATUS_DOS(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                 smbsrv_send_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, type) do { \
49         ptr = talloc(req, type); \
50         if (!ptr) { \
51                 smbsrv_send_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         smbsrv_setup_reply(req, 0, 0);
76         smbsrv_send_reply(req);
77 }
78
79
80 /****************************************************************************
81  Reply to a tcon.
82 ****************************************************************************/
83 void smbsrv_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                 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
101                 return;
102         }
103
104         /* call backend */
105         status = smbsrv_tcon_backend(req, &con);
106
107         if (!NT_STATUS_IS_OK(status)) {
108                 smbsrv_send_error(req, status);
109                 return;
110         }
111
112         /* construct reply */
113         smbsrv_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         smbsrv_send_reply(req);
120 }
121
122
123 /****************************************************************************
124  Reply to a tcon and X.
125 ****************************************************************************/
126 void smbsrv_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                 smbsrv_send_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                 smbsrv_send_error(req, NT_STATUS_BAD_DEVICE_TYPE);
154                 return;
155         }
156
157         /* call backend */
158         status = smbsrv_tcon_backend(req, &con);
159
160         if (!NT_STATUS_IS_OK(status)) {
161                 smbsrv_send_error(req, status);
162                 return;
163         }
164
165         /* construct reply - two variants */
166         if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
167                 smbsrv_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                 smbsrv_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         smbsrv_chain_reply(req);
189 }
190
191
192 /****************************************************************************
193  Reply to an unknown request
194 ****************************************************************************/
195 void smbsrv_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         smbsrv_send_error(req, NT_STATUS_DOS(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         smbsrv_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         smbsrv_send_reply(req);
225 }
226
227 /****************************************************************************
228  Reply to an ioctl.
229 ****************************************************************************/
230 void smbsrv_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, union smb_ioctl);
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 smbsrv_reply_chkpth(struct smbsrv_request *req)
257 {
258         struct smb_chkpath *io;
259
260         REQ_TALLOC(io, struct smb_chkpath);
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         smbsrv_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         smbsrv_send_reply(req);
291 }
292
293
294 /****************************************************************************
295  Reply to a getatr.
296 ****************************************************************************/
297 void smbsrv_reply_getatr(struct smbsrv_request *req)
298 {
299         union smb_fileinfo *st;
300
301         REQ_TALLOC(st, union smb_fileinfo);
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                 smbsrv_send_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 smbsrv_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, union smb_setfileinfo);
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                 smbsrv_send_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         smbsrv_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         smbsrv_send_reply(req);
375 }
376
377
378 /****************************************************************************
379  Reply to a dskattr.
380 ****************************************************************************/
381 void smbsrv_reply_dskattr(struct smbsrv_request *req)
382 {
383         union smb_fsinfo *fs;
384
385         REQ_TALLOC(fs, union smb_fsinfo);
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         smbsrv_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         smbsrv_send_reply(req);
420 }
421
422 /****************************************************************************
423  Reply to an open.
424 ****************************************************************************/
425 void smbsrv_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, union smb_open);
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                 smbsrv_send_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_open(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                 smbsrv_setup_reply(req, 19, 0);
467         } else {
468                 smbsrv_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         smbsrv_chain_reply(req);
491 }
492
493
494 /****************************************************************************
495  Reply to an open and X.
496 ****************************************************************************/
497 void smbsrv_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, union smb_open);
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                 smbsrv_send_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_open(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         smbsrv_setup_reply(req, 1, 0);
544
545         SSVAL(req->out.vwv, VWV(0), oi->mknew.out.fnum);
546
547         smbsrv_send_reply(req);
548 }
549
550
551 /****************************************************************************
552  Reply to a mknew or a create.
553 ****************************************************************************/
554 void smbsrv_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, union smb_open);
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                 smbsrv_send_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_open(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         smbsrv_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         smbsrv_send_reply(req);
605 }
606
607 /****************************************************************************
608  Reply to a create temporary file.
609 ****************************************************************************/
610 void smbsrv_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, union smb_open);
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                 smbsrv_send_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_open(req, oi);
637
638         REQ_ASYNC_TAIL;
639 }
640
641
642 /****************************************************************************
643  Reply to a unlink
644 ****************************************************************************/
645 void smbsrv_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, struct smb_unlink);
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 smbsrv_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         smbsrv_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         smbsrv_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         smbsrv_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 smbsrv_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, union smb_read);
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         smbsrv_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         smbsrv_send_reply(req);
814 }
815
816 /****************************************************************************
817  Reply to a read.
818 ****************************************************************************/
819 void smbsrv_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, union smb_read);
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         smbsrv_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         smbsrv_chain_reply(req);
881 }
882
883 /****************************************************************************
884  Reply to a read and X.
885 ****************************************************************************/
886 void smbsrv_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, union smb_read);
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         smbsrv_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 smbsrv_reply_writebraw(struct smbsrv_request *req)
943 {
944         smbsrv_send_error(req, NT_STATUS_DOS(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         smbsrv_setup_reply(req, 1, 0);
959
960         SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
961
962         smbsrv_send_reply(req);
963 }
964
965 /****************************************************************************
966  Reply to a writeunlock (core+).
967 ****************************************************************************/
968 void smbsrv_reply_writeunlock(struct smbsrv_request *req)
969 {
970         union smb_write *io;
971
972         REQ_CHECK_WCT(req, 5);
973         REQ_TALLOC(io, union smb_write);
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                 smbsrv_send_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                 smbsrv_send_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         smbsrv_setup_reply(req, 1, 0);
1017
1018         SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1019
1020         smbsrv_send_reply(req);
1021 }
1022
1023 /****************************************************************************
1024  Reply to a write
1025 ****************************************************************************/
1026 void smbsrv_reply_write(struct smbsrv_request *req)
1027 {
1028         union smb_write *io;
1029
1030         REQ_CHECK_WCT(req, 5);
1031         REQ_TALLOC(io, union smb_write);
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                 smbsrv_send_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                 smbsrv_send_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         smbsrv_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         smbsrv_chain_reply(req);
1083 }
1084
1085 /****************************************************************************
1086  Reply to a write and X.
1087 ****************************************************************************/
1088 void smbsrv_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, union smb_write);
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                 smbsrv_send_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         smbsrv_setup_reply(req, 2, 0);
1141
1142         SIVALS(req->out.vwv, VWV(0), io->out.offset);
1143
1144         smbsrv_send_reply(req);
1145 }
1146
1147 /****************************************************************************
1148  Reply to a lseek.
1149 ****************************************************************************/
1150 void smbsrv_reply_lseek(struct smbsrv_request *req)
1151 {
1152         struct smb_seek *io;
1153
1154         REQ_CHECK_WCT(req, 4);
1155         REQ_TALLOC(io, struct smb_seek);
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 smbsrv_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, struct smb_flush);
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 smbsrv_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                         smbsrv_send_error(req, status);
1209                         return;
1210                 }
1211         }
1212
1213         smbsrv_setup_reply(req, 0, 0);
1214         smbsrv_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 smbsrv_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, union smb_close);
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         smbsrv_setup_reply(req, 1, 0);
1257
1258         SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1259
1260         smbsrv_send_reply(req);
1261 }
1262
1263 /****************************************************************************
1264  Reply to a writeclose (Core+ protocol).
1265 ****************************************************************************/
1266 void smbsrv_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, union smb_write);
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                 smbsrv_send_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 smbsrv_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, union smb_lock);
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 smbsrv_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, union smb_lock);
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 smbsrv_reply_tdis(struct smbsrv_request *req)
1356 {
1357         REQ_CHECK_WCT(req, 0);
1358
1359         if (req->tcon == NULL) {
1360                 smbsrv_send_error(req, NT_STATUS_INVALID_HANDLE);
1361                 return;
1362         }
1363
1364         talloc_free(req->tcon);
1365
1366         /* construct reply */
1367         smbsrv_setup_reply(req, 0, 0);
1368
1369         smbsrv_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 smbsrv_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         smbsrv_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 = smbsrv_setup_secondary_request(req);
1395                 } else {
1396                         this_req = req;
1397                 }
1398
1399                 SSVAL(this_req->out.vwv, VWV(0), i);
1400                 smbsrv_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         smbsrv_setup_reply(req, 1, 0);
1417
1418         SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
1419
1420         smbsrv_send_reply(req);
1421 }
1422
1423 /****************************************************************************
1424  Reply to a printopen.
1425 ****************************************************************************/
1426 void smbsrv_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, union smb_open);
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_open(req, oi);
1446
1447         REQ_ASYNC_TAIL;
1448 }
1449
1450 /****************************************************************************
1451  Reply to a printclose.
1452 ****************************************************************************/
1453 void smbsrv_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, union smb_close);
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 static 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         smbsrv_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         smbsrv_send_reply(req);
1516 }
1517
1518 /****************************************************************************
1519  Reply to a printqueue.
1520 ****************************************************************************/
1521 void smbsrv_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, union smb_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 smbsrv_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, union smb_write);
1554
1555         io->splwrite.level = RAW_WRITE_SPLWRITE;
1556
1557         if (req->in.data_size < 3) {
1558                 smbsrv_send_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                 smbsrv_send_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 smbsrv_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, union smb_mkdir);
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 smbsrv_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, struct smb_rmdir);
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 smbsrv_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, union smb_rename);
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                 smbsrv_send_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 smbsrv_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, union smb_rename);
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                 smbsrv_send_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         smbsrv_setup_reply(req, 1, 0);
1709
1710         SSVAL(req->out.vwv, VWV(0), cp->out.count);
1711
1712         smbsrv_send_reply(req);
1713 }
1714
1715 /****************************************************************************
1716  Reply to a file copy.
1717 ****************************************************************************/
1718 void smbsrv_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, struct smb_copy);
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                 smbsrv_send_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                 talloc_free(req);
1763                 return;
1764         }
1765
1766         /* construct reply */
1767         smbsrv_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         smbsrv_chain_reply(req);
1773 }
1774
1775
1776 /****************************************************************************
1777  Reply to a lockingX request.
1778 ****************************************************************************/
1779 void smbsrv_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, union smb_lock);
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                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1809                 return;
1810         }
1811
1812         /* allocate the locks array */
1813         if (total_locks) {
1814                 lck->lockx.in.locks = talloc_array(req, struct smb_lock_entry, 
1815                                                    total_locks);
1816                 if (lck->lockx.in.locks == NULL) {
1817                         smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1818                         return;
1819                 }
1820         }
1821
1822         p = req->in.data;
1823
1824         /* construct the locks array */
1825         for (i=0;i<total_locks;i++) {
1826                 uint32_t ofs_high=0, count_high=0;
1827
1828                 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1829
1830                 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1831                         ofs_high   = IVAL(p, 4);
1832                         lck->lockx.in.locks[i].offset = IVAL(p, 8);
1833                         count_high = IVAL(p, 12);
1834                         lck->lockx.in.locks[i].count  = IVAL(p, 16);
1835                 } else {
1836                         lck->lockx.in.locks[i].offset = IVAL(p, 2);
1837                         lck->lockx.in.locks[i].count  = IVAL(p, 6);
1838                 }
1839                 if (ofs_high != 0 || count_high != 0) {
1840                         lck->lockx.in.locks[i].count  |= ((uint64_t)count_high) << 32;
1841                         lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1842                 }
1843                 p += lck_size;
1844         }
1845
1846         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1847         req->async_states->send_fn = reply_lockingX_send;
1848         req->async_states->private_data = lck;
1849
1850         /* call backend */
1851         req->async_states->status = ntvfs_lock(req, lck);
1852
1853         REQ_ASYNC_TAIL;
1854 }
1855
1856 /****************************************************************************
1857  Reply to a SMBreadbmpx (read block multiplex) request.
1858 ****************************************************************************/
1859 void smbsrv_reply_readbmpx(struct smbsrv_request *req)
1860 {
1861         /* tell the client to not use a multiplexed read - its too broken to use */
1862         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1863 }
1864
1865
1866 /****************************************************************************
1867  Reply to a SMBsetattrE.
1868 ****************************************************************************/
1869 void smbsrv_reply_setattrE(struct smbsrv_request *req)
1870 {
1871         union smb_setfileinfo *info;
1872
1873         /* parse request */
1874         REQ_CHECK_WCT(req, 7);
1875         REQ_TALLOC(info, union smb_setfileinfo);
1876
1877         info->setattre.level = RAW_SFILEINFO_SETATTRE;
1878         info->setattre.file.fnum =      req_fnum(req, req->in.vwv,    VWV(0));
1879         info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1880         info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1881         info->setattre.in.write_time  = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1882
1883         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1884         req->async_states->send_fn = reply_simple_send;
1885
1886         /* call backend */
1887         req->async_states->status = ntvfs_setfileinfo(req, info);
1888
1889         REQ_ASYNC_TAIL;
1890 }
1891
1892
1893 /****************************************************************************
1894  Reply to a SMBwritebmpx (write block multiplex primary) request.
1895 ****************************************************************************/
1896 void smbsrv_reply_writebmpx(struct smbsrv_request *req)
1897 {
1898         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1899 }
1900
1901
1902 /****************************************************************************
1903  Reply to a SMBwritebs (write block multiplex secondary) request.
1904 ****************************************************************************/
1905 void smbsrv_reply_writebs(struct smbsrv_request *req)
1906 {
1907         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1908 }
1909
1910
1911
1912 /****************************************************************************
1913  Reply to a SMBgetattrE (async reply)
1914 ****************************************************************************/
1915 static void reply_getattrE_send(struct smbsrv_request *req)
1916 {
1917         union smb_fileinfo *info = req->async_states->private_data;
1918
1919         CHECK_ASYNC_STATUS;
1920
1921         /* setup reply */
1922         smbsrv_setup_reply(req, 11, 0);
1923
1924         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1925         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1926         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1927         SIVAL(req->out.vwv,         VWV(6), info->getattre.out.size);
1928         SIVAL(req->out.vwv,         VWV(8), info->getattre.out.alloc_size);
1929         SSVAL(req->out.vwv,        VWV(10), info->getattre.out.attrib);
1930
1931         smbsrv_send_reply(req);
1932 }
1933
1934 /****************************************************************************
1935  Reply to a SMBgetattrE.
1936 ****************************************************************************/
1937 void smbsrv_reply_getattrE(struct smbsrv_request *req)
1938 {
1939         union smb_fileinfo *info;
1940
1941         /* parse request */
1942         REQ_CHECK_WCT(req, 1);
1943         REQ_TALLOC(info, union smb_fileinfo);
1944
1945         info->getattr.level = RAW_FILEINFO_GETATTRE;
1946         info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1947
1948         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1949         req->async_states->send_fn = reply_getattrE_send;
1950         req->async_states->private_data = info;
1951
1952         /* call backend */
1953         req->async_states->status = ntvfs_qfileinfo(req, info);
1954
1955         REQ_ASYNC_TAIL;
1956 }
1957
1958
1959 /****************************************************************************
1960 reply to an old style session setup command
1961 ****************************************************************************/
1962 static void reply_sesssetup_old(struct smbsrv_request *req)
1963 {
1964         NTSTATUS status;
1965         union smb_sesssetup sess;
1966         uint8_t *p;
1967         uint16_t passlen;
1968
1969         sess.old.level = RAW_SESSSETUP_OLD;
1970
1971         /* parse request */
1972         sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1973         sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1974         sess.old.in.vc_num  = SVAL(req->in.vwv, VWV(4));
1975         sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1976         passlen             = SVAL(req->in.vwv, VWV(7));
1977
1978         /* check the request isn't malformed */
1979         if (req_data_oob(req, req->in.data, passlen)) {
1980                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1981                 return;
1982         }
1983         
1984         p = req->in.data;
1985         if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1986                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1987                 return;
1988         }
1989         p += passlen;
1990         
1991         p += req_pull_string(req, &sess.old.in.user,   p, -1, STR_TERMINATE);
1992         p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1993         p += req_pull_string(req, &sess.old.in.os,     p, -1, STR_TERMINATE);
1994         p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
1995
1996         /* call the generic handler */
1997         status = smbsrv_sesssetup_backend(req, &sess);
1998
1999         if (!NT_STATUS_IS_OK(status)) {
2000                 smbsrv_send_error(req, status);
2001                 return;
2002         }
2003
2004         /* construct reply */
2005         smbsrv_setup_reply(req, 3, 0);
2006
2007         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2008         SSVAL(req->out.vwv, VWV(1), 0);
2009         SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
2010
2011         SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
2012
2013         smbsrv_chain_reply(req);
2014 }
2015
2016
2017 /****************************************************************************
2018 reply to an NT1 style session setup command
2019 ****************************************************************************/
2020 static void reply_sesssetup_nt1(struct smbsrv_request *req)
2021 {
2022         NTSTATUS status;
2023         union smb_sesssetup sess;
2024         uint8_t *p;
2025         uint16_t passlen1, passlen2;
2026
2027         sess.nt1.level = RAW_SESSSETUP_NT1;
2028
2029         /* parse request */
2030         sess.nt1.in.bufsize      = SVAL(req->in.vwv, VWV(2));
2031         sess.nt1.in.mpx_max      = SVAL(req->in.vwv, VWV(3));
2032         sess.nt1.in.vc_num       = SVAL(req->in.vwv, VWV(4));
2033         sess.nt1.in.sesskey      = IVAL(req->in.vwv, VWV(5));
2034         passlen1                 = SVAL(req->in.vwv, VWV(7));
2035         passlen2                 = SVAL(req->in.vwv, VWV(8));
2036         sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
2037
2038         /* check the request isn't malformed */
2039         if (req_data_oob(req, req->in.data, passlen1) ||
2040             req_data_oob(req, req->in.data + passlen1, passlen2)) {
2041                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2042                 return;
2043         }
2044         
2045         p = req->in.data;
2046         if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
2047                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2048                 return;
2049         }
2050         p += passlen1;
2051         if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
2052                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2053                 return;
2054         }
2055         p += passlen2;
2056         
2057         p += req_pull_string(req, &sess.nt1.in.user,   p, -1, STR_TERMINATE);
2058         p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
2059         p += req_pull_string(req, &sess.nt1.in.os,     p, -1, STR_TERMINATE);
2060         p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
2061
2062         /* call the generic handler */
2063         status = smbsrv_sesssetup_backend(req, &sess);
2064
2065         if (!NT_STATUS_IS_OK(status)) {
2066                 smbsrv_send_error(req, status);
2067                 return;
2068         }
2069
2070         /* construct reply */
2071         smbsrv_setup_reply(req, 3, 0);
2072
2073         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2074         SSVAL(req->out.vwv, VWV(1), 0);
2075         SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
2076
2077         SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
2078
2079         req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
2080         req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
2081         req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
2082
2083         smbsrv_chain_reply(req);
2084 }
2085
2086
2087 /****************************************************************************
2088 reply to an SPNEGO style session setup command
2089 ****************************************************************************/
2090 static void reply_sesssetup_spnego(struct smbsrv_request *req)
2091 {
2092         NTSTATUS status;
2093         union smb_sesssetup sess;
2094         uint8_t *p;
2095         uint16_t blob_len;
2096
2097         sess.spnego.level = RAW_SESSSETUP_SPNEGO;
2098
2099         /* parse request */
2100         sess.spnego.in.bufsize      = SVAL(req->in.vwv, VWV(2));
2101         sess.spnego.in.mpx_max      = SVAL(req->in.vwv, VWV(3));
2102         sess.spnego.in.vc_num       = SVAL(req->in.vwv, VWV(4));
2103         sess.spnego.in.sesskey      = IVAL(req->in.vwv, VWV(5));
2104         blob_len                    = SVAL(req->in.vwv, VWV(7));
2105         sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
2106
2107         p = req->in.data;
2108         if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
2109                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2110                 return;
2111         }
2112         p += blob_len;
2113         
2114         p += req_pull_string(req, &sess.spnego.in.os,        p, -1, STR_TERMINATE);
2115         p += req_pull_string(req, &sess.spnego.in.lanman,    p, -1, STR_TERMINATE);
2116         p += req_pull_string(req, &sess.spnego.in.workgroup, p, -1, STR_TERMINATE);
2117
2118         /* call the generic handler */
2119         status = smbsrv_sesssetup_backend(req, &sess);
2120
2121         if (!NT_STATUS_IS_OK(status) && 
2122             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2123                 smbsrv_send_error(req, status);
2124                 return;
2125         }
2126
2127         /* construct reply */
2128         smbsrv_setup_reply(req, 4, sess.spnego.out.secblob.length);
2129
2130         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2131                 smbsrv_setup_error(req, status);
2132         }
2133
2134         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2135         SSVAL(req->out.vwv, VWV(1), 0);
2136         SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
2137         SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
2138
2139         SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
2140
2141         memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
2142         req_push_str(req, NULL, sess.spnego.out.os,        -1, STR_TERMINATE);
2143         req_push_str(req, NULL, sess.spnego.out.lanman,    -1, STR_TERMINATE);
2144         req_push_str(req, NULL, sess.spnego.out.workgroup, -1, STR_TERMINATE);
2145
2146         smbsrv_chain_reply(req);
2147 }
2148
2149
2150 /****************************************************************************
2151 reply to a session setup command
2152 ****************************************************************************/
2153 void smbsrv_reply_sesssetup(struct smbsrv_request *req)
2154 {
2155         switch (req->in.wct) {
2156         case 10:
2157                 /* a pre-NT1 call */
2158                 reply_sesssetup_old(req);
2159                 return;
2160         case 13:
2161                 /* a NT1 call */
2162                 reply_sesssetup_nt1(req);
2163                 return;
2164         case 12:
2165                 /* a SPNEGO call */
2166                 reply_sesssetup_spnego(req);
2167                 return;
2168         }
2169
2170         /* unsupported variant */
2171         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2172 }
2173
2174 /****************************************************************************
2175  Reply to a SMBulogoffX.
2176 ****************************************************************************/
2177 void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
2178 {
2179         struct smbsrv_tcon *tcon;
2180         NTSTATUS status;
2181
2182         if (!req->session) {
2183                 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
2184                 return;
2185         }
2186
2187         /* in user level security we are supposed to close any files
2188            open by this user on all open tree connects */
2189         for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
2190                 req->tcon = tcon;
2191                 status = ntvfs_logoff(req);
2192                 req->tcon = NULL;
2193                 if (!NT_STATUS_IS_OK(status)) {
2194                         smbsrv_send_error(req, status);
2195                         return;
2196                 }
2197         }
2198
2199         talloc_free(req->session);
2200         req->session = NULL; /* it is now invalid, don't use on 
2201                                 any chained packets */
2202
2203         smbsrv_setup_reply(req, 2, 0);
2204
2205         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2206         SSVAL(req->out.vwv, VWV(1), 0); 
2207         
2208         smbsrv_chain_reply(req);
2209 }
2210
2211
2212 /****************************************************************************
2213  Reply to an SMBfindclose request
2214 ****************************************************************************/
2215 void smbsrv_reply_findclose(struct smbsrv_request *req)
2216 {
2217         NTSTATUS status;
2218         union smb_search_close io;
2219
2220         io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2221
2222         /* parse request */
2223         REQ_CHECK_WCT(req, 1);
2224
2225         io.findclose.in.handle  = SVAL(req->in.vwv, VWV(0));
2226         
2227         /* call backend */
2228         status = ntvfs_search_close(req, &io);
2229
2230         if (!NT_STATUS_IS_OK(status)) {
2231                 smbsrv_send_error(req, status);
2232                 return;
2233         }
2234
2235         /* construct reply */
2236         smbsrv_setup_reply(req, 0, 0);
2237
2238         smbsrv_send_reply(req); 
2239 }
2240
2241 /****************************************************************************
2242  Reply to an SMBfindnclose request
2243 ****************************************************************************/
2244 void smbsrv_reply_findnclose(struct smbsrv_request *req)
2245 {
2246         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2247 }
2248
2249
2250 /****************************************************************************
2251  Reply to an SMBntcreateX request (async send)
2252 ****************************************************************************/
2253 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
2254 {
2255         union smb_open *io = req->async_states->private_data;
2256
2257         CHECK_ASYNC_STATUS;
2258
2259         /* construct reply */
2260         smbsrv_setup_reply(req, 34, 0);
2261
2262         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2263         SSVAL(req->out.vwv, VWV(1), 0); 
2264         SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2265
2266         /* the rest of the parameters are not aligned! */
2267         SSVAL(req->out.vwv,        5, io->ntcreatex.out.fnum);
2268         SIVAL(req->out.vwv,        7, io->ntcreatex.out.create_action);
2269         push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2270         push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2271         push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2272         push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2273         SIVAL(req->out.vwv,       43, io->ntcreatex.out.attrib);
2274         SBVAL(req->out.vwv,       47, io->ntcreatex.out.alloc_size);
2275         SBVAL(req->out.vwv,       55, io->ntcreatex.out.size);
2276         SSVAL(req->out.vwv,       63, io->ntcreatex.out.file_type);
2277         SSVAL(req->out.vwv,       65, io->ntcreatex.out.ipc_state);
2278         SCVAL(req->out.vwv,       67, io->ntcreatex.out.is_directory);
2279
2280         req->chained_fnum = io->ntcreatex.out.fnum;
2281
2282         smbsrv_chain_reply(req);
2283 }
2284
2285 /****************************************************************************
2286  Reply to an SMBntcreateX request
2287 ****************************************************************************/
2288 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request *req)
2289 {
2290         union smb_open *io;
2291         uint16_t fname_len;
2292
2293         /* parse the request */
2294         REQ_CHECK_WCT(req, 24);
2295         REQ_TALLOC(io, union smb_open);
2296
2297         io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2298
2299         /* notice that the word parameters are not word aligned, so we don't use VWV() */
2300         fname_len =                         SVAL(req->in.vwv, 5);
2301         io->ntcreatex.in.flags =            IVAL(req->in.vwv, 7);
2302         io->ntcreatex.in.root_fid =         IVAL(req->in.vwv, 11);
2303         io->ntcreatex.in.access_mask =      IVAL(req->in.vwv, 15);
2304         io->ntcreatex.in.alloc_size =       BVAL(req->in.vwv, 19);
2305         io->ntcreatex.in.file_attr =        IVAL(req->in.vwv, 27);
2306         io->ntcreatex.in.share_access =     IVAL(req->in.vwv, 31);
2307         io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2308         io->ntcreatex.in.create_options =   IVAL(req->in.vwv, 39);
2309         io->ntcreatex.in.impersonation =    IVAL(req->in.vwv, 43);
2310         io->ntcreatex.in.security_flags =   CVAL(req->in.vwv, 47);
2311         io->ntcreatex.in.ea_list          = NULL;
2312         io->ntcreatex.in.sec_desc         = NULL;
2313
2314         /* we need a neater way to handle this alignment */
2315         if ((req->flags2 & FLAGS2_UNICODE_STRINGS) && 
2316             ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2317                 fname_len++;
2318         }
2319
2320         req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2321         if (!io->ntcreatex.in.fname) {
2322                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2323                 return;
2324         }
2325
2326         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
2327         req->async_states->send_fn = reply_ntcreate_and_X_send;
2328         req->async_states->private_data = io;
2329
2330         /* call the backend */
2331         req->async_states->status = ntvfs_open(req, io);
2332
2333         REQ_ASYNC_TAIL;
2334 }
2335
2336
2337 /****************************************************************************
2338  Reply to an SMBntcancel request
2339 ****************************************************************************/
2340 void smbsrv_reply_ntcancel(struct smbsrv_request *req)
2341 {
2342         /* NOTE: this request does not generate a reply */
2343         ntvfs_cancel(req);
2344         talloc_free(req);
2345 }
2346
2347 /****************************************************************************
2348  Reply to an SMBsends request
2349 ****************************************************************************/
2350 void smbsrv_reply_sends(struct smbsrv_request *req)
2351 {
2352         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2353 }
2354
2355 /****************************************************************************
2356  Reply to an SMBsendstrt request
2357 ****************************************************************************/
2358 void smbsrv_reply_sendstrt(struct smbsrv_request *req)
2359 {
2360         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2361 }
2362
2363 /****************************************************************************
2364  Reply to an SMBsendend request
2365 ****************************************************************************/
2366 void smbsrv_reply_sendend(struct smbsrv_request *req)
2367 {
2368         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2369 }
2370
2371 /****************************************************************************
2372  Reply to an SMBsendtxt request
2373 ****************************************************************************/
2374 void smbsrv_reply_sendtxt(struct smbsrv_request *req)
2375 {
2376         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2377 }
2378
2379
2380 /*
2381   parse the called/calling names from session request
2382 */
2383 static NTSTATUS parse_session_request(struct smbsrv_request *req)
2384 {
2385         DATA_BLOB blob;
2386         NTSTATUS status;
2387         
2388         blob.data = req->in.buffer + 4;
2389         blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2390         if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2391
2392         req->smb_conn->negotiate.called_name  = talloc(req->smb_conn, struct nbt_name);
2393         req->smb_conn->negotiate.calling_name = talloc(req->smb_conn, struct nbt_name);
2394         if (req->smb_conn->negotiate.called_name == NULL ||
2395             req->smb_conn->negotiate.calling_name == NULL) {
2396                 return NT_STATUS_NO_MEMORY;
2397         }
2398
2399         status = nbt_name_from_blob(req->smb_conn, &blob,
2400                                     req->smb_conn->negotiate.called_name);
2401         NT_STATUS_NOT_OK_RETURN(status);
2402
2403         blob.data += blob.length;
2404         blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2405         if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2406
2407         status = nbt_name_from_blob(req->smb_conn, &blob,
2408                                     req->smb_conn->negotiate.calling_name);
2409         NT_STATUS_NOT_OK_RETURN(status);
2410
2411         req->smb_conn->negotiate.done_nbt_session = True;
2412
2413         return NT_STATUS_OK;
2414 }       
2415
2416
2417
2418 /****************************************************************************
2419  Reply to a special message - a SMB packet with non zero NBT message type
2420 ****************************************************************************/
2421 void smbsrv_reply_special(struct smbsrv_request *req)
2422 {
2423         uint8_t msg_type;
2424         uint8_t *buf = talloc_zero_array(req, uint8_t, 4);
2425
2426         msg_type = CVAL(req->in.buffer,0);
2427
2428         SIVAL(buf, 0, 0);
2429         
2430         switch (msg_type) {
2431         case 0x81: /* session request */
2432                 if (req->smb_conn->negotiate.done_nbt_session) {
2433                         DEBUG(0,("Warning: ignoring secondary session request\n"));
2434                         return;
2435                 }
2436                 
2437                 SCVAL(buf,0,0x82);
2438                 SCVAL(buf,3,0);
2439
2440                 /* we don't check the status - samba always accepts session
2441                    requests for any name */
2442                 parse_session_request(req);
2443
2444                 req->out.buffer = buf;
2445                 req->out.size = 4;
2446                 smbsrv_send_reply_nosign(req);
2447                 return;
2448                 
2449         case 0x89: /* session keepalive request 
2450                       (some old clients produce this?) */
2451                 SCVAL(buf, 0, SMBkeepalive);
2452                 SCVAL(buf, 3, 0);
2453                 req->out.buffer = buf;
2454                 req->out.size = 4;
2455                 smbsrv_send_reply_nosign(req);
2456                 return;
2457                 
2458         case SMBkeepalive: 
2459                 /* session keepalive - swallow it */
2460                 talloc_free(req);
2461                 return;
2462         }
2463
2464         DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));
2465         talloc_free(req);
2466 }