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