8b6dedb81a2a3ce52ed0d59e76ea07ac964fa5e3
[gd/samba-autobuild/.git] / source4 / smb_server / smb / reply.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main SMB reply routines
4    Copyright (C) Andrew Tridgell 1992-2003
5    Copyright (C) James J Myers 2003 <myersjj@samba.org>
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 /*
22    This file handles most of the reply_ calls that the server
23    makes to handle specific protocols
24 */
25
26 #include "includes.h"
27 #include "smb_server/smb_server.h"
28 #include "ntvfs/ntvfs.h"
29
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.file.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         union smb_chkpath *io;
259
260         REQ_TALLOC(io, union smb_chkpath);
261
262         req_pull_ascii4(req, &io->chkpath.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.file.path, req->in.data, STR_TERMINATE);
307         if (!st->getattr.file.path) {
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.path, req->in.data, STR_TERMINATE);
339
340         if (!st->setattr.file.path) {
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.file.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.file.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.file.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.file.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.file.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         union smb_unlink *unl;
648
649         /* parse the request */
650         REQ_CHECK_WCT(req, 1);
651         REQ_TALLOC(unl, union smb_unlink);
652         
653         unl->unlink.in.attrib = SVAL(req->in.vwv, VWV(0));
654
655         req_pull_ascii4(req, &unl->unlink.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.file.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.file.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.file.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.file.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         if (req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) {
904                 io->readx.in.read_for_execute = True;
905         } else {
906                 io->readx.in.read_for_execute = False;
907         }
908
909         if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
910                 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
911                 if (high_part == 1) {
912                         io->readx.in.maxcnt |= high_part << 16;
913                 }
914         }
915         
916         /* the 64 bit variant */
917         if (req->in.wct == 12) {
918                 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
919                 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
920         }
921
922         /* setup the reply packet assuming the maximum possible read */
923         smbsrv_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
924
925         /* tell the backend where to put the data. Notice the pad byte. */
926         if (io->readx.in.maxcnt != 0xFFFF &&
927             io->readx.in.mincnt != 0xFFFF) {
928                 io->readx.out.data = req->out.data + 1;
929         } else {
930                 io->readx.out.data = req->out.data;
931         }
932
933         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
934         req->async_states->send_fn = reply_read_and_X_send;
935         req->async_states->private_data = io;
936
937         /* call backend */
938         req->async_states->status = ntvfs_read(req, io);
939
940         REQ_ASYNC_TAIL;
941 }
942
943
944 /****************************************************************************
945  Reply to a writebraw (core+ or LANMAN1.0 protocol).
946 ****************************************************************************/
947 void smbsrv_reply_writebraw(struct smbsrv_request *req)
948 {
949         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
950 }
951
952
953 /****************************************************************************
954  Reply to a writeunlock (async reply)
955 ****************************************************************************/
956 static void reply_writeunlock_send(struct smbsrv_request *req)
957 {
958         union smb_write *io = req->async_states->private_data;
959
960         CHECK_ASYNC_STATUS;
961
962         /* construct reply */
963         smbsrv_setup_reply(req, 1, 0);
964
965         SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
966
967         smbsrv_send_reply(req);
968 }
969
970 /****************************************************************************
971  Reply to a writeunlock (core+).
972 ****************************************************************************/
973 void smbsrv_reply_writeunlock(struct smbsrv_request *req)
974 {
975         union smb_write *io;
976
977         REQ_CHECK_WCT(req, 5);
978         REQ_TALLOC(io, union smb_write);
979
980         io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
981         io->writeunlock.file.fnum      = req_fnum(req, req->in.vwv, VWV(0));
982         io->writeunlock.in.count       = SVAL(req->in.vwv, VWV(1));
983         io->writeunlock.in.offset      = IVAL(req->in.vwv, VWV(2));
984         io->writeunlock.in.remaining   = SVAL(req->in.vwv, VWV(4));
985         io->writeunlock.in.data        = req->in.data + 3;
986
987         /* make sure they gave us the data they promised */
988         if (io->writeunlock.in.count+3 > req->in.data_size) {
989                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
990                 return;
991         }
992
993         /* make sure the data block is big enough */
994         if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
995                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
996                 return;
997         }
998
999         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1000         req->async_states->send_fn = reply_writeunlock_send;
1001         req->async_states->private_data = io;
1002
1003         /* call backend */
1004         req->async_states->status = ntvfs_write(req, io);
1005
1006         REQ_ASYNC_TAIL;
1007 }
1008
1009
1010
1011 /****************************************************************************
1012  Reply to a write (async reply)
1013 ****************************************************************************/
1014 static void reply_write_send(struct smbsrv_request *req)
1015 {
1016         union smb_write *io = req->async_states->private_data;
1017         
1018         CHECK_ASYNC_STATUS;
1019
1020         /* construct reply */
1021         smbsrv_setup_reply(req, 1, 0);
1022
1023         SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1024
1025         smbsrv_send_reply(req);
1026 }
1027
1028 /****************************************************************************
1029  Reply to a write
1030 ****************************************************************************/
1031 void smbsrv_reply_write(struct smbsrv_request *req)
1032 {
1033         union smb_write *io;
1034
1035         REQ_CHECK_WCT(req, 5);
1036         REQ_TALLOC(io, union smb_write);
1037
1038         io->write.level = RAW_WRITE_WRITE;
1039         io->write.file.fnum      = req_fnum(req, req->in.vwv, VWV(0));
1040         io->write.in.count       = SVAL(req->in.vwv, VWV(1));
1041         io->write.in.offset      = IVAL(req->in.vwv, VWV(2));
1042         io->write.in.remaining   = SVAL(req->in.vwv, VWV(4));
1043         io->write.in.data        = req->in.data + 3;
1044
1045         /* make sure they gave us the data they promised */
1046         if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
1047                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1048                 return;
1049         }
1050
1051         /* make sure the data block is big enough */
1052         if (SVAL(req->in.data, 1) < io->write.in.count) {
1053                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1054                 return;
1055         }
1056
1057         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1058         req->async_states->send_fn = reply_write_send;
1059         req->async_states->private_data = io;
1060
1061         /* call backend */
1062         req->async_states->status = ntvfs_write(req, io);
1063
1064         REQ_ASYNC_TAIL;
1065 }
1066
1067
1068 /****************************************************************************
1069  Reply to a write and X (async reply)
1070 ****************************************************************************/
1071 static void reply_write_and_X_send(struct smbsrv_request *req)
1072 {
1073         union smb_write *io = req->async_states->private_data;
1074
1075         CHECK_ASYNC_STATUS;
1076
1077         /* construct reply */
1078         smbsrv_setup_reply(req, 6, 0);
1079
1080         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1081         SSVAL(req->out.vwv, VWV(1), 0);
1082         SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
1083         SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
1084         SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
1085         REQ_VWV_RESERVED(5, 1);
1086
1087         smbsrv_chain_reply(req);
1088 }
1089
1090 /****************************************************************************
1091  Reply to a write and X.
1092 ****************************************************************************/
1093 void smbsrv_reply_write_and_X(struct smbsrv_request *req)
1094 {
1095         union smb_write *io;
1096         
1097         if (req->in.wct != 14) {
1098                 REQ_CHECK_WCT(req, 12);
1099         }
1100
1101         REQ_TALLOC(io, union smb_write);
1102
1103         io->writex.level = RAW_WRITE_WRITEX;
1104         io->writex.file.fnum    = req_fnum(req, req->in.vwv, VWV(2));
1105         io->writex.in.offset    = IVAL(req->in.vwv, VWV(3));
1106         io->writex.in.wmode     = SVAL(req->in.vwv, VWV(7));
1107         io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1108         io->writex.in.count     = SVAL(req->in.vwv, VWV(10));
1109         io->writex.in.data      = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1110
1111         if (req->in.wct == 14) {
1112                 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1113                 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1114                 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1115                 io->writex.in.count |= ((uint32_t)count_high) << 16;
1116         }
1117
1118         /* make sure the data is in bounds */
1119         if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1120                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1121                 return;
1122         } 
1123
1124         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1125         req->async_states->send_fn = reply_write_and_X_send;
1126         req->async_states->private_data = io;
1127
1128         /* call backend */
1129         req->async_states->status = ntvfs_write(req, io);
1130
1131         REQ_ASYNC_TAIL;
1132 }
1133
1134
1135 /****************************************************************************
1136  Reply to a lseek (async reply)
1137 ****************************************************************************/
1138 static void reply_lseek_send(struct smbsrv_request *req)
1139 {
1140         union smb_seek *io = req->async_states->private_data;
1141
1142         CHECK_ASYNC_STATUS;
1143
1144         /* construct reply */
1145         smbsrv_setup_reply(req, 2, 0);
1146
1147         SIVALS(req->out.vwv, VWV(0), io->lseek.out.offset);
1148
1149         smbsrv_send_reply(req);
1150 }
1151
1152 /****************************************************************************
1153  Reply to a lseek.
1154 ****************************************************************************/
1155 void smbsrv_reply_lseek(struct smbsrv_request *req)
1156 {
1157         union smb_seek *io;
1158
1159         REQ_CHECK_WCT(req, 4);
1160         REQ_TALLOC(io, union smb_seek);
1161
1162         io->lseek.file.fnum   = req_fnum(req, req->in.vwv,  VWV(0));
1163         io->lseek.in.mode   = SVAL(req->in.vwv,  VWV(1));
1164         io->lseek.in.offset = IVALS(req->in.vwv, VWV(2));
1165
1166         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1167         req->async_states->send_fn = reply_lseek_send;
1168         req->async_states->private_data = io;
1169         
1170         /* call backend */
1171         req->async_states->status = ntvfs_seek(req, io);
1172
1173         REQ_ASYNC_TAIL;
1174 }
1175
1176 /****************************************************************************
1177  Reply to a flush.
1178 ****************************************************************************/
1179 void smbsrv_reply_flush(struct smbsrv_request *req)
1180 {
1181         union smb_flush *io;
1182
1183         /* parse request */
1184         REQ_CHECK_WCT(req, 1);
1185         REQ_TALLOC(io, union smb_flush);
1186
1187         io->flush.file.fnum   = req_fnum(req, req->in.vwv,  VWV(0));
1188
1189         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1190         req->async_states->send_fn = reply_simple_send;
1191
1192         /* call backend */
1193         req->async_states->status = ntvfs_flush(req, io);
1194         
1195         REQ_ASYNC_TAIL;
1196 }
1197
1198
1199 /****************************************************************************
1200  Reply to a exit. This closes all files open by a smbpid
1201 ****************************************************************************/
1202 void smbsrv_reply_exit(struct smbsrv_request *req)
1203 {
1204         NTSTATUS status;
1205         struct smbsrv_tcon *tcon;
1206         REQ_CHECK_WCT(req, 0);
1207
1208         for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
1209                 req->tcon = tcon;
1210                 status = ntvfs_exit(req);
1211                 req->tcon = NULL;
1212                 if (!NT_STATUS_IS_OK(status)) {
1213                         smbsrv_send_error(req, status);
1214                         return;
1215                 }
1216         }
1217
1218         smbsrv_setup_reply(req, 0, 0);
1219         smbsrv_send_reply(req);
1220 }
1221
1222
1223 /****************************************************************************
1224  Reply to a close 
1225
1226  Note that this has to deal with closing a directory opened by NT SMB's.
1227 ****************************************************************************/
1228 void smbsrv_reply_close(struct smbsrv_request *req)
1229 {
1230         union smb_close *io;
1231
1232         /* parse request */
1233         REQ_CHECK_WCT(req, 3);
1234         REQ_TALLOC(io, union smb_close);
1235
1236         io->close.level = RAW_CLOSE_CLOSE;
1237         io->close.file.fnum = req_fnum(req, req->in.vwv,  VWV(0));
1238         io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1239
1240         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1241         req->async_states->send_fn = reply_simple_send;
1242
1243         /* call backend */
1244         req->async_states->status = ntvfs_close(req, io);
1245
1246         REQ_ASYNC_TAIL;
1247 }
1248
1249
1250
1251 /****************************************************************************
1252  Reply to a writeclose (async reply)
1253 ****************************************************************************/
1254 static void reply_writeclose_send(struct smbsrv_request *req)
1255 {
1256         union smb_write *io = req->async_states->private_data;
1257
1258         CHECK_ASYNC_STATUS;
1259
1260         /* construct reply */
1261         smbsrv_setup_reply(req, 1, 0);
1262
1263         SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1264
1265         smbsrv_send_reply(req);
1266 }
1267
1268 /****************************************************************************
1269  Reply to a writeclose (Core+ protocol).
1270 ****************************************************************************/
1271 void smbsrv_reply_writeclose(struct smbsrv_request *req)
1272 {
1273         union smb_write *io;
1274
1275         /* this one is pretty weird - the wct can be 6 or 12 */
1276         if (req->in.wct != 12) {
1277                 REQ_CHECK_WCT(req, 6);
1278         }
1279
1280         REQ_TALLOC(io, union smb_write);
1281
1282         io->writeclose.level = RAW_WRITE_WRITECLOSE;
1283         io->writeclose.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1284         io->writeclose.in.count  = SVAL(req->in.vwv, VWV(1));
1285         io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1286         io->writeclose.in.mtime  = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1287         io->writeclose.in.data   = req->in.data + 1;
1288
1289         /* make sure they gave us the data they promised */
1290         if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1291                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1292                 return;
1293         }
1294
1295         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1296         req->async_states->send_fn = reply_writeclose_send;
1297         req->async_states->private_data = io;
1298
1299         /* call backend */
1300         req->async_states->status = ntvfs_write(req, io);
1301
1302         REQ_ASYNC_TAIL;
1303 }
1304
1305 /****************************************************************************
1306  Reply to a lock.
1307 ****************************************************************************/
1308 void smbsrv_reply_lock(struct smbsrv_request *req)
1309 {
1310         union smb_lock *lck;
1311
1312         /* parse request */
1313         REQ_CHECK_WCT(req, 5);
1314         REQ_TALLOC(lck, union smb_lock);
1315
1316         lck->lock.level     = RAW_LOCK_LOCK;
1317         lck->lock.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1318         lck->lock.in.count  = IVAL(req->in.vwv, VWV(1));
1319         lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1320
1321         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1322         req->async_states->send_fn = reply_simple_send;
1323
1324         /* call backend */
1325         req->async_states->status = ntvfs_lock(req, lck);
1326
1327         REQ_ASYNC_TAIL;
1328 }
1329
1330
1331 /****************************************************************************
1332  Reply to a unlock.
1333 ****************************************************************************/
1334 void smbsrv_reply_unlock(struct smbsrv_request *req)
1335 {
1336         union smb_lock *lck;
1337
1338         /* parse request */
1339         REQ_CHECK_WCT(req, 5);
1340         REQ_TALLOC(lck, union smb_lock);
1341
1342         lck->unlock.level = RAW_LOCK_UNLOCK;
1343         lck->unlock.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1344         lck->unlock.in.count  = IVAL(req->in.vwv, VWV(1));
1345         lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1346
1347         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1348         req->async_states->send_fn = reply_simple_send;
1349
1350         /* call backend */
1351         req->async_states->status = ntvfs_lock(req, lck);
1352
1353         REQ_ASYNC_TAIL;
1354 }
1355
1356
1357 /****************************************************************************
1358  Reply to a tdis.
1359 ****************************************************************************/
1360 void smbsrv_reply_tdis(struct smbsrv_request *req)
1361 {
1362         REQ_CHECK_WCT(req, 0);
1363
1364         if (req->tcon == NULL) {
1365                 smbsrv_send_error(req, NT_STATUS_INVALID_HANDLE);
1366                 return;
1367         }
1368
1369         talloc_free(req->tcon);
1370
1371         /* construct reply */
1372         smbsrv_setup_reply(req, 0, 0);
1373
1374         smbsrv_send_reply(req);
1375 }
1376
1377
1378 /****************************************************************************
1379  Reply to a echo. This is one of the few calls that is handled directly (the
1380  backends don't see it at all)
1381 ****************************************************************************/
1382 void smbsrv_reply_echo(struct smbsrv_request *req)
1383 {
1384         uint16_t count;
1385         int i;
1386
1387         REQ_CHECK_WCT(req, 0);
1388
1389         count = SVAL(req->in.vwv, VWV(0));
1390
1391         smbsrv_setup_reply(req, 1, req->in.data_size);
1392
1393         memcpy(req->out.data, req->in.data, req->in.data_size);
1394
1395         for (i=1; i <= count;i++) {
1396                 struct smbsrv_request *this_req;
1397                 
1398                 if (i != count) {
1399                         this_req = smbsrv_setup_secondary_request(req);
1400                 } else {
1401                         this_req = req;
1402                 }
1403
1404                 SSVAL(this_req->out.vwv, VWV(0), i);
1405                 smbsrv_send_reply(this_req);
1406         }
1407 }
1408
1409
1410
1411 /****************************************************************************
1412  Reply to a printopen (async reply)
1413 ****************************************************************************/
1414 static void reply_printopen_send(struct smbsrv_request *req)
1415 {
1416         union smb_open *oi = req->async_states->private_data;
1417
1418         CHECK_ASYNC_STATUS;
1419
1420         /* construct reply */
1421         smbsrv_setup_reply(req, 1, 0);
1422
1423         SSVAL(req->out.vwv, VWV(0), oi->openold.file.fnum);
1424
1425         smbsrv_send_reply(req);
1426 }
1427
1428 /****************************************************************************
1429  Reply to a printopen.
1430 ****************************************************************************/
1431 void smbsrv_reply_printopen(struct smbsrv_request *req)
1432 {
1433         union smb_open *oi;
1434
1435         /* parse request */
1436         REQ_CHECK_WCT(req, 2);
1437         REQ_TALLOC(oi, union smb_open);
1438
1439         oi->splopen.level = RAW_OPEN_SPLOPEN;
1440         oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1441         oi->splopen.in.mode         = SVAL(req->in.vwv, VWV(1));
1442
1443         req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1444
1445         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1446         req->async_states->send_fn = reply_printopen_send;
1447         req->async_states->private_data = oi;
1448
1449         /* call backend */
1450         req->async_states->status = ntvfs_open(req, oi);
1451
1452         REQ_ASYNC_TAIL;
1453 }
1454
1455 /****************************************************************************
1456  Reply to a printclose.
1457 ****************************************************************************/
1458 void smbsrv_reply_printclose(struct smbsrv_request *req)
1459 {
1460         union smb_close *io;
1461
1462         /* parse request */
1463         REQ_CHECK_WCT(req, 3);
1464         REQ_TALLOC(io, union smb_close);
1465
1466         io->splclose.level = RAW_CLOSE_SPLCLOSE;
1467         io->splclose.file.fnum = req_fnum(req, req->in.vwv,  VWV(0));
1468
1469         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1470         req->async_states->send_fn = reply_simple_send;
1471
1472         /* call backend */
1473         req->async_states->status = ntvfs_close(req, io);
1474
1475         REQ_ASYNC_TAIL;
1476 }
1477
1478 /****************************************************************************
1479  Reply to a printqueue.
1480 ****************************************************************************/
1481 static void reply_printqueue_send(struct smbsrv_request *req)
1482 {
1483         union smb_lpq *lpq = req->async_states->private_data;
1484         int i, maxcount;
1485         const uint_t el_size = 28;      
1486
1487         CHECK_ASYNC_STATUS;
1488
1489         /* construct reply */
1490         smbsrv_setup_reply(req, 2, 0);
1491
1492         /* truncate the returned list to fit in the negotiated buffer size */
1493         maxcount = (req_max_data(req) - 3) / el_size;
1494         if (maxcount < lpq->retq.out.count) {
1495                 lpq->retq.out.count = maxcount;
1496         }
1497
1498         /* setup enough space in the reply */
1499         req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1500         
1501         /* and fill it in */
1502         SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1503         SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1504
1505         SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1506         SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1507
1508         req->out.ptr = req->out.data + 3;
1509
1510         for (i=0;i<lpq->retq.out.count;i++) {
1511                 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1512                 SCVAL(req->out.ptr,  4, lpq->retq.out.queue[i].status);
1513                 SSVAL(req->out.ptr,  5, lpq->retq.out.queue[i].job);
1514                 SIVAL(req->out.ptr,  7, lpq->retq.out.queue[i].size);
1515                 SCVAL(req->out.ptr, 11, 0); /* reserved */
1516                 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1517                 req->out.ptr += el_size;
1518         }
1519
1520         smbsrv_send_reply(req);
1521 }
1522
1523 /****************************************************************************
1524  Reply to a printqueue.
1525 ****************************************************************************/
1526 void smbsrv_reply_printqueue(struct smbsrv_request *req)
1527 {
1528         union smb_lpq *lpq;
1529
1530         /* parse request */
1531         REQ_CHECK_WCT(req, 2);
1532         REQ_TALLOC(lpq, union smb_lpq);
1533
1534         lpq->retq.level = RAW_LPQ_RETQ;
1535         lpq->retq.in.maxcount = SVAL(req->in.vwv,  VWV(0));
1536         lpq->retq.in.startidx = SVAL(req->in.vwv,  VWV(1));
1537
1538         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1539         req->async_states->send_fn = reply_printqueue_send;
1540         req->async_states->private_data = lpq;
1541
1542         /* call backend */
1543         req->async_states->status = ntvfs_lpq(req, lpq);
1544
1545         REQ_ASYNC_TAIL;
1546 }
1547
1548
1549 /****************************************************************************
1550  Reply to a printwrite.
1551 ****************************************************************************/
1552 void smbsrv_reply_printwrite(struct smbsrv_request *req)
1553 {
1554         union smb_write *io;
1555
1556         /* parse request */
1557         REQ_CHECK_WCT(req, 1);
1558         REQ_TALLOC(io, union smb_write);
1559
1560         io->splwrite.level = RAW_WRITE_SPLWRITE;
1561
1562         if (req->in.data_size < 3) {
1563                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1564                 return;
1565         }
1566
1567         io->splwrite.file.fnum= req_fnum(req, req->in.vwv, VWV(0));
1568         io->splwrite.in.count = SVAL(req->in.data, 1);
1569         io->splwrite.in.data  = req->in.data + 3;
1570
1571         /* make sure they gave us the data they promised */
1572         if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1573                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1574                 return;
1575         }
1576
1577         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1578         req->async_states->send_fn = reply_simple_send;
1579
1580         /* call backend */
1581         req->async_states->status = ntvfs_write(req, io);
1582
1583         REQ_ASYNC_TAIL;
1584 }
1585
1586
1587 /****************************************************************************
1588  Reply to a mkdir.
1589 ****************************************************************************/
1590 void smbsrv_reply_mkdir(struct smbsrv_request *req)
1591 {
1592         union smb_mkdir *io;
1593
1594         /* parse the request */
1595         REQ_CHECK_WCT(req, 0);
1596         REQ_TALLOC(io, union smb_mkdir);
1597
1598         io->generic.level = RAW_MKDIR_MKDIR;
1599         req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1600
1601         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1602         req->async_states->send_fn = reply_simple_send;
1603
1604         /* call backend */
1605         req->async_states->status = ntvfs_mkdir(req, io);
1606
1607         REQ_ASYNC_TAIL;
1608 }
1609
1610
1611 /****************************************************************************
1612  Reply to a rmdir.
1613 ****************************************************************************/
1614 void smbsrv_reply_rmdir(struct smbsrv_request *req)
1615 {
1616         struct smb_rmdir *io;
1617  
1618         /* parse the request */
1619         REQ_CHECK_WCT(req, 0);
1620         REQ_TALLOC(io, struct smb_rmdir);
1621
1622         req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1623
1624         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1625         req->async_states->send_fn = reply_simple_send;
1626
1627         /* call backend */
1628         req->async_states->status = ntvfs_rmdir(req, io);
1629
1630         REQ_ASYNC_TAIL;
1631 }
1632
1633
1634 /****************************************************************************
1635  Reply to a mv.
1636 ****************************************************************************/
1637 void smbsrv_reply_mv(struct smbsrv_request *req)
1638 {
1639         union smb_rename *io;
1640         uint8_t *p;
1641  
1642         /* parse the request */
1643         REQ_CHECK_WCT(req, 1);
1644         REQ_TALLOC(io, union smb_rename);
1645
1646         io->generic.level = RAW_RENAME_RENAME;
1647         io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1648
1649         p = req->in.data;
1650         p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1651         p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1652
1653         if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1654                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1655                 return;
1656         }
1657
1658         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1659         req->async_states->send_fn = reply_simple_send;
1660
1661         /* call backend */
1662         req->async_states->status = ntvfs_rename(req, io);
1663
1664         REQ_ASYNC_TAIL;
1665 }
1666
1667
1668 /****************************************************************************
1669  Reply to an NT rename.
1670 ****************************************************************************/
1671 void smbsrv_reply_ntrename(struct smbsrv_request *req)
1672 {
1673         union smb_rename *io;
1674         uint8_t *p;
1675  
1676         /* parse the request */
1677         REQ_CHECK_WCT(req, 4);
1678         REQ_TALLOC(io, union smb_rename);
1679
1680         io->generic.level = RAW_RENAME_NTRENAME;
1681         io->ntrename.in.attrib  = SVAL(req->in.vwv, VWV(0));
1682         io->ntrename.in.flags   = SVAL(req->in.vwv, VWV(1));
1683         io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1684
1685         p = req->in.data;
1686         p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1687         p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1688
1689         if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1690                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1691                 return;
1692         }
1693
1694         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1695         req->async_states->send_fn = reply_simple_send;
1696
1697         /* call backend */
1698         req->async_states->status = ntvfs_rename(req, io);
1699
1700         REQ_ASYNC_TAIL;
1701 }
1702
1703 /****************************************************************************
1704  Reply to a file copy (async reply)
1705 ****************************************************************************/
1706 static void reply_copy_send(struct smbsrv_request *req)
1707 {
1708         struct smb_copy *cp = req->async_states->private_data;
1709
1710         CHECK_ASYNC_STATUS;
1711
1712         /* build the reply */
1713         smbsrv_setup_reply(req, 1, 0);
1714
1715         SSVAL(req->out.vwv, VWV(0), cp->out.count);
1716
1717         smbsrv_send_reply(req);
1718 }
1719
1720 /****************************************************************************
1721  Reply to a file copy.
1722 ****************************************************************************/
1723 void smbsrv_reply_copy(struct smbsrv_request *req)
1724 {
1725         struct smb_copy *cp;
1726         uint8_t *p;
1727
1728         /* parse request */
1729         REQ_CHECK_WCT(req, 3);
1730         REQ_TALLOC(cp, struct smb_copy);
1731
1732         cp->in.tid2  = SVAL(req->in.vwv, VWV(0));
1733         cp->in.ofun  = SVAL(req->in.vwv, VWV(1));
1734         cp->in.flags = SVAL(req->in.vwv, VWV(2));
1735
1736         p = req->in.data;
1737         p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1738         p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1739
1740         if (!cp->in.path1 || !cp->in.path2) {
1741                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1742                 return;
1743         }
1744
1745         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1746         req->async_states->send_fn = reply_copy_send;
1747         req->async_states->private_data = cp;
1748
1749         /* call backend */
1750         req->async_states->status = ntvfs_copy(req, cp);
1751
1752         REQ_ASYNC_TAIL;
1753 }
1754
1755 /****************************************************************************
1756  Reply to a lockingX request (async send)
1757 ****************************************************************************/
1758 static void reply_lockingX_send(struct smbsrv_request *req)
1759 {
1760         union smb_lock *lck = req->async_states->private_data;
1761
1762         CHECK_ASYNC_STATUS;
1763
1764         /* if it was an oplock break ack then we only send a reply if
1765            there was an error */
1766         if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1767                 talloc_free(req);
1768                 return;
1769         }
1770
1771         /* construct reply */
1772         smbsrv_setup_reply(req, 2, 0);
1773         
1774         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1775         SSVAL(req->out.vwv, VWV(1), 0);
1776
1777         smbsrv_chain_reply(req);
1778 }
1779
1780
1781 /****************************************************************************
1782  Reply to a lockingX request.
1783 ****************************************************************************/
1784 void smbsrv_reply_lockingX(struct smbsrv_request *req)
1785 {
1786         union smb_lock *lck;
1787         uint_t total_locks, i;
1788         uint_t lck_size;
1789         uint8_t *p;
1790
1791         /* parse request */
1792         REQ_CHECK_WCT(req, 8);
1793         REQ_TALLOC(lck, union smb_lock);
1794
1795         lck->lockx.level = RAW_LOCK_LOCKX;
1796         lck->lockx.file.fnum    = req_fnum(req, req->in.vwv, VWV(2));
1797         lck->lockx.in.mode      = SVAL(req->in.vwv, VWV(3));
1798         lck->lockx.in.timeout   = IVAL(req->in.vwv, VWV(4));
1799         lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1800         lck->lockx.in.lock_cnt  = SVAL(req->in.vwv, VWV(7));
1801
1802         total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1803
1804         /* there are two variants, one with 64 bit offsets and counts */
1805         if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1806                 lck_size = 20;
1807         } else {
1808                 lck_size = 10;          
1809         }
1810
1811         /* make sure we got the promised data */
1812         if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1813                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1814                 return;
1815         }
1816
1817         /* allocate the locks array */
1818         if (total_locks) {
1819                 lck->lockx.in.locks = talloc_array(req, struct smb_lock_entry, 
1820                                                    total_locks);
1821                 if (lck->lockx.in.locks == NULL) {
1822                         smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1823                         return;
1824                 }
1825         }
1826
1827         p = req->in.data;
1828
1829         /* construct the locks array */
1830         for (i=0;i<total_locks;i++) {
1831                 uint32_t ofs_high=0, count_high=0;
1832
1833                 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1834
1835                 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1836                         ofs_high   = IVAL(p, 4);
1837                         lck->lockx.in.locks[i].offset = IVAL(p, 8);
1838                         count_high = IVAL(p, 12);
1839                         lck->lockx.in.locks[i].count  = IVAL(p, 16);
1840                 } else {
1841                         lck->lockx.in.locks[i].offset = IVAL(p, 2);
1842                         lck->lockx.in.locks[i].count  = IVAL(p, 6);
1843                 }
1844                 if (ofs_high != 0 || count_high != 0) {
1845                         lck->lockx.in.locks[i].count  |= ((uint64_t)count_high) << 32;
1846                         lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1847                 }
1848                 p += lck_size;
1849         }
1850
1851         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1852         req->async_states->send_fn = reply_lockingX_send;
1853         req->async_states->private_data = lck;
1854
1855         /* call backend */
1856         req->async_states->status = ntvfs_lock(req, lck);
1857
1858         REQ_ASYNC_TAIL;
1859 }
1860
1861 /****************************************************************************
1862  Reply to a SMBreadbmpx (read block multiplex) request.
1863 ****************************************************************************/
1864 void smbsrv_reply_readbmpx(struct smbsrv_request *req)
1865 {
1866         /* tell the client to not use a multiplexed read - its too broken to use */
1867         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1868 }
1869
1870
1871 /****************************************************************************
1872  Reply to a SMBsetattrE.
1873 ****************************************************************************/
1874 void smbsrv_reply_setattrE(struct smbsrv_request *req)
1875 {
1876         union smb_setfileinfo *info;
1877
1878         /* parse request */
1879         REQ_CHECK_WCT(req, 7);
1880         REQ_TALLOC(info, union smb_setfileinfo);
1881
1882         info->setattre.level = RAW_SFILEINFO_SETATTRE;
1883         info->setattre.file.fnum      = req_fnum(req, req->in.vwv,    VWV(0));
1884         info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1885         info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1886         info->setattre.in.write_time  = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1887
1888         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1889         req->async_states->send_fn = reply_simple_send;
1890
1891         /* call backend */
1892         req->async_states->status = ntvfs_setfileinfo(req, info);
1893
1894         REQ_ASYNC_TAIL;
1895 }
1896
1897
1898 /****************************************************************************
1899  Reply to a SMBwritebmpx (write block multiplex primary) request.
1900 ****************************************************************************/
1901 void smbsrv_reply_writebmpx(struct smbsrv_request *req)
1902 {
1903         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1904 }
1905
1906
1907 /****************************************************************************
1908  Reply to a SMBwritebs (write block multiplex secondary) request.
1909 ****************************************************************************/
1910 void smbsrv_reply_writebs(struct smbsrv_request *req)
1911 {
1912         smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1913 }
1914
1915
1916
1917 /****************************************************************************
1918  Reply to a SMBgetattrE (async reply)
1919 ****************************************************************************/
1920 static void reply_getattrE_send(struct smbsrv_request *req)
1921 {
1922         union smb_fileinfo *info = req->async_states->private_data;
1923
1924         CHECK_ASYNC_STATUS;
1925
1926         /* setup reply */
1927         smbsrv_setup_reply(req, 11, 0);
1928
1929         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1930         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1931         srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1932         SIVAL(req->out.vwv,         VWV(6), info->getattre.out.size);
1933         SIVAL(req->out.vwv,         VWV(8), info->getattre.out.alloc_size);
1934         SSVAL(req->out.vwv,        VWV(10), info->getattre.out.attrib);
1935
1936         smbsrv_send_reply(req);
1937 }
1938
1939 /****************************************************************************
1940  Reply to a SMBgetattrE.
1941 ****************************************************************************/
1942 void smbsrv_reply_getattrE(struct smbsrv_request *req)
1943 {
1944         union smb_fileinfo *info;
1945
1946         /* parse request */
1947         REQ_CHECK_WCT(req, 1);
1948         REQ_TALLOC(info, union smb_fileinfo);
1949
1950         info->getattr.level = RAW_FILEINFO_GETATTRE;
1951         info->getattr.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1952
1953         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1954         req->async_states->send_fn = reply_getattrE_send;
1955         req->async_states->private_data = info;
1956
1957         /* call backend */
1958         req->async_states->status = ntvfs_qfileinfo(req, info);
1959
1960         REQ_ASYNC_TAIL;
1961 }
1962
1963
1964 /****************************************************************************
1965 reply to an old style session setup command
1966 ****************************************************************************/
1967 static void reply_sesssetup_old(struct smbsrv_request *req)
1968 {
1969         NTSTATUS status;
1970         union smb_sesssetup sess;
1971         uint8_t *p;
1972         uint16_t passlen;
1973
1974         sess.old.level = RAW_SESSSETUP_OLD;
1975
1976         /* parse request */
1977         sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1978         sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1979         sess.old.in.vc_num  = SVAL(req->in.vwv, VWV(4));
1980         sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1981         passlen             = SVAL(req->in.vwv, VWV(7));
1982
1983         /* check the request isn't malformed */
1984         if (req_data_oob(req, req->in.data, passlen)) {
1985                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1986                 return;
1987         }
1988         
1989         p = req->in.data;
1990         if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1991                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1992                 return;
1993         }
1994         p += passlen;
1995         
1996         p += req_pull_string(req, &sess.old.in.user,   p, -1, STR_TERMINATE);
1997         p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1998         p += req_pull_string(req, &sess.old.in.os,     p, -1, STR_TERMINATE);
1999         p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
2000
2001         /* call the generic handler */
2002         status = smbsrv_sesssetup_backend(req, &sess);
2003
2004         if (!NT_STATUS_IS_OK(status)) {
2005                 smbsrv_send_error(req, status);
2006                 return;
2007         }
2008
2009         /* construct reply */
2010         smbsrv_setup_reply(req, 3, 0);
2011
2012         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2013         SSVAL(req->out.vwv, VWV(1), 0);
2014         SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
2015
2016         SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
2017
2018         smbsrv_chain_reply(req);
2019 }
2020
2021
2022 /****************************************************************************
2023 reply to an NT1 style session setup command
2024 ****************************************************************************/
2025 static void reply_sesssetup_nt1(struct smbsrv_request *req)
2026 {
2027         NTSTATUS status;
2028         union smb_sesssetup sess;
2029         uint8_t *p;
2030         uint16_t passlen1, passlen2;
2031
2032         sess.nt1.level = RAW_SESSSETUP_NT1;
2033
2034         /* parse request */
2035         sess.nt1.in.bufsize      = SVAL(req->in.vwv, VWV(2));
2036         sess.nt1.in.mpx_max      = SVAL(req->in.vwv, VWV(3));
2037         sess.nt1.in.vc_num       = SVAL(req->in.vwv, VWV(4));
2038         sess.nt1.in.sesskey      = IVAL(req->in.vwv, VWV(5));
2039         passlen1                 = SVAL(req->in.vwv, VWV(7));
2040         passlen2                 = SVAL(req->in.vwv, VWV(8));
2041         sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
2042
2043         /* check the request isn't malformed */
2044         if (req_data_oob(req, req->in.data, passlen1) ||
2045             req_data_oob(req, req->in.data + passlen1, passlen2)) {
2046                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2047                 return;
2048         }
2049         
2050         p = req->in.data;
2051         if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
2052                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2053                 return;
2054         }
2055         p += passlen1;
2056         if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
2057                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2058                 return;
2059         }
2060         p += passlen2;
2061         
2062         p += req_pull_string(req, &sess.nt1.in.user,   p, -1, STR_TERMINATE);
2063         p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
2064         p += req_pull_string(req, &sess.nt1.in.os,     p, -1, STR_TERMINATE);
2065         p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
2066
2067         /* call the generic handler */
2068         status = smbsrv_sesssetup_backend(req, &sess);
2069
2070         if (!NT_STATUS_IS_OK(status)) {
2071                 smbsrv_send_error(req, status);
2072                 return;
2073         }
2074
2075         /* construct reply */
2076         smbsrv_setup_reply(req, 3, 0);
2077
2078         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2079         SSVAL(req->out.vwv, VWV(1), 0);
2080         SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
2081
2082         SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
2083
2084         req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
2085         req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
2086         req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
2087
2088         smbsrv_chain_reply(req);
2089 }
2090
2091
2092 /****************************************************************************
2093 reply to an SPNEGO style session setup command
2094 ****************************************************************************/
2095 static void reply_sesssetup_spnego(struct smbsrv_request *req)
2096 {
2097         NTSTATUS status;
2098         union smb_sesssetup sess;
2099         uint8_t *p;
2100         uint16_t blob_len;
2101
2102         sess.spnego.level = RAW_SESSSETUP_SPNEGO;
2103
2104         /* parse request */
2105         sess.spnego.in.bufsize      = SVAL(req->in.vwv, VWV(2));
2106         sess.spnego.in.mpx_max      = SVAL(req->in.vwv, VWV(3));
2107         sess.spnego.in.vc_num       = SVAL(req->in.vwv, VWV(4));
2108         sess.spnego.in.sesskey      = IVAL(req->in.vwv, VWV(5));
2109         blob_len                    = SVAL(req->in.vwv, VWV(7));
2110         sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
2111
2112         p = req->in.data;
2113         if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
2114                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2115                 return;
2116         }
2117         p += blob_len;
2118         
2119         p += req_pull_string(req, &sess.spnego.in.os,        p, -1, STR_TERMINATE);
2120         p += req_pull_string(req, &sess.spnego.in.lanman,    p, -1, STR_TERMINATE);
2121         p += req_pull_string(req, &sess.spnego.in.workgroup, p, -1, STR_TERMINATE);
2122
2123         /* call the generic handler */
2124         status = smbsrv_sesssetup_backend(req, &sess);
2125
2126         if (!NT_STATUS_IS_OK(status) && 
2127             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2128                 smbsrv_send_error(req, status);
2129                 return;
2130         }
2131
2132         /* construct reply */
2133         smbsrv_setup_reply(req, 4, sess.spnego.out.secblob.length);
2134
2135         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2136                 smbsrv_setup_error(req, status);
2137         }
2138
2139         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2140         SSVAL(req->out.vwv, VWV(1), 0);
2141         SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
2142         SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
2143
2144         SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
2145
2146         memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
2147         req_push_str(req, NULL, sess.spnego.out.os,        -1, STR_TERMINATE);
2148         req_push_str(req, NULL, sess.spnego.out.lanman,    -1, STR_TERMINATE);
2149         req_push_str(req, NULL, sess.spnego.out.workgroup, -1, STR_TERMINATE);
2150
2151         smbsrv_chain_reply(req);
2152 }
2153
2154
2155 /****************************************************************************
2156 reply to a session setup command
2157 ****************************************************************************/
2158 void smbsrv_reply_sesssetup(struct smbsrv_request *req)
2159 {
2160         switch (req->in.wct) {
2161         case 10:
2162                 /* a pre-NT1 call */
2163                 reply_sesssetup_old(req);
2164                 return;
2165         case 13:
2166                 /* a NT1 call */
2167                 reply_sesssetup_nt1(req);
2168                 return;
2169         case 12:
2170                 /* a SPNEGO call */
2171                 reply_sesssetup_spnego(req);
2172                 return;
2173         }
2174
2175         /* unsupported variant */
2176         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2177 }
2178
2179 /****************************************************************************
2180  Reply to a SMBulogoffX.
2181 ****************************************************************************/
2182 void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
2183 {
2184         struct smbsrv_tcon *tcon;
2185         NTSTATUS status;
2186
2187         if (!req->session) {
2188                 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
2189                 return;
2190         }
2191
2192         /* in user level security we are supposed to close any files
2193            open by this user on all open tree connects */
2194         for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
2195                 req->tcon = tcon;
2196                 status = ntvfs_logoff(req);
2197                 req->tcon = NULL;
2198                 if (!NT_STATUS_IS_OK(status)) {
2199                         smbsrv_send_error(req, status);
2200                         return;
2201                 }
2202         }
2203
2204         talloc_free(req->session);
2205         req->session = NULL; /* it is now invalid, don't use on 
2206                                 any chained packets */
2207
2208         smbsrv_setup_reply(req, 2, 0);
2209
2210         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2211         SSVAL(req->out.vwv, VWV(1), 0); 
2212         
2213         smbsrv_chain_reply(req);
2214 }
2215
2216
2217 /****************************************************************************
2218  Reply to an SMBfindclose request
2219 ****************************************************************************/
2220 void smbsrv_reply_findclose(struct smbsrv_request *req)
2221 {
2222         NTSTATUS status;
2223         union smb_search_close io;
2224
2225         io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2226
2227         /* parse request */
2228         REQ_CHECK_WCT(req, 1);
2229
2230         io.findclose.in.handle  = SVAL(req->in.vwv, VWV(0));
2231         
2232         /* call backend */
2233         status = ntvfs_search_close(req, &io);
2234
2235         if (!NT_STATUS_IS_OK(status)) {
2236                 smbsrv_send_error(req, status);
2237                 return;
2238         }
2239
2240         /* construct reply */
2241         smbsrv_setup_reply(req, 0, 0);
2242
2243         smbsrv_send_reply(req); 
2244 }
2245
2246 /****************************************************************************
2247  Reply to an SMBfindnclose request
2248 ****************************************************************************/
2249 void smbsrv_reply_findnclose(struct smbsrv_request *req)
2250 {
2251         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2252 }
2253
2254
2255 /****************************************************************************
2256  Reply to an SMBntcreateX request (async send)
2257 ****************************************************************************/
2258 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
2259 {
2260         union smb_open *io = req->async_states->private_data;
2261
2262         CHECK_ASYNC_STATUS;
2263
2264         /* construct reply */
2265         smbsrv_setup_reply(req, 34, 0);
2266
2267         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2268         SSVAL(req->out.vwv, VWV(1), 0); 
2269         SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2270
2271         /* the rest of the parameters are not aligned! */
2272         SSVAL(req->out.vwv,        5, io->ntcreatex.file.fnum);
2273         SIVAL(req->out.vwv,        7, io->ntcreatex.out.create_action);
2274         push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2275         push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2276         push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2277         push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2278         SIVAL(req->out.vwv,       43, io->ntcreatex.out.attrib);
2279         SBVAL(req->out.vwv,       47, io->ntcreatex.out.alloc_size);
2280         SBVAL(req->out.vwv,       55, io->ntcreatex.out.size);
2281         SSVAL(req->out.vwv,       63, io->ntcreatex.out.file_type);
2282         SSVAL(req->out.vwv,       65, io->ntcreatex.out.ipc_state);
2283         SCVAL(req->out.vwv,       67, io->ntcreatex.out.is_directory);
2284
2285         req->chained_fnum = io->ntcreatex.file.fnum;
2286
2287         smbsrv_chain_reply(req);
2288 }
2289
2290 /****************************************************************************
2291  Reply to an SMBntcreateX request
2292 ****************************************************************************/
2293 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request *req)
2294 {
2295         union smb_open *io;
2296         uint16_t fname_len;
2297
2298         /* parse the request */
2299         REQ_CHECK_WCT(req, 24);
2300         REQ_TALLOC(io, union smb_open);
2301
2302         io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2303
2304         /* notice that the word parameters are not word aligned, so we don't use VWV() */
2305         fname_len =                         SVAL(req->in.vwv, 5);
2306         io->ntcreatex.in.flags =            IVAL(req->in.vwv, 7);
2307         io->ntcreatex.in.root_fid =         IVAL(req->in.vwv, 11);
2308         io->ntcreatex.in.access_mask =      IVAL(req->in.vwv, 15);
2309         io->ntcreatex.in.alloc_size =       BVAL(req->in.vwv, 19);
2310         io->ntcreatex.in.file_attr =        IVAL(req->in.vwv, 27);
2311         io->ntcreatex.in.share_access =     IVAL(req->in.vwv, 31);
2312         io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2313         io->ntcreatex.in.create_options =   IVAL(req->in.vwv, 39);
2314         io->ntcreatex.in.impersonation =    IVAL(req->in.vwv, 43);
2315         io->ntcreatex.in.security_flags =   CVAL(req->in.vwv, 47);
2316         io->ntcreatex.in.ea_list          = NULL;
2317         io->ntcreatex.in.sec_desc         = NULL;
2318
2319         /* we need a neater way to handle this alignment */
2320         if ((req->flags2 & FLAGS2_UNICODE_STRINGS) && 
2321             ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2322                 fname_len++;
2323         }
2324
2325         req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2326         if (!io->ntcreatex.in.fname) {
2327                 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2328                 return;
2329         }
2330
2331         req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
2332         req->async_states->send_fn = reply_ntcreate_and_X_send;
2333         req->async_states->private_data = io;
2334
2335         /* call the backend */
2336         req->async_states->status = ntvfs_open(req, io);
2337
2338         REQ_ASYNC_TAIL;
2339 }
2340
2341
2342 /****************************************************************************
2343  Reply to an SMBntcancel request
2344 ****************************************************************************/
2345 void smbsrv_reply_ntcancel(struct smbsrv_request *req)
2346 {
2347         /* NOTE: this request does not generate a reply */
2348         ntvfs_cancel(req);
2349         talloc_free(req);
2350 }
2351
2352 /****************************************************************************
2353  Reply to an SMBsends request
2354 ****************************************************************************/
2355 void smbsrv_reply_sends(struct smbsrv_request *req)
2356 {
2357         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2358 }
2359
2360 /****************************************************************************
2361  Reply to an SMBsendstrt request
2362 ****************************************************************************/
2363 void smbsrv_reply_sendstrt(struct smbsrv_request *req)
2364 {
2365         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2366 }
2367
2368 /****************************************************************************
2369  Reply to an SMBsendend request
2370 ****************************************************************************/
2371 void smbsrv_reply_sendend(struct smbsrv_request *req)
2372 {
2373         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2374 }
2375
2376 /****************************************************************************
2377  Reply to an SMBsendtxt request
2378 ****************************************************************************/
2379 void smbsrv_reply_sendtxt(struct smbsrv_request *req)
2380 {
2381         smbsrv_send_error(req, NT_STATUS_FOOBAR);
2382 }
2383
2384
2385 /*
2386   parse the called/calling names from session request
2387 */
2388 static NTSTATUS parse_session_request(struct smbsrv_request *req)
2389 {
2390         DATA_BLOB blob;
2391         NTSTATUS status;
2392         
2393         blob.data = req->in.buffer + 4;
2394         blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2395         if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2396
2397         req->smb_conn->negotiate.called_name  = talloc(req->smb_conn, struct nbt_name);
2398         req->smb_conn->negotiate.calling_name = talloc(req->smb_conn, struct nbt_name);
2399         if (req->smb_conn->negotiate.called_name == NULL ||
2400             req->smb_conn->negotiate.calling_name == NULL) {
2401                 return NT_STATUS_NO_MEMORY;
2402         }
2403
2404         status = nbt_name_from_blob(req->smb_conn, &blob,
2405                                     req->smb_conn->negotiate.called_name);
2406         NT_STATUS_NOT_OK_RETURN(status);
2407
2408         blob.data += blob.length;
2409         blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2410         if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2411
2412         status = nbt_name_from_blob(req->smb_conn, &blob,
2413                                     req->smb_conn->negotiate.calling_name);
2414         NT_STATUS_NOT_OK_RETURN(status);
2415
2416         req->smb_conn->negotiate.done_nbt_session = True;
2417
2418         return NT_STATUS_OK;
2419 }       
2420
2421
2422
2423 /****************************************************************************
2424  Reply to a special message - a SMB packet with non zero NBT message type
2425 ****************************************************************************/
2426 void smbsrv_reply_special(struct smbsrv_request *req)
2427 {
2428         uint8_t msg_type;
2429         uint8_t *buf = talloc_zero_array(req, uint8_t, 4);
2430
2431         msg_type = CVAL(req->in.buffer,0);
2432
2433         SIVAL(buf, 0, 0);
2434         
2435         switch (msg_type) {
2436         case 0x81: /* session request */
2437                 if (req->smb_conn->negotiate.done_nbt_session) {
2438                         DEBUG(0,("Warning: ignoring secondary session request\n"));
2439                         return;
2440                 }
2441                 
2442                 SCVAL(buf,0,0x82);
2443                 SCVAL(buf,3,0);
2444
2445                 /* we don't check the status - samba always accepts session
2446                    requests for any name */
2447                 parse_session_request(req);
2448
2449                 req->out.buffer = buf;
2450                 req->out.size = 4;
2451                 smbsrv_send_reply_nosign(req);
2452                 return;
2453                 
2454         case 0x89: /* session keepalive request 
2455                       (some old clients produce this?) */
2456                 SCVAL(buf, 0, SMBkeepalive);
2457                 SCVAL(buf, 3, 0);
2458                 req->out.buffer = buf;
2459                 req->out.size = 4;
2460                 smbsrv_send_reply_nosign(req);
2461                 return;
2462                 
2463         case SMBkeepalive: 
2464                 /* session keepalive - swallow it */
2465                 talloc_free(req);
2466                 return;
2467         }
2468
2469         DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));
2470         talloc_free(req);
2471 }