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