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