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>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "smb_server/smb_server.h"
28 #include "ntvfs/ntvfs.h"
29 #include "librpc/gen_ndr/ndr_nbt.h"
32 /* useful way of catching wct errors with file and line number */
33 #define REQ_CHECK_WCT(req, wcount) do { \
34 if ((req)->in.wct != (wcount)) { \
35 DEBUG(1,("Unexpected WCT %d at %s(%d) - expected %d\n", \
36 (req)->in.wct, __FILE__, __LINE__, wcount)); \
37 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRerror)); \
41 /* check req->async_states->status and if not OK then send an error reply */
42 #define CHECK_ASYNC_STATUS do { \
43 if (!NT_STATUS_IS_OK(req->async_states->status)) { \
44 smbsrv_send_error(req, req->async_states->status); \
48 /* useful wrapper for talloc with NO_MEMORY reply */
49 #define REQ_TALLOC(ptr, type) do { \
50 ptr = talloc(req, type); \
52 smbsrv_send_error(req, NT_STATUS_NO_MEMORY); \
57 check if the backend wants to handle the request asynchronously.
58 if it wants it handled synchronously then call the send function
61 #define REQ_ASYNC_TAIL do { \
62 if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
63 req->async_states->send_fn(req); \
66 /* zero out some reserved fields in a reply */
67 #define REQ_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)
69 /****************************************************************************
70 Reply to a simple request (async send)
71 ****************************************************************************/
72 static void reply_simple_send(struct smbsrv_request *req)
76 smbsrv_setup_reply(req, 0, 0);
77 smbsrv_send_reply(req);
81 /****************************************************************************
83 ****************************************************************************/
84 void smbsrv_reply_tcon(struct smbsrv_request *req)
91 REQ_CHECK_WCT(req, 0);
93 con.tcon.level = RAW_TCON_TCON;
96 p += req_pull_ascii4(req, &con.tcon.in.service, p, STR_TERMINATE);
97 p += req_pull_ascii4(req, &con.tcon.in.password, p, STR_TERMINATE);
98 p += req_pull_ascii4(req, &con.tcon.in.dev, p, STR_TERMINATE);
100 if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
101 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
106 status = smbsrv_tcon_backend(req, &con);
108 if (!NT_STATUS_IS_OK(status)) {
109 smbsrv_send_error(req, status);
113 /* construct reply */
114 smbsrv_setup_reply(req, 2, 0);
116 SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
117 SSVAL(req->out.vwv, VWV(1), con.tcon.out.tid);
118 SSVAL(req->out.hdr, HDR_TID, req->tcon->tid);
120 smbsrv_send_reply(req);
124 /****************************************************************************
125 Reply to a tcon and X.
126 ****************************************************************************/
127 void smbsrv_reply_tcon_and_X(struct smbsrv_request *req)
134 con.tconx.level = RAW_TCON_TCONX;
137 REQ_CHECK_WCT(req, 4);
139 con.tconx.in.flags = SVAL(req->in.vwv, VWV(2));
140 passlen = SVAL(req->in.vwv, VWV(3));
144 if (!req_pull_blob(req, p, passlen, &con.tconx.in.password)) {
145 smbsrv_send_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
150 p += req_pull_string(req, &con.tconx.in.path, p, -1, STR_TERMINATE);
151 p += req_pull_string(req, &con.tconx.in.device, p, -1, STR_ASCII);
153 if (!con.tconx.in.path || !con.tconx.in.device) {
154 smbsrv_send_error(req, NT_STATUS_BAD_DEVICE_TYPE);
159 status = smbsrv_tcon_backend(req, &con);
161 if (!NT_STATUS_IS_OK(status)) {
162 smbsrv_send_error(req, status);
166 /* construct reply - two variants */
167 if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
168 smbsrv_setup_reply(req, 2, 0);
170 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
171 SSVAL(req->out.vwv, VWV(1), 0);
173 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
175 smbsrv_setup_reply(req, 3, 0);
177 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
178 SSVAL(req->out.vwv, VWV(1), 0);
179 SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
181 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
182 req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
185 /* set the incoming and outgoing tid to the just created one */
186 SSVAL(req->in.hdr, HDR_TID, con.tconx.out.tid);
187 SSVAL(req->out.hdr,HDR_TID, con.tconx.out.tid);
189 smbsrv_chain_reply(req);
193 /****************************************************************************
194 Reply to an unknown request
195 ****************************************************************************/
196 void smbsrv_reply_unknown(struct smbsrv_request *req)
200 type = CVAL(req->in.hdr, HDR_COM);
202 DEBUG(0,("unknown command type %d (0x%X)\n", type, type));
204 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRunknownsmb));
208 /****************************************************************************
209 Reply to an ioctl (async reply)
210 ****************************************************************************/
211 static void reply_ioctl_send(struct smbsrv_request *req)
213 union smb_ioctl *io = req->async_states->private_data;
217 /* the +1 is for nicer alignment */
218 smbsrv_setup_reply(req, 8, io->ioctl.out.blob.length+1);
219 SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length);
220 SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length);
221 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1);
223 memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length);
225 smbsrv_send_reply(req);
228 /****************************************************************************
230 ****************************************************************************/
231 void smbsrv_reply_ioctl(struct smbsrv_request *req)
236 REQ_CHECK_WCT(req, 3);
237 REQ_TALLOC(io, union smb_ioctl);
239 io->ioctl.level = RAW_IOCTL_IOCTL;
240 io->ioctl.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
241 io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
243 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
244 req->async_states->send_fn = reply_ioctl_send;
245 req->async_states->private_data = io;
248 req->async_states->status = ntvfs_ioctl(req, io);
254 /****************************************************************************
256 ****************************************************************************/
257 void smbsrv_reply_chkpth(struct smbsrv_request *req)
259 union smb_chkpath *io;
261 REQ_TALLOC(io, union smb_chkpath);
263 req_pull_ascii4(req, &io->chkpath.in.path, req->in.data, STR_TERMINATE);
265 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
266 req->async_states->send_fn = reply_simple_send;
268 req->async_states->status = ntvfs_chkpath(req, io);
273 /****************************************************************************
274 Reply to a getatr (async reply)
275 ****************************************************************************/
276 static void reply_getatr_send(struct smbsrv_request *req)
278 union smb_fileinfo *st = req->async_states->private_data;
282 /* construct reply */
283 smbsrv_setup_reply(req, 10, 0);
285 SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib);
286 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
287 SIVAL(req->out.vwv, VWV(3), st->getattr.out.size);
289 REQ_VWV_RESERVED(5, 5);
291 smbsrv_send_reply(req);
295 /****************************************************************************
297 ****************************************************************************/
298 void smbsrv_reply_getatr(struct smbsrv_request *req)
300 union smb_fileinfo *st;
302 REQ_TALLOC(st, union smb_fileinfo);
304 st->getattr.level = RAW_FILEINFO_GETATTR;
307 req_pull_ascii4(req, &st->getattr.in.file.path, req->in.data, STR_TERMINATE);
308 if (!st->getattr.in.file.path) {
309 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
313 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
314 req->async_states->send_fn = reply_getatr_send;
315 req->async_states->private_data = st;
318 req->async_states->status = ntvfs_qpathinfo(req, st);
324 /****************************************************************************
326 ****************************************************************************/
327 void smbsrv_reply_setatr(struct smbsrv_request *req)
329 union smb_setfileinfo *st;
332 REQ_CHECK_WCT(req, 8);
333 REQ_TALLOC(st, union smb_setfileinfo);
335 st->setattr.level = RAW_SFILEINFO_SETATTR;
336 st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0));
337 st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
339 req_pull_ascii4(req, &st->setattr.in.file.path, req->in.data, STR_TERMINATE);
341 if (!st->setattr.in.file.path) {
342 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
346 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
347 req->async_states->send_fn = reply_simple_send;
350 req->async_states->status = ntvfs_setpathinfo(req, st);
356 /****************************************************************************
357 Reply to a dskattr (async reply)
358 ****************************************************************************/
359 static void reply_dskattr_send(struct smbsrv_request *req)
361 union smb_fsinfo *fs = req->async_states->private_data;
365 /* construct reply */
366 smbsrv_setup_reply(req, 5, 0);
368 SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total);
369 SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit);
370 SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size);
371 SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free);
373 REQ_VWV_RESERVED(4, 1);
375 smbsrv_send_reply(req);
379 /****************************************************************************
381 ****************************************************************************/
382 void smbsrv_reply_dskattr(struct smbsrv_request *req)
384 union smb_fsinfo *fs;
386 REQ_TALLOC(fs, union smb_fsinfo);
388 fs->dskattr.level = RAW_QFS_DSKATTR;
390 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
391 req->async_states->send_fn = reply_dskattr_send;
392 req->async_states->private_data = fs;
395 req->async_states->status = ntvfs_fsinfo(req, fs);
402 /****************************************************************************
403 Reply to an open (async reply)
404 ****************************************************************************/
405 static void reply_open_send(struct smbsrv_request *req)
407 union smb_open *oi = req->async_states->private_data;
411 /* construct reply */
412 smbsrv_setup_reply(req, 7, 0);
414 SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum);
415 SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
416 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
417 SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
418 SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
420 smbsrv_send_reply(req);
423 /****************************************************************************
425 ****************************************************************************/
426 void smbsrv_reply_open(struct smbsrv_request *req)
431 REQ_CHECK_WCT(req, 2);
432 REQ_TALLOC(oi, union smb_open);
434 oi->openold.level = RAW_OPEN_OPEN;
435 oi->openold.in.open_mode = SVAL(req->in.vwv, VWV(0));
436 oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
438 req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
440 if (!oi->openold.in.fname) {
441 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
445 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
446 req->async_states->send_fn = reply_open_send;
447 req->async_states->private_data = oi;
450 req->async_states->status = ntvfs_open(req, oi);
456 /****************************************************************************
457 Reply to an open and X (async reply)
458 ****************************************************************************/
459 static void reply_open_and_X_send(struct smbsrv_request *req)
461 union smb_open *oi = req->async_states->private_data;
465 /* build the reply */
466 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
467 smbsrv_setup_reply(req, 19, 0);
469 smbsrv_setup_reply(req, 15, 0);
472 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
473 SSVAL(req->out.vwv, VWV(1), 0);
474 SSVAL(req->out.vwv, VWV(2), oi->openx.out.file.fnum);
475 SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
476 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
477 SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
478 SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
479 SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
480 SSVAL(req->out.vwv, VWV(10),oi->openx.out.devstate);
481 SSVAL(req->out.vwv, VWV(11),oi->openx.out.action);
482 SIVAL(req->out.vwv, VWV(12),oi->openx.out.unique_fid);
483 SSVAL(req->out.vwv, VWV(14),0); /* reserved */
484 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
485 SIVAL(req->out.vwv, VWV(15),oi->openx.out.access_mask);
486 REQ_VWV_RESERVED(17, 2);
489 req->chained_fnum = oi->openx.out.file.fnum;
491 smbsrv_chain_reply(req);
495 /****************************************************************************
496 Reply to an open and X.
497 ****************************************************************************/
498 void smbsrv_reply_open_and_X(struct smbsrv_request *req)
502 /* parse the request */
503 REQ_CHECK_WCT(req, 15);
504 REQ_TALLOC(oi, union smb_open);
506 oi->openx.level = RAW_OPEN_OPENX;
507 oi->openx.in.flags = SVAL(req->in.vwv, VWV(2));
508 oi->openx.in.open_mode = SVAL(req->in.vwv, VWV(3));
509 oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
510 oi->openx.in.file_attrs = SVAL(req->in.vwv, VWV(5));
511 oi->openx.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
512 oi->openx.in.open_func = SVAL(req->in.vwv, VWV(8));
513 oi->openx.in.size = IVAL(req->in.vwv, VWV(9));
514 oi->openx.in.timeout = IVAL(req->in.vwv, VWV(11));
516 req_pull_ascii4(req, &oi->openx.in.fname, req->in.data, STR_TERMINATE);
518 if (!oi->openx.in.fname) {
519 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
523 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
524 req->async_states->send_fn = reply_open_and_X_send;
525 req->async_states->private_data = oi;
527 /* call the backend */
528 req->async_states->status = ntvfs_open(req, oi);
534 /****************************************************************************
535 Reply to a mknew or a create.
536 ****************************************************************************/
537 static void reply_mknew_send(struct smbsrv_request *req)
539 union smb_open *oi = req->async_states->private_data;
543 /* build the reply */
544 smbsrv_setup_reply(req, 1, 0);
546 SSVAL(req->out.vwv, VWV(0), oi->mknew.out.file.fnum);
548 smbsrv_send_reply(req);
552 /****************************************************************************
553 Reply to a mknew or a create.
554 ****************************************************************************/
555 void smbsrv_reply_mknew(struct smbsrv_request *req)
559 /* parse the request */
560 REQ_CHECK_WCT(req, 3);
561 REQ_TALLOC(oi, union smb_open);
563 if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
564 oi->mknew.level = RAW_OPEN_MKNEW;
566 oi->mknew.level = RAW_OPEN_CREATE;
568 oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0));
569 oi->mknew.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
571 req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
573 if (!oi->mknew.in.fname) {
574 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
578 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
579 req->async_states->send_fn = reply_mknew_send;
580 req->async_states->private_data = oi;
582 /* call the backend */
583 req->async_states->status = ntvfs_open(req, oi);
588 /****************************************************************************
589 Reply to a create temporary file (async reply)
590 ****************************************************************************/
591 static void reply_ctemp_send(struct smbsrv_request *req)
593 union smb_open *oi = req->async_states->private_data;
597 /* build the reply */
598 smbsrv_setup_reply(req, 1, 0);
600 SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.file.fnum);
602 /* the returned filename is relative to the directory */
603 req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
605 smbsrv_send_reply(req);
608 /****************************************************************************
609 Reply to a create temporary file.
610 ****************************************************************************/
611 void smbsrv_reply_ctemp(struct smbsrv_request *req)
615 /* parse the request */
616 REQ_CHECK_WCT(req, 3);
617 REQ_TALLOC(oi, union smb_open);
619 oi->ctemp.level = RAW_OPEN_CTEMP;
620 oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
621 oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
623 /* the filename is actually a directory name, the server provides a filename
625 req_pull_ascii4(req, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
627 if (!oi->ctemp.in.directory) {
628 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
632 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
633 req->async_states->send_fn = reply_ctemp_send;
634 req->async_states->private_data = oi;
636 /* call the backend */
637 req->async_states->status = ntvfs_open(req, oi);
643 /****************************************************************************
645 ****************************************************************************/
646 void smbsrv_reply_unlink(struct smbsrv_request *req)
648 union smb_unlink *unl;
650 /* parse the request */
651 REQ_CHECK_WCT(req, 1);
652 REQ_TALLOC(unl, union smb_unlink);
654 unl->unlink.in.attrib = SVAL(req->in.vwv, VWV(0));
656 req_pull_ascii4(req, &unl->unlink.in.pattern, req->in.data, STR_TERMINATE);
658 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
659 req->async_states->send_fn = reply_simple_send;
662 req->async_states->status = ntvfs_unlink(req, unl);
668 /****************************************************************************
669 Reply to a readbraw (core+ protocol).
670 this is a strange packet because it doesn't use a standard SMB header in the reply,
671 only the 4 byte NBT header
672 This command must be replied to synchronously
673 ****************************************************************************/
674 void smbsrv_reply_readbraw(struct smbsrv_request *req)
679 io.readbraw.level = RAW_READ_READBRAW;
681 /* there are two variants, one with 10 and one with 8 command words */
682 if (req->in.wct < 8) {
686 io.readbraw.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
687 io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
688 io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3));
689 io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4));
690 io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
692 /* the 64 bit variant */
693 if (req->in.wct == 10) {
694 uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
695 io.readbraw.in.offset |= (((off_t)offset_high) << 32);
698 /* before calling the backend we setup the raw buffer. This
699 * saves a copy later */
700 req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
701 req->out.buffer = talloc_size(req, req->out.size);
702 if (req->out.buffer == NULL) {
705 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
707 /* tell the backend where to put the data */
708 io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
710 /* call the backend */
711 status = ntvfs_read(req, &io);
713 if (!NT_STATUS_IS_OK(status)) {
717 req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
719 smbsrv_send_reply_nosign(req);
723 /* any failure in readbraw is equivalent to reading zero bytes */
725 req->out.buffer = talloc_size(req, req->out.size);
726 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
728 smbsrv_send_reply_nosign(req);
732 /****************************************************************************
733 Reply to a lockread (async reply)
734 ****************************************************************************/
735 static void reply_lockread_send(struct smbsrv_request *req)
737 union smb_read *io = req->async_states->private_data;
742 io->lockread.out.nread = MIN(io->lockread.out.nread,
743 req_max_data(req) - 3);
744 req_grow_data(req, 3 + io->lockread.out.nread);
746 /* construct reply */
747 SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
748 REQ_VWV_RESERVED(1, 4);
750 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
751 SSVAL(req->out.data, 1, io->lockread.out.nread);
753 smbsrv_send_reply(req);
757 /****************************************************************************
758 Reply to a lockread (core+ protocol).
759 note that the lock is a write lock, not a read lock!
760 ****************************************************************************/
761 void smbsrv_reply_lockread(struct smbsrv_request *req)
766 REQ_CHECK_WCT(req, 5);
767 REQ_TALLOC(io, union smb_read);
769 io->lockread.level = RAW_READ_LOCKREAD;
770 io->lockread.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
771 io->lockread.in.count = SVAL(req->in.vwv, VWV(1));
772 io->lockread.in.offset = IVAL(req->in.vwv, VWV(2));
773 io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
775 /* setup the reply packet assuming the maximum possible read */
776 smbsrv_setup_reply(req, 5, 3 + io->lockread.in.count);
778 /* tell the backend where to put the data */
779 io->lockread.out.data = req->out.data + 3;
781 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
782 req->async_states->send_fn = reply_lockread_send;
783 req->async_states->private_data = io;
786 req->async_states->status = ntvfs_read(req, io);
793 /****************************************************************************
794 Reply to a read (async reply)
795 ****************************************************************************/
796 static void reply_read_send(struct smbsrv_request *req)
798 union smb_read *io = req->async_states->private_data;
803 io->read.out.nread = MIN(io->read.out.nread,
804 req_max_data(req) - 3);
805 req_grow_data(req, 3 + io->read.out.nread);
807 /* construct reply */
808 SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
809 REQ_VWV_RESERVED(1, 4);
811 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
812 SSVAL(req->out.data, 1, io->read.out.nread);
814 smbsrv_send_reply(req);
817 /****************************************************************************
819 ****************************************************************************/
820 void smbsrv_reply_read(struct smbsrv_request *req)
825 REQ_CHECK_WCT(req, 5);
826 REQ_TALLOC(io, union smb_read);
828 io->read.level = RAW_READ_READ;
829 io->read.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
830 io->read.in.count = SVAL(req->in.vwv, VWV(1));
831 io->read.in.offset = IVAL(req->in.vwv, VWV(2));
832 io->read.in.remaining = SVAL(req->in.vwv, VWV(4));
834 /* setup the reply packet assuming the maximum possible read */
835 smbsrv_setup_reply(req, 5, 3 + io->read.in.count);
837 /* tell the backend where to put the data */
838 io->read.out.data = req->out.data + 3;
840 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
841 req->async_states->send_fn = reply_read_send;
842 req->async_states->private_data = io;
845 req->async_states->status = ntvfs_read(req, io);
852 /****************************************************************************
853 Reply to a read and X (async reply)
854 ****************************************************************************/
855 static void reply_read_and_X_send(struct smbsrv_request *req)
857 union smb_read *io = req->async_states->private_data;
861 /* readx reply packets can be over-sized */
862 req->control_flags |= REQ_CONTROL_LARGE;
863 if (io->readx.in.maxcnt != 0xFFFF &&
864 io->readx.in.mincnt != 0xFFFF) {
865 req_grow_data(req, 1 + io->readx.out.nread);
866 SCVAL(req->out.data, 0, 0); /* padding */
868 req_grow_data(req, io->readx.out.nread);
871 /* construct reply */
872 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
873 SSVAL(req->out.vwv, VWV(1), 0);
874 SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
875 SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
876 REQ_VWV_RESERVED(4, 1);
877 SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
878 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
879 REQ_VWV_RESERVED(7, 5);
881 smbsrv_chain_reply(req);
884 /****************************************************************************
885 Reply to a read and X.
886 ****************************************************************************/
887 void smbsrv_reply_read_and_X(struct smbsrv_request *req)
892 if (req->in.wct != 12) {
893 REQ_CHECK_WCT(req, 10);
896 REQ_TALLOC(io, union smb_read);
898 io->readx.level = RAW_READ_READX;
899 io->readx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
900 io->readx.in.offset = IVAL(req->in.vwv, VWV(3));
901 io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
902 io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
903 io->readx.in.remaining = SVAL(req->in.vwv, VWV(9));
904 if (req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) {
905 io->readx.in.read_for_execute = True;
907 io->readx.in.read_for_execute = False;
910 if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
911 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
912 if (high_part == 1) {
913 io->readx.in.maxcnt |= high_part << 16;
917 /* the 64 bit variant */
918 if (req->in.wct == 12) {
919 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
920 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
923 /* setup the reply packet assuming the maximum possible read */
924 smbsrv_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
926 /* tell the backend where to put the data. Notice the pad byte. */
927 if (io->readx.in.maxcnt != 0xFFFF &&
928 io->readx.in.mincnt != 0xFFFF) {
929 io->readx.out.data = req->out.data + 1;
931 io->readx.out.data = req->out.data;
934 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
935 req->async_states->send_fn = reply_read_and_X_send;
936 req->async_states->private_data = io;
939 req->async_states->status = ntvfs_read(req, io);
945 /****************************************************************************
946 Reply to a writebraw (core+ or LANMAN1.0 protocol).
947 ****************************************************************************/
948 void smbsrv_reply_writebraw(struct smbsrv_request *req)
950 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
954 /****************************************************************************
955 Reply to a writeunlock (async reply)
956 ****************************************************************************/
957 static void reply_writeunlock_send(struct smbsrv_request *req)
959 union smb_write *io = req->async_states->private_data;
963 /* construct reply */
964 smbsrv_setup_reply(req, 1, 0);
966 SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
968 smbsrv_send_reply(req);
971 /****************************************************************************
972 Reply to a writeunlock (core+).
973 ****************************************************************************/
974 void smbsrv_reply_writeunlock(struct smbsrv_request *req)
978 REQ_CHECK_WCT(req, 5);
979 REQ_TALLOC(io, union smb_write);
981 io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
982 io->writeunlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
983 io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
984 io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
985 io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
986 io->writeunlock.in.data = req->in.data + 3;
988 /* make sure they gave us the data they promised */
989 if (io->writeunlock.in.count+3 > req->in.data_size) {
990 smbsrv_send_error(req, NT_STATUS_FOOBAR);
994 /* make sure the data block is big enough */
995 if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
996 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1000 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1001 req->async_states->send_fn = reply_writeunlock_send;
1002 req->async_states->private_data = io;
1005 req->async_states->status = ntvfs_write(req, io);
1012 /****************************************************************************
1013 Reply to a write (async reply)
1014 ****************************************************************************/
1015 static void reply_write_send(struct smbsrv_request *req)
1017 union smb_write *io = req->async_states->private_data;
1021 /* construct reply */
1022 smbsrv_setup_reply(req, 1, 0);
1024 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1026 smbsrv_send_reply(req);
1029 /****************************************************************************
1031 ****************************************************************************/
1032 void smbsrv_reply_write(struct smbsrv_request *req)
1034 union smb_write *io;
1036 REQ_CHECK_WCT(req, 5);
1037 REQ_TALLOC(io, union smb_write);
1039 io->write.level = RAW_WRITE_WRITE;
1040 io->write.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1041 io->write.in.count = SVAL(req->in.vwv, VWV(1));
1042 io->write.in.offset = IVAL(req->in.vwv, VWV(2));
1043 io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
1044 io->write.in.data = req->in.data + 3;
1046 /* make sure they gave us the data they promised */
1047 if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
1048 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1052 /* make sure the data block is big enough */
1053 if (SVAL(req->in.data, 1) < io->write.in.count) {
1054 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1058 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1059 req->async_states->send_fn = reply_write_send;
1060 req->async_states->private_data = io;
1063 req->async_states->status = ntvfs_write(req, io);
1069 /****************************************************************************
1070 Reply to a write and X (async reply)
1071 ****************************************************************************/
1072 static void reply_write_and_X_send(struct smbsrv_request *req)
1074 union smb_write *io = req->async_states->private_data;
1078 /* construct reply */
1079 smbsrv_setup_reply(req, 6, 0);
1081 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1082 SSVAL(req->out.vwv, VWV(1), 0);
1083 SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
1084 SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
1085 SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
1086 REQ_VWV_RESERVED(5, 1);
1088 smbsrv_chain_reply(req);
1091 /****************************************************************************
1092 Reply to a write and X.
1093 ****************************************************************************/
1094 void smbsrv_reply_write_and_X(struct smbsrv_request *req)
1096 union smb_write *io;
1098 if (req->in.wct != 14) {
1099 REQ_CHECK_WCT(req, 12);
1102 REQ_TALLOC(io, union smb_write);
1104 io->writex.level = RAW_WRITE_WRITEX;
1105 io->writex.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
1106 io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
1107 io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
1108 io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1109 io->writex.in.count = SVAL(req->in.vwv, VWV(10));
1110 io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1112 if (req->in.wct == 14) {
1113 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1114 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1115 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1116 io->writex.in.count |= ((uint32_t)count_high) << 16;
1119 /* make sure the data is in bounds */
1120 if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1121 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1125 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1126 req->async_states->send_fn = reply_write_and_X_send;
1127 req->async_states->private_data = io;
1130 req->async_states->status = ntvfs_write(req, io);
1136 /****************************************************************************
1137 Reply to a lseek (async reply)
1138 ****************************************************************************/
1139 static void reply_lseek_send(struct smbsrv_request *req)
1141 union smb_seek *io = req->async_states->private_data;
1145 /* construct reply */
1146 smbsrv_setup_reply(req, 2, 0);
1148 SIVALS(req->out.vwv, VWV(0), io->lseek.out.offset);
1150 smbsrv_send_reply(req);
1153 /****************************************************************************
1155 ****************************************************************************/
1156 void smbsrv_reply_lseek(struct smbsrv_request *req)
1160 REQ_CHECK_WCT(req, 4);
1161 REQ_TALLOC(io, union smb_seek);
1163 io->lseek.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1164 io->lseek.in.mode = SVAL(req->in.vwv, VWV(1));
1165 io->lseek.in.offset = IVALS(req->in.vwv, VWV(2));
1167 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1168 req->async_states->send_fn = reply_lseek_send;
1169 req->async_states->private_data = io;
1172 req->async_states->status = ntvfs_seek(req, io);
1177 /****************************************************************************
1179 ****************************************************************************/
1180 void smbsrv_reply_flush(struct smbsrv_request *req)
1182 union smb_flush *io;
1185 REQ_CHECK_WCT(req, 1);
1186 REQ_TALLOC(io, union smb_flush);
1188 io->flush.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1190 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1191 req->async_states->send_fn = reply_simple_send;
1194 req->async_states->status = ntvfs_flush(req, io);
1200 /****************************************************************************
1201 Reply to a exit. This closes all files open by a smbpid
1202 ****************************************************************************/
1203 void smbsrv_reply_exit(struct smbsrv_request *req)
1206 struct smbsrv_tcon *tcon;
1207 REQ_CHECK_WCT(req, 0);
1209 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
1211 req->ctx = req->tcon->ntvfs;
1212 status = ntvfs_exit(req);
1215 if (!NT_STATUS_IS_OK(status)) {
1216 smbsrv_send_error(req, status);
1221 smbsrv_setup_reply(req, 0, 0);
1222 smbsrv_send_reply(req);
1226 /****************************************************************************
1229 Note that this has to deal with closing a directory opened by NT SMB's.
1230 ****************************************************************************/
1231 void smbsrv_reply_close(struct smbsrv_request *req)
1233 union smb_close *io;
1236 REQ_CHECK_WCT(req, 3);
1237 REQ_TALLOC(io, union smb_close);
1239 io->close.level = RAW_CLOSE_CLOSE;
1240 io->close.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1241 io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1243 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1244 req->async_states->send_fn = reply_simple_send;
1247 req->async_states->status = ntvfs_close(req, io);
1254 /****************************************************************************
1255 Reply to a writeclose (async reply)
1256 ****************************************************************************/
1257 static void reply_writeclose_send(struct smbsrv_request *req)
1259 union smb_write *io = req->async_states->private_data;
1263 /* construct reply */
1264 smbsrv_setup_reply(req, 1, 0);
1266 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1268 smbsrv_send_reply(req);
1271 /****************************************************************************
1272 Reply to a writeclose (Core+ protocol).
1273 ****************************************************************************/
1274 void smbsrv_reply_writeclose(struct smbsrv_request *req)
1276 union smb_write *io;
1278 /* this one is pretty weird - the wct can be 6 or 12 */
1279 if (req->in.wct != 12) {
1280 REQ_CHECK_WCT(req, 6);
1283 REQ_TALLOC(io, union smb_write);
1285 io->writeclose.level = RAW_WRITE_WRITECLOSE;
1286 io->writeclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1287 io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
1288 io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1289 io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1290 io->writeclose.in.data = req->in.data + 1;
1292 /* make sure they gave us the data they promised */
1293 if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1294 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1298 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1299 req->async_states->send_fn = reply_writeclose_send;
1300 req->async_states->private_data = io;
1303 req->async_states->status = ntvfs_write(req, io);
1308 /****************************************************************************
1310 ****************************************************************************/
1311 void smbsrv_reply_lock(struct smbsrv_request *req)
1313 union smb_lock *lck;
1316 REQ_CHECK_WCT(req, 5);
1317 REQ_TALLOC(lck, union smb_lock);
1319 lck->lock.level = RAW_LOCK_LOCK;
1320 lck->lock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1321 lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
1322 lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1324 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1325 req->async_states->send_fn = reply_simple_send;
1328 req->async_states->status = ntvfs_lock(req, lck);
1334 /****************************************************************************
1336 ****************************************************************************/
1337 void smbsrv_reply_unlock(struct smbsrv_request *req)
1339 union smb_lock *lck;
1342 REQ_CHECK_WCT(req, 5);
1343 REQ_TALLOC(lck, union smb_lock);
1345 lck->unlock.level = RAW_LOCK_UNLOCK;
1346 lck->unlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1347 lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
1348 lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1350 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1351 req->async_states->send_fn = reply_simple_send;
1354 req->async_states->status = ntvfs_lock(req, lck);
1360 /****************************************************************************
1362 ****************************************************************************/
1363 void smbsrv_reply_tdis(struct smbsrv_request *req)
1365 REQ_CHECK_WCT(req, 0);
1367 talloc_free(req->tcon);
1369 /* construct reply */
1370 smbsrv_setup_reply(req, 0, 0);
1372 smbsrv_send_reply(req);
1376 /****************************************************************************
1377 Reply to a echo. This is one of the few calls that is handled directly (the
1378 backends don't see it at all)
1379 ****************************************************************************/
1380 void smbsrv_reply_echo(struct smbsrv_request *req)
1385 REQ_CHECK_WCT(req, 0);
1387 count = SVAL(req->in.vwv, VWV(0));
1389 smbsrv_setup_reply(req, 1, req->in.data_size);
1391 memcpy(req->out.data, req->in.data, req->in.data_size);
1393 for (i=1; i <= count;i++) {
1394 struct smbsrv_request *this_req;
1397 this_req = smbsrv_setup_secondary_request(req);
1402 SSVAL(this_req->out.vwv, VWV(0), i);
1403 smbsrv_send_reply(this_req);
1409 /****************************************************************************
1410 Reply to a printopen (async reply)
1411 ****************************************************************************/
1412 static void reply_printopen_send(struct smbsrv_request *req)
1414 union smb_open *oi = req->async_states->private_data;
1418 /* construct reply */
1419 smbsrv_setup_reply(req, 1, 0);
1421 SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum);
1423 smbsrv_send_reply(req);
1426 /****************************************************************************
1427 Reply to a printopen.
1428 ****************************************************************************/
1429 void smbsrv_reply_printopen(struct smbsrv_request *req)
1434 REQ_CHECK_WCT(req, 2);
1435 REQ_TALLOC(oi, union smb_open);
1437 oi->splopen.level = RAW_OPEN_SPLOPEN;
1438 oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1439 oi->splopen.in.mode = SVAL(req->in.vwv, VWV(1));
1441 req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1443 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1444 req->async_states->send_fn = reply_printopen_send;
1445 req->async_states->private_data = oi;
1448 req->async_states->status = ntvfs_open(req, oi);
1453 /****************************************************************************
1454 Reply to a printclose.
1455 ****************************************************************************/
1456 void smbsrv_reply_printclose(struct smbsrv_request *req)
1458 union smb_close *io;
1461 REQ_CHECK_WCT(req, 3);
1462 REQ_TALLOC(io, union smb_close);
1464 io->splclose.level = RAW_CLOSE_SPLCLOSE;
1465 io->splclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1467 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1468 req->async_states->send_fn = reply_simple_send;
1471 req->async_states->status = ntvfs_close(req, io);
1476 /****************************************************************************
1477 Reply to a printqueue.
1478 ****************************************************************************/
1479 static void reply_printqueue_send(struct smbsrv_request *req)
1481 union smb_lpq *lpq = req->async_states->private_data;
1483 const uint_t el_size = 28;
1487 /* construct reply */
1488 smbsrv_setup_reply(req, 2, 0);
1490 /* truncate the returned list to fit in the negotiated buffer size */
1491 maxcount = (req_max_data(req) - 3) / el_size;
1492 if (maxcount < lpq->retq.out.count) {
1493 lpq->retq.out.count = maxcount;
1496 /* setup enough space in the reply */
1497 req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1499 /* and fill it in */
1500 SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1501 SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1503 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1504 SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1506 req->out.ptr = req->out.data + 3;
1508 for (i=0;i<lpq->retq.out.count;i++) {
1509 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1510 SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
1511 SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
1512 SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
1513 SCVAL(req->out.ptr, 11, 0); /* reserved */
1514 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1515 req->out.ptr += el_size;
1518 smbsrv_send_reply(req);
1521 /****************************************************************************
1522 Reply to a printqueue.
1523 ****************************************************************************/
1524 void smbsrv_reply_printqueue(struct smbsrv_request *req)
1529 REQ_CHECK_WCT(req, 2);
1530 REQ_TALLOC(lpq, union smb_lpq);
1532 lpq->retq.level = RAW_LPQ_RETQ;
1533 lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
1534 lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
1536 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1537 req->async_states->send_fn = reply_printqueue_send;
1538 req->async_states->private_data = lpq;
1541 req->async_states->status = ntvfs_lpq(req, lpq);
1547 /****************************************************************************
1548 Reply to a printwrite.
1549 ****************************************************************************/
1550 void smbsrv_reply_printwrite(struct smbsrv_request *req)
1552 union smb_write *io;
1555 REQ_CHECK_WCT(req, 1);
1556 REQ_TALLOC(io, union smb_write);
1558 io->splwrite.level = RAW_WRITE_SPLWRITE;
1560 if (req->in.data_size < 3) {
1561 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1565 io->splwrite.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1566 io->splwrite.in.count = SVAL(req->in.data, 1);
1567 io->splwrite.in.data = req->in.data + 3;
1569 /* make sure they gave us the data they promised */
1570 if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1571 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1575 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1576 req->async_states->send_fn = reply_simple_send;
1579 req->async_states->status = ntvfs_write(req, io);
1585 /****************************************************************************
1587 ****************************************************************************/
1588 void smbsrv_reply_mkdir(struct smbsrv_request *req)
1590 union smb_mkdir *io;
1592 /* parse the request */
1593 REQ_CHECK_WCT(req, 0);
1594 REQ_TALLOC(io, union smb_mkdir);
1596 io->generic.level = RAW_MKDIR_MKDIR;
1597 req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1599 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1600 req->async_states->send_fn = reply_simple_send;
1603 req->async_states->status = ntvfs_mkdir(req, io);
1609 /****************************************************************************
1611 ****************************************************************************/
1612 void smbsrv_reply_rmdir(struct smbsrv_request *req)
1614 struct smb_rmdir *io;
1616 /* parse the request */
1617 REQ_CHECK_WCT(req, 0);
1618 REQ_TALLOC(io, struct smb_rmdir);
1620 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1622 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1623 req->async_states->send_fn = reply_simple_send;
1626 req->async_states->status = ntvfs_rmdir(req, io);
1632 /****************************************************************************
1634 ****************************************************************************/
1635 void smbsrv_reply_mv(struct smbsrv_request *req)
1637 union smb_rename *io;
1640 /* parse the request */
1641 REQ_CHECK_WCT(req, 1);
1642 REQ_TALLOC(io, union smb_rename);
1644 io->generic.level = RAW_RENAME_RENAME;
1645 io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1648 p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1649 p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1651 if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1652 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1656 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1657 req->async_states->send_fn = reply_simple_send;
1660 req->async_states->status = ntvfs_rename(req, io);
1666 /****************************************************************************
1667 Reply to an NT rename.
1668 ****************************************************************************/
1669 void smbsrv_reply_ntrename(struct smbsrv_request *req)
1671 union smb_rename *io;
1674 /* parse the request */
1675 REQ_CHECK_WCT(req, 4);
1676 REQ_TALLOC(io, union smb_rename);
1678 io->generic.level = RAW_RENAME_NTRENAME;
1679 io->ntrename.in.attrib = SVAL(req->in.vwv, VWV(0));
1680 io->ntrename.in.flags = SVAL(req->in.vwv, VWV(1));
1681 io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1684 p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1685 p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1687 if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1688 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1692 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1693 req->async_states->send_fn = reply_simple_send;
1696 req->async_states->status = ntvfs_rename(req, io);
1701 /****************************************************************************
1702 Reply to a file copy (async reply)
1703 ****************************************************************************/
1704 static void reply_copy_send(struct smbsrv_request *req)
1706 struct smb_copy *cp = req->async_states->private_data;
1710 /* build the reply */
1711 smbsrv_setup_reply(req, 1, 0);
1713 SSVAL(req->out.vwv, VWV(0), cp->out.count);
1715 smbsrv_send_reply(req);
1718 /****************************************************************************
1719 Reply to a file copy.
1720 ****************************************************************************/
1721 void smbsrv_reply_copy(struct smbsrv_request *req)
1723 struct smb_copy *cp;
1727 REQ_CHECK_WCT(req, 3);
1728 REQ_TALLOC(cp, struct smb_copy);
1730 cp->in.tid2 = SVAL(req->in.vwv, VWV(0));
1731 cp->in.ofun = SVAL(req->in.vwv, VWV(1));
1732 cp->in.flags = SVAL(req->in.vwv, VWV(2));
1735 p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1736 p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1738 if (!cp->in.path1 || !cp->in.path2) {
1739 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1743 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1744 req->async_states->send_fn = reply_copy_send;
1745 req->async_states->private_data = cp;
1748 req->async_states->status = ntvfs_copy(req, cp);
1753 /****************************************************************************
1754 Reply to a lockingX request (async send)
1755 ****************************************************************************/
1756 static void reply_lockingX_send(struct smbsrv_request *req)
1758 union smb_lock *lck = req->async_states->private_data;
1762 /* if it was an oplock break ack then we only send a reply if
1763 there was an error */
1764 if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1769 /* construct reply */
1770 smbsrv_setup_reply(req, 2, 0);
1772 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1773 SSVAL(req->out.vwv, VWV(1), 0);
1775 smbsrv_chain_reply(req);
1779 /****************************************************************************
1780 Reply to a lockingX request.
1781 ****************************************************************************/
1782 void smbsrv_reply_lockingX(struct smbsrv_request *req)
1784 union smb_lock *lck;
1785 uint_t total_locks, i;
1790 REQ_CHECK_WCT(req, 8);
1791 REQ_TALLOC(lck, union smb_lock);
1793 lck->lockx.level = RAW_LOCK_LOCKX;
1794 lck->lockx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
1795 lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
1796 lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
1797 lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1798 lck->lockx.in.lock_cnt = SVAL(req->in.vwv, VWV(7));
1800 total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1802 /* there are two variants, one with 64 bit offsets and counts */
1803 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1809 /* make sure we got the promised data */
1810 if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1811 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1815 /* allocate the locks array */
1817 lck->lockx.in.locks = talloc_array(req, struct smb_lock_entry,
1819 if (lck->lockx.in.locks == NULL) {
1820 smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1827 /* construct the locks array */
1828 for (i=0;i<total_locks;i++) {
1829 uint32_t ofs_high=0, count_high=0;
1831 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1833 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1834 ofs_high = IVAL(p, 4);
1835 lck->lockx.in.locks[i].offset = IVAL(p, 8);
1836 count_high = IVAL(p, 12);
1837 lck->lockx.in.locks[i].count = IVAL(p, 16);
1839 lck->lockx.in.locks[i].offset = IVAL(p, 2);
1840 lck->lockx.in.locks[i].count = IVAL(p, 6);
1842 if (ofs_high != 0 || count_high != 0) {
1843 lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32;
1844 lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1849 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1850 req->async_states->send_fn = reply_lockingX_send;
1851 req->async_states->private_data = lck;
1854 req->async_states->status = ntvfs_lock(req, lck);
1859 /****************************************************************************
1860 Reply to a SMBreadbmpx (read block multiplex) request.
1861 ****************************************************************************/
1862 void smbsrv_reply_readbmpx(struct smbsrv_request *req)
1864 /* tell the client to not use a multiplexed read - its too broken to use */
1865 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1869 /****************************************************************************
1870 Reply to a SMBsetattrE.
1871 ****************************************************************************/
1872 void smbsrv_reply_setattrE(struct smbsrv_request *req)
1874 union smb_setfileinfo *info;
1877 REQ_CHECK_WCT(req, 7);
1878 REQ_TALLOC(info, union smb_setfileinfo);
1880 info->setattre.level = RAW_SFILEINFO_SETATTRE;
1881 info->setattre.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1882 info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1883 info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1884 info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1886 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1887 req->async_states->send_fn = reply_simple_send;
1890 req->async_states->status = ntvfs_setfileinfo(req, info);
1896 /****************************************************************************
1897 Reply to a SMBwritebmpx (write block multiplex primary) request.
1898 ****************************************************************************/
1899 void smbsrv_reply_writebmpx(struct smbsrv_request *req)
1901 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1905 /****************************************************************************
1906 Reply to a SMBwritebs (write block multiplex secondary) request.
1907 ****************************************************************************/
1908 void smbsrv_reply_writebs(struct smbsrv_request *req)
1910 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1915 /****************************************************************************
1916 Reply to a SMBgetattrE (async reply)
1917 ****************************************************************************/
1918 static void reply_getattrE_send(struct smbsrv_request *req)
1920 union smb_fileinfo *info = req->async_states->private_data;
1925 smbsrv_setup_reply(req, 11, 0);
1927 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1928 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1929 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1930 SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
1931 SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
1932 SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
1934 smbsrv_send_reply(req);
1937 /****************************************************************************
1938 Reply to a SMBgetattrE.
1939 ****************************************************************************/
1940 void smbsrv_reply_getattrE(struct smbsrv_request *req)
1942 union smb_fileinfo *info;
1945 REQ_CHECK_WCT(req, 1);
1946 REQ_TALLOC(info, union smb_fileinfo);
1948 info->getattr.level = RAW_FILEINFO_GETATTRE;
1949 info->getattr.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1951 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1952 req->async_states->send_fn = reply_getattrE_send;
1953 req->async_states->private_data = info;
1956 req->async_states->status = ntvfs_qfileinfo(req, info);
1962 /****************************************************************************
1963 reply to an old style session setup command
1964 ****************************************************************************/
1965 static void reply_sesssetup_old(struct smbsrv_request *req)
1968 union smb_sesssetup sess;
1972 sess.old.level = RAW_SESSSETUP_OLD;
1975 sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1976 sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1977 sess.old.in.vc_num = SVAL(req->in.vwv, VWV(4));
1978 sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1979 passlen = SVAL(req->in.vwv, VWV(7));
1981 /* check the request isn't malformed */
1982 if (req_data_oob(req, req->in.data, passlen)) {
1983 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1988 if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1989 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1994 p += req_pull_string(req, &sess.old.in.user, p, -1, STR_TERMINATE);
1995 p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1996 p += req_pull_string(req, &sess.old.in.os, p, -1, STR_TERMINATE);
1997 p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
1999 /* call the generic handler */
2000 status = smbsrv_sesssetup_backend(req, &sess);
2002 if (!NT_STATUS_IS_OK(status)) {
2003 smbsrv_send_error(req, status);
2007 /* construct reply */
2008 smbsrv_setup_reply(req, 3, 0);
2010 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2011 SSVAL(req->out.vwv, VWV(1), 0);
2012 SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
2014 SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
2016 smbsrv_chain_reply(req);
2020 /****************************************************************************
2021 reply to an NT1 style session setup command
2022 ****************************************************************************/
2023 static void reply_sesssetup_nt1(struct smbsrv_request *req)
2026 union smb_sesssetup sess;
2028 uint16_t passlen1, passlen2;
2030 sess.nt1.level = RAW_SESSSETUP_NT1;
2033 sess.nt1.in.bufsize = SVAL(req->in.vwv, VWV(2));
2034 sess.nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2035 sess.nt1.in.vc_num = SVAL(req->in.vwv, VWV(4));
2036 sess.nt1.in.sesskey = IVAL(req->in.vwv, VWV(5));
2037 passlen1 = SVAL(req->in.vwv, VWV(7));
2038 passlen2 = SVAL(req->in.vwv, VWV(8));
2039 sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
2041 /* check the request isn't malformed */
2042 if (req_data_oob(req, req->in.data, passlen1) ||
2043 req_data_oob(req, req->in.data + passlen1, passlen2)) {
2044 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2049 if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
2050 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2054 if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
2055 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2060 p += req_pull_string(req, &sess.nt1.in.user, p, -1, STR_TERMINATE);
2061 p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
2062 p += req_pull_string(req, &sess.nt1.in.os, p, -1, STR_TERMINATE);
2063 p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
2065 /* call the generic handler */
2066 status = smbsrv_sesssetup_backend(req, &sess);
2068 if (!NT_STATUS_IS_OK(status)) {
2069 smbsrv_send_error(req, status);
2073 /* construct reply */
2074 smbsrv_setup_reply(req, 3, 0);
2076 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2077 SSVAL(req->out.vwv, VWV(1), 0);
2078 SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
2080 SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
2082 req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
2083 req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
2084 req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
2086 smbsrv_chain_reply(req);
2090 /****************************************************************************
2091 reply to an SPNEGO style session setup command
2092 ****************************************************************************/
2093 static void reply_sesssetup_spnego(struct smbsrv_request *req)
2096 union smb_sesssetup sess;
2100 sess.spnego.level = RAW_SESSSETUP_SPNEGO;
2103 sess.spnego.in.bufsize = SVAL(req->in.vwv, VWV(2));
2104 sess.spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2105 sess.spnego.in.vc_num = SVAL(req->in.vwv, VWV(4));
2106 sess.spnego.in.sesskey = IVAL(req->in.vwv, VWV(5));
2107 blob_len = SVAL(req->in.vwv, VWV(7));
2108 sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
2111 if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
2112 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2117 p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE);
2118 p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE);
2119 p += req_pull_string(req, &sess.spnego.in.workgroup, p, -1, STR_TERMINATE);
2121 /* call the generic handler */
2122 status = smbsrv_sesssetup_backend(req, &sess);
2124 if (!NT_STATUS_IS_OK(status) &&
2125 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2126 smbsrv_send_error(req, status);
2130 /* construct reply */
2131 smbsrv_setup_reply(req, 4, sess.spnego.out.secblob.length);
2133 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2134 smbsrv_setup_error(req, status);
2137 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2138 SSVAL(req->out.vwv, VWV(1), 0);
2139 SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
2140 SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
2142 SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
2144 memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
2145 req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
2146 req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
2147 req_push_str(req, NULL, sess.spnego.out.workgroup, -1, STR_TERMINATE);
2149 smbsrv_chain_reply(req);
2153 /****************************************************************************
2154 reply to a session setup command
2155 ****************************************************************************/
2156 void smbsrv_reply_sesssetup(struct smbsrv_request *req)
2158 switch (req->in.wct) {
2160 /* a pre-NT1 call */
2161 reply_sesssetup_old(req);
2165 reply_sesssetup_nt1(req);
2169 reply_sesssetup_spnego(req);
2173 /* unsupported variant */
2174 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2177 /****************************************************************************
2178 Reply to a SMBulogoffX.
2179 ****************************************************************************/
2180 void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
2182 struct smbsrv_tcon *tcon;
2185 /* in user level security we are supposed to close any files
2186 open by this user on all open tree connects */
2187 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
2189 req->ctx = tcon->ntvfs;
2190 status = ntvfs_logoff(req);
2193 if (!NT_STATUS_IS_OK(status)) {
2194 smbsrv_send_error(req, status);
2199 talloc_free(req->session);
2200 req->session = NULL; /* it is now invalid, don't use on
2201 any chained packets */
2203 smbsrv_setup_reply(req, 2, 0);
2205 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2206 SSVAL(req->out.vwv, VWV(1), 0);
2208 smbsrv_chain_reply(req);
2212 /****************************************************************************
2213 Reply to an SMBfindclose request
2214 ****************************************************************************/
2215 void smbsrv_reply_findclose(struct smbsrv_request *req)
2218 union smb_search_close io;
2220 io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2223 REQ_CHECK_WCT(req, 1);
2225 io.findclose.in.handle = SVAL(req->in.vwv, VWV(0));
2228 status = ntvfs_search_close(req, &io);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 smbsrv_send_error(req, status);
2235 /* construct reply */
2236 smbsrv_setup_reply(req, 0, 0);
2238 smbsrv_send_reply(req);
2241 /****************************************************************************
2242 Reply to an SMBfindnclose request
2243 ****************************************************************************/
2244 void smbsrv_reply_findnclose(struct smbsrv_request *req)
2246 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2250 /****************************************************************************
2251 Reply to an SMBntcreateX request (async send)
2252 ****************************************************************************/
2253 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
2255 union smb_open *io = req->async_states->private_data;
2259 /* construct reply */
2260 smbsrv_setup_reply(req, 34, 0);
2262 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2263 SSVAL(req->out.vwv, VWV(1), 0);
2264 SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2266 /* the rest of the parameters are not aligned! */
2267 SSVAL(req->out.vwv, 5, io->ntcreatex.out.file.fnum);
2268 SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
2269 push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2270 push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2271 push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2272 push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2273 SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
2274 SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
2275 SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
2276 SSVAL(req->out.vwv, 63, io->ntcreatex.out.file_type);
2277 SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
2278 SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
2280 req->chained_fnum = io->ntcreatex.out.file.fnum;
2282 smbsrv_chain_reply(req);
2285 /****************************************************************************
2286 Reply to an SMBntcreateX request
2287 ****************************************************************************/
2288 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request *req)
2293 /* parse the request */
2294 REQ_CHECK_WCT(req, 24);
2295 REQ_TALLOC(io, union smb_open);
2297 io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2299 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2300 fname_len = SVAL(req->in.vwv, 5);
2301 io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
2302 io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
2303 io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
2304 io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
2305 io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
2306 io->ntcreatex.in.share_access = IVAL(req->in.vwv, 31);
2307 io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2308 io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
2309 io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
2310 io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
2311 io->ntcreatex.in.ea_list = NULL;
2312 io->ntcreatex.in.sec_desc = NULL;
2314 /* we need a neater way to handle this alignment */
2315 if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
2316 ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2320 req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2321 if (!io->ntcreatex.in.fname) {
2322 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2326 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
2327 req->async_states->send_fn = reply_ntcreate_and_X_send;
2328 req->async_states->private_data = io;
2330 /* call the backend */
2331 req->async_states->status = ntvfs_open(req, io);
2337 /****************************************************************************
2338 Reply to an SMBntcancel request
2339 ****************************************************************************/
2340 void smbsrv_reply_ntcancel(struct smbsrv_request *req)
2342 /* NOTE: this request does not generate a reply */
2348 parse the called/calling names from session request
2350 static NTSTATUS parse_session_request(struct smbsrv_request *req)
2355 blob.data = req->in.buffer + 4;
2356 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2357 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2359 req->smb_conn->negotiate.called_name = talloc(req->smb_conn, struct nbt_name);
2360 req->smb_conn->negotiate.calling_name = talloc(req->smb_conn, struct nbt_name);
2361 if (req->smb_conn->negotiate.called_name == NULL ||
2362 req->smb_conn->negotiate.calling_name == NULL) {
2363 return NT_STATUS_NO_MEMORY;
2366 status = nbt_name_from_blob(req->smb_conn, &blob,
2367 req->smb_conn->negotiate.called_name);
2368 NT_STATUS_NOT_OK_RETURN(status);
2370 blob.data += blob.length;
2371 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2372 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2374 status = nbt_name_from_blob(req->smb_conn, &blob,
2375 req->smb_conn->negotiate.calling_name);
2376 NT_STATUS_NOT_OK_RETURN(status);
2378 req->smb_conn->negotiate.done_nbt_session = True;
2380 return NT_STATUS_OK;
2385 /****************************************************************************
2386 Reply to a special message - a SMB packet with non zero NBT message type
2387 ****************************************************************************/
2388 void smbsrv_reply_special(struct smbsrv_request *req)
2391 uint8_t *buf = talloc_zero_array(req, uint8_t, 4);
2393 msg_type = CVAL(req->in.buffer,0);
2398 case 0x81: /* session request */
2399 if (req->smb_conn->negotiate.done_nbt_session) {
2400 DEBUG(0,("Warning: ignoring secondary session request\n"));
2407 /* we don't check the status - samba always accepts session
2408 requests for any name */
2409 parse_session_request(req);
2411 req->out.buffer = buf;
2413 smbsrv_send_reply_nosign(req);
2416 case 0x89: /* session keepalive request
2417 (some old clients produce this?) */
2418 SCVAL(buf, 0, SMBkeepalive);
2420 req->out.buffer = buf;
2422 smbsrv_send_reply_nosign(req);
2426 /* session keepalive - swallow it */
2431 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));