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