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"
30 /* useful way of catching wct errors with file and line number */
31 #define REQ_CHECK_WCT(req, wcount) do { \
32 if ((req)->in.wct != (wcount)) { \
33 DEBUG(1,("Unexpected WCT %d at %s(%d) - expected %d\n", \
34 (req)->in.wct, __FILE__, __LINE__, wcount)); \
35 req_reply_dos_error(req, ERRSRV, ERRerror); \
39 /* check req->async_states->status and if not OK then send an error reply */
40 #define CHECK_ASYNC_STATUS do { \
41 if (!NT_STATUS_IS_OK(req->async_states->status)) { \
42 req_reply_error(req, req->async_states->status); \
46 /* useful wrapper for talloc with NO_MEMORY reply */
47 #define REQ_TALLOC(ptr, size) do { \
48 ptr = talloc(req, size); \
50 req_reply_error(req, NT_STATUS_NO_MEMORY); \
55 check if the backend wants to handle the request asynchronously.
56 if it wants it handled synchronously then call the send function
59 #define REQ_ASYNC_TAIL do { \
60 if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
61 req->async_states->send_fn(req); \
64 /* zero out some reserved fields in a reply */
65 #define REQ_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)
67 /****************************************************************************
68 Reply to a simple request (async send)
69 ****************************************************************************/
70 static void reply_simple_send(struct smbsrv_request *req)
74 req_setup_reply(req, 0, 0);
79 /****************************************************************************
81 ****************************************************************************/
82 void reply_tcon(struct smbsrv_request *req)
89 REQ_CHECK_WCT(req, 0);
91 con.tcon.level = RAW_TCON_TCON;
94 p += req_pull_ascii4(req, &con.tcon.in.service, p, STR_TERMINATE);
95 p += req_pull_ascii4(req, &con.tcon.in.password, p, STR_TERMINATE);
96 p += req_pull_ascii4(req, &con.tcon.in.dev, p, STR_TERMINATE);
98 if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
99 req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
104 status = tcon_backend(req, &con);
106 if (!NT_STATUS_IS_OK(status)) {
107 req_reply_error(req, status);
111 /* construct reply */
112 req_setup_reply(req, 2, 0);
114 SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
115 SSVAL(req->out.vwv, VWV(1), con.tcon.out.cnum);
116 SSVAL(req->out.hdr, HDR_TID, req->tcon->cnum);
122 /****************************************************************************
123 Reply to a tcon and X.
124 ****************************************************************************/
125 void reply_tcon_and_X(struct smbsrv_request *req)
132 con.tconx.level = RAW_TCON_TCONX;
135 REQ_CHECK_WCT(req, 4);
137 con.tconx.in.flags = SVAL(req->in.vwv, VWV(2));
138 passlen = SVAL(req->in.vwv, VWV(3));
142 if (!req_pull_blob(req, p, passlen, &con.tconx.in.password)) {
143 req_reply_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
148 p += req_pull_string(req, &con.tconx.in.path, p, -1, STR_TERMINATE);
149 p += req_pull_string(req, &con.tconx.in.device, p, -1, STR_ASCII);
151 if (!con.tconx.in.path || !con.tconx.in.device) {
152 req_reply_error(req, NT_STATUS_BAD_DEVICE_TYPE);
157 status = tcon_backend(req, &con);
159 if (!NT_STATUS_IS_OK(status)) {
160 req_reply_error(req, status);
164 /* construct reply - two variants */
165 if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
166 req_setup_reply(req, 2, 0);
168 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
169 SSVAL(req->out.vwv, VWV(1), 0);
171 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
173 req_setup_reply(req, 3, 0);
175 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
176 SSVAL(req->out.vwv, VWV(1), 0);
177 SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
179 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
180 req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
183 /* set the incoming and outgoing tid to the just created one */
184 SSVAL(req->in.hdr, HDR_TID, con.tconx.out.cnum);
185 SSVAL(req->out.hdr,HDR_TID, con.tconx.out.cnum);
191 /****************************************************************************
192 Reply to an unknown request
193 ****************************************************************************/
194 void reply_unknown(struct smbsrv_request *req)
198 type = CVAL(req->in.hdr, HDR_COM);
200 DEBUG(0,("unknown command type %d (0x%X)\n", type, type));
202 req_reply_dos_error(req, ERRSRV, ERRunknownsmb);
206 /****************************************************************************
207 Reply to an ioctl (async reply)
208 ****************************************************************************/
209 static void reply_ioctl_send(struct smbsrv_request *req)
211 union smb_ioctl *io = req->async_states->private_data;
215 /* the +1 is for nicer alignment */
216 req_setup_reply(req, 8, io->ioctl.out.blob.length+1);
217 SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length);
218 SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length);
219 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1);
221 memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length);
226 /****************************************************************************
228 ****************************************************************************/
229 void reply_ioctl(struct smbsrv_request *req)
234 REQ_CHECK_WCT(req, 3);
235 REQ_TALLOC(io, sizeof(*io));
237 io->ioctl.level = RAW_IOCTL_IOCTL;
238 io->ioctl.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
239 io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
241 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
242 req->async_states->send_fn = reply_ioctl_send;
243 req->async_states->private_data = io;
246 req->async_states->status = ntvfs_ioctl(req, io);
252 /****************************************************************************
254 ****************************************************************************/
255 void reply_chkpth(struct smbsrv_request *req)
257 struct smb_chkpath *io;
259 REQ_TALLOC(io, sizeof(*io));
261 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
263 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
264 req->async_states->send_fn = reply_simple_send;
266 req->async_states->status = ntvfs_chkpath(req, io);
271 /****************************************************************************
272 Reply to a getatr (async reply)
273 ****************************************************************************/
274 static void reply_getatr_send(struct smbsrv_request *req)
276 union smb_fileinfo *st = req->async_states->private_data;
280 /* construct reply */
281 req_setup_reply(req, 10, 0);
283 SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib);
284 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
285 SIVAL(req->out.vwv, VWV(3), st->getattr.out.size);
287 REQ_VWV_RESERVED(5, 5);
293 /****************************************************************************
295 ****************************************************************************/
296 void reply_getatr(struct smbsrv_request *req)
298 union smb_fileinfo *st;
300 REQ_TALLOC(st, sizeof(*st));
302 st->getattr.level = RAW_FILEINFO_GETATTR;
305 req_pull_ascii4(req, &st->getattr.in.fname, req->in.data, STR_TERMINATE);
306 if (!st->getattr.in.fname) {
307 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
311 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
312 req->async_states->send_fn = reply_getatr_send;
313 req->async_states->private_data = st;
316 req->async_states->status = ntvfs_qpathinfo(req, st);
322 /****************************************************************************
324 ****************************************************************************/
325 void reply_setatr(struct smbsrv_request *req)
327 union smb_setfileinfo *st;
330 REQ_CHECK_WCT(req, 8);
331 REQ_TALLOC(st, sizeof(*st));
333 st->setattr.level = RAW_SFILEINFO_SETATTR;
334 st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0));
335 st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
337 req_pull_ascii4(req, &st->setattr.file.fname, req->in.data, STR_TERMINATE);
339 if (!st->setattr.file.fname) {
340 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
344 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
345 req->async_states->send_fn = reply_simple_send;
348 req->async_states->status = ntvfs_setpathinfo(req, st);
354 /****************************************************************************
355 Reply to a dskattr (async reply)
356 ****************************************************************************/
357 static void reply_dskattr_send(struct smbsrv_request *req)
359 union smb_fsinfo *fs = req->async_states->private_data;
363 /* construct reply */
364 req_setup_reply(req, 5, 0);
366 SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total);
367 SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit);
368 SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size);
369 SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free);
371 REQ_VWV_RESERVED(4, 1);
377 /****************************************************************************
379 ****************************************************************************/
380 void reply_dskattr(struct smbsrv_request *req)
382 union smb_fsinfo *fs;
384 REQ_TALLOC(fs, sizeof(*fs));
386 fs->dskattr.level = RAW_QFS_DSKATTR;
388 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
389 req->async_states->send_fn = reply_dskattr_send;
390 req->async_states->private_data = fs;
393 req->async_states->status = ntvfs_fsinfo(req, fs);
400 /****************************************************************************
401 Reply to an open (async reply)
402 ****************************************************************************/
403 static void reply_open_send(struct smbsrv_request *req)
405 union smb_open *oi = req->async_states->private_data;
409 /* construct reply */
410 req_setup_reply(req, 7, 0);
412 SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
413 SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
414 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
415 SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
416 SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
421 /****************************************************************************
423 ****************************************************************************/
424 void reply_open(struct smbsrv_request *req)
429 REQ_CHECK_WCT(req, 2);
430 REQ_TALLOC(oi, sizeof(*oi));
432 oi->openold.level = RAW_OPEN_OPEN;
433 oi->openold.in.flags = SVAL(req->in.vwv, VWV(0));
434 oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
436 req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
438 if (!oi->openold.in.fname) {
439 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
443 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
444 req->async_states->send_fn = reply_open_send;
445 req->async_states->private_data = oi;
448 req->async_states->status = ntvfs_openfile(req, oi);
454 /****************************************************************************
455 Reply to an open and X (async reply)
456 ****************************************************************************/
457 static void reply_open_and_X_send(struct smbsrv_request *req)
459 union smb_open *oi = req->async_states->private_data;
463 /* build the reply */
464 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
465 req_setup_reply(req, 19, 0);
467 req_setup_reply(req, 15, 0);
470 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
471 SSVAL(req->out.vwv, VWV(1), 0);
472 SSVAL(req->out.vwv, VWV(2), oi->openx.out.fnum);
473 SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
474 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
475 SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
476 SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
477 SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
478 SSVAL(req->out.vwv, VWV(10),oi->openx.out.devstate);
479 SSVAL(req->out.vwv, VWV(11),oi->openx.out.action);
480 SIVAL(req->out.vwv, VWV(12),oi->openx.out.unique_fid);
481 SSVAL(req->out.vwv, VWV(14),0); /* reserved */
482 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
483 SIVAL(req->out.vwv, VWV(15),oi->openx.out.access_mask);
484 REQ_VWV_RESERVED(17, 2);
491 /****************************************************************************
492 Reply to an open and X.
493 ****************************************************************************/
494 void reply_open_and_X(struct smbsrv_request *req)
498 /* parse the request */
499 REQ_CHECK_WCT(req, 15);
500 REQ_TALLOC(oi, sizeof(*oi));
502 oi->openx.level = RAW_OPEN_OPENX;
503 oi->openx.in.flags = SVAL(req->in.vwv, VWV(2));
504 oi->openx.in.open_mode = SVAL(req->in.vwv, VWV(3));
505 oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
506 oi->openx.in.file_attrs = SVAL(req->in.vwv, VWV(5));
507 oi->openx.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
508 oi->openx.in.open_func = SVAL(req->in.vwv, VWV(8));
509 oi->openx.in.size = IVAL(req->in.vwv, VWV(9));
510 oi->openx.in.timeout = IVAL(req->in.vwv, VWV(11));
512 req_pull_ascii4(req, &oi->openx.in.fname, req->in.data, STR_TERMINATE);
514 if (!oi->openx.in.fname) {
515 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
519 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
520 req->async_states->send_fn = reply_open_and_X_send;
521 req->async_states->private_data = oi;
523 /* call the backend */
524 req->async_states->status = ntvfs_openfile(req, oi);
530 /****************************************************************************
531 Reply to a mknew or a create.
532 ****************************************************************************/
533 static void reply_mknew_send(struct smbsrv_request *req)
535 union smb_open *oi = req->async_states->private_data;
539 /* build the reply */
540 req_setup_reply(req, 1, 0);
542 SSVAL(req->out.vwv, VWV(0), oi->mknew.out.fnum);
548 /****************************************************************************
549 Reply to a mknew or a create.
550 ****************************************************************************/
551 void reply_mknew(struct smbsrv_request *req)
555 /* parse the request */
556 REQ_CHECK_WCT(req, 3);
557 REQ_TALLOC(oi, sizeof(*oi));
559 if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
560 oi->mknew.level = RAW_OPEN_MKNEW;
562 oi->mknew.level = RAW_OPEN_CREATE;
564 oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0));
565 oi->mknew.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
567 req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
569 if (!oi->mknew.in.fname) {
570 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
574 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
575 req->async_states->send_fn = reply_mknew_send;
576 req->async_states->private_data = oi;
578 /* call the backend */
579 req->async_states->status = ntvfs_openfile(req, oi);
584 /****************************************************************************
585 Reply to a create temporary file (async reply)
586 ****************************************************************************/
587 static void reply_ctemp_send(struct smbsrv_request *req)
589 union smb_open *oi = req->async_states->private_data;
593 /* build the reply */
594 req_setup_reply(req, 1, 0);
596 SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.fnum);
598 /* the returned filename is relative to the directory */
599 req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
604 /****************************************************************************
605 Reply to a create temporary file.
606 ****************************************************************************/
607 void reply_ctemp(struct smbsrv_request *req)
611 /* parse the request */
612 REQ_CHECK_WCT(req, 3);
613 REQ_TALLOC(oi, sizeof(*oi));
615 oi->ctemp.level = RAW_OPEN_CTEMP;
616 oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
617 oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
619 /* the filename is actually a directory name, the server provides a filename
621 req_pull_ascii4(req, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
623 if (!oi->ctemp.in.directory) {
624 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
628 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
629 req->async_states->send_fn = reply_ctemp_send;
630 req->async_states->private_data = oi;
632 /* call the backend */
633 req->async_states->status = ntvfs_openfile(req, oi);
639 /****************************************************************************
641 ****************************************************************************/
642 void reply_unlink(struct smbsrv_request *req)
644 struct smb_unlink *unl;
646 /* parse the request */
647 REQ_CHECK_WCT(req, 1);
648 REQ_TALLOC(unl, sizeof(*unl));
650 unl->in.attrib = SVAL(req->in.vwv, VWV(0));
652 req_pull_ascii4(req, &unl->in.pattern, req->in.data, STR_TERMINATE);
654 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
655 req->async_states->send_fn = reply_simple_send;
658 req->async_states->status = ntvfs_unlink(req, unl);
664 /****************************************************************************
665 Reply to a readbraw (core+ protocol).
666 this is a strange packet because it doesn't use a standard SMB header in the reply,
667 only the 4 byte NBT header
668 This command must be replied to synchronously
669 ****************************************************************************/
670 void reply_readbraw(struct smbsrv_request *req)
675 io.readbraw.level = RAW_READ_READBRAW;
677 /* there are two variants, one with 10 and one with 8 command words */
678 if (req->in.wct < 8) {
682 io.readbraw.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
683 io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
684 io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3));
685 io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4));
686 io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
688 /* the 64 bit variant */
689 if (req->in.wct == 10) {
690 uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
691 io.readbraw.in.offset |= (((off_t)offset_high) << 32);
694 /* before calling the backend we setup the raw buffer. This
695 * saves a copy later */
696 req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
697 req->out.buffer = talloc(req, req->out.size);
698 if (req->out.buffer == NULL) {
701 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
703 /* tell the backend where to put the data */
704 io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
706 /* call the backend */
707 status = ntvfs_read(req, &io);
709 if (!NT_STATUS_IS_OK(status)) {
713 req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
715 req_send_reply_nosign(req);
719 /* any failure in readbraw is equivalent to reading zero bytes */
721 req->out.buffer = talloc(req, req->out.size);
722 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
724 req_send_reply_nosign(req);
728 /****************************************************************************
729 Reply to a lockread (async reply)
730 ****************************************************************************/
731 static void reply_lockread_send(struct smbsrv_request *req)
733 union smb_read *io = req->async_states->private_data;
738 io->lockread.out.nread = MIN(io->lockread.out.nread,
739 req_max_data(req) - 3);
740 req_grow_data(req, 3 + io->lockread.out.nread);
742 /* construct reply */
743 SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
744 REQ_VWV_RESERVED(1, 4);
746 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
747 SSVAL(req->out.data, 1, io->lockread.out.nread);
753 /****************************************************************************
754 Reply to a lockread (core+ protocol).
755 note that the lock is a write lock, not a read lock!
756 ****************************************************************************/
757 void reply_lockread(struct smbsrv_request *req)
762 REQ_CHECK_WCT(req, 5);
763 REQ_TALLOC(io, sizeof(*io));
765 io->lockread.level = RAW_READ_LOCKREAD;
766 io->lockread.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
767 io->lockread.in.count = SVAL(req->in.vwv, VWV(1));
768 io->lockread.in.offset = IVAL(req->in.vwv, VWV(2));
769 io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
771 /* setup the reply packet assuming the maximum possible read */
772 req_setup_reply(req, 5, 3 + io->lockread.in.count);
774 /* tell the backend where to put the data */
775 io->lockread.out.data = req->out.data + 3;
777 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
778 req->async_states->send_fn = reply_lockread_send;
779 req->async_states->private_data = io;
782 req->async_states->status = ntvfs_read(req, io);
789 /****************************************************************************
790 Reply to a read (async reply)
791 ****************************************************************************/
792 static void reply_read_send(struct smbsrv_request *req)
794 union smb_read *io = req->async_states->private_data;
799 io->read.out.nread = MIN(io->read.out.nread,
800 req_max_data(req) - 3);
801 req_grow_data(req, 3 + io->read.out.nread);
803 /* construct reply */
804 SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
805 REQ_VWV_RESERVED(1, 4);
807 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
808 SSVAL(req->out.data, 1, io->read.out.nread);
813 /****************************************************************************
815 ****************************************************************************/
816 void reply_read(struct smbsrv_request *req)
821 REQ_CHECK_WCT(req, 5);
822 REQ_TALLOC(io, sizeof(*io));
824 io->read.level = RAW_READ_READ;
825 io->read.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
826 io->read.in.count = SVAL(req->in.vwv, VWV(1));
827 io->read.in.offset = IVAL(req->in.vwv, VWV(2));
828 io->read.in.remaining = SVAL(req->in.vwv, VWV(4));
830 /* setup the reply packet assuming the maximum possible read */
831 req_setup_reply(req, 5, 3 + io->read.in.count);
833 /* tell the backend where to put the data */
834 io->read.out.data = req->out.data + 3;
836 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
837 req->async_states->send_fn = reply_read_send;
838 req->async_states->private_data = io;
841 req->async_states->status = ntvfs_read(req, io);
848 /****************************************************************************
849 Reply to a read and X (async reply)
850 ****************************************************************************/
851 static void reply_read_and_X_send(struct smbsrv_request *req)
853 union smb_read *io = req->async_states->private_data;
857 /* readx reply packets can be over-sized */
858 req->control_flags |= REQ_CONTROL_LARGE;
859 if (io->readx.in.maxcnt != 0xFFFF &&
860 io->readx.in.mincnt != 0xFFFF) {
861 req_grow_data(req, 1 + io->readx.out.nread);
862 SCVAL(req->out.data, 0, 0); /* padding */
864 req_grow_data(req, io->readx.out.nread);
867 /* construct reply */
868 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
869 SSVAL(req->out.vwv, VWV(1), 0);
870 SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
871 SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
872 REQ_VWV_RESERVED(4, 1);
873 SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
874 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
875 REQ_VWV_RESERVED(7, 5);
880 /****************************************************************************
881 Reply to a read and X.
882 ****************************************************************************/
883 void reply_read_and_X(struct smbsrv_request *req)
888 if (req->in.wct != 12) {
889 REQ_CHECK_WCT(req, 10);
892 REQ_TALLOC(io, sizeof(*io));
894 io->readx.level = RAW_READ_READX;
895 io->readx.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
896 io->readx.in.offset = IVAL(req->in.vwv, VWV(3));
897 io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
898 io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
899 io->readx.in.remaining = SVAL(req->in.vwv, VWV(9));
901 if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
902 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
903 if (high_part == 1) {
904 io->readx.in.maxcnt |= high_part << 16;
908 /* the 64 bit variant */
909 if (req->in.wct == 12) {
910 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
911 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
914 /* setup the reply packet assuming the maximum possible read */
915 req_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
917 /* tell the backend where to put the data. Notice the pad byte. */
918 if (io->readx.in.maxcnt != 0xFFFF &&
919 io->readx.in.mincnt != 0xFFFF) {
920 io->readx.out.data = req->out.data + 1;
922 io->readx.out.data = req->out.data;
925 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
926 req->async_states->send_fn = reply_read_and_X_send;
927 req->async_states->private_data = io;
930 req->async_states->status = ntvfs_read(req, io);
936 /****************************************************************************
937 Reply to a writebraw (core+ or LANMAN1.0 protocol).
938 ****************************************************************************/
939 void reply_writebraw(struct smbsrv_request *req)
941 /* this one is damn complex - put it off for now */
942 req_reply_error(req, NT_STATUS_FOOBAR);
946 /****************************************************************************
947 Reply to a writeunlock (async reply)
948 ****************************************************************************/
949 static void reply_writeunlock_send(struct smbsrv_request *req)
951 union smb_write *io = req->async_states->private_data;
955 /* construct reply */
956 req_setup_reply(req, 1, 0);
958 SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
963 /****************************************************************************
964 Reply to a writeunlock (core+).
965 ****************************************************************************/
966 void reply_writeunlock(struct smbsrv_request *req)
970 REQ_CHECK_WCT(req, 5);
971 REQ_TALLOC(io, sizeof(*io));
973 io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
974 io->writeunlock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
975 io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
976 io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
977 io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
978 io->writeunlock.in.data = req->in.data + 3;
980 /* make sure they gave us the data they promised */
981 if (io->writeunlock.in.count+3 > req->in.data_size) {
982 req_reply_error(req, NT_STATUS_FOOBAR);
986 /* make sure the data block is big enough */
987 if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
988 req_reply_error(req, NT_STATUS_FOOBAR);
992 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
993 req->async_states->send_fn = reply_writeunlock_send;
994 req->async_states->private_data = io;
997 req->async_states->status = ntvfs_write(req, io);
1004 /****************************************************************************
1005 Reply to a write (async reply)
1006 ****************************************************************************/
1007 static void reply_write_send(struct smbsrv_request *req)
1009 union smb_write *io = req->async_states->private_data;
1013 /* construct reply */
1014 req_setup_reply(req, 1, 0);
1016 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1018 req_send_reply(req);
1021 /****************************************************************************
1023 ****************************************************************************/
1024 void reply_write(struct smbsrv_request *req)
1026 union smb_write *io;
1028 REQ_CHECK_WCT(req, 5);
1029 REQ_TALLOC(io, sizeof(*io));
1031 io->write.level = RAW_WRITE_WRITE;
1032 io->write.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1033 io->write.in.count = SVAL(req->in.vwv, VWV(1));
1034 io->write.in.offset = IVAL(req->in.vwv, VWV(2));
1035 io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
1036 io->write.in.data = req->in.data + 3;
1038 /* make sure they gave us the data they promised */
1039 if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
1040 req_reply_error(req, NT_STATUS_FOOBAR);
1044 /* make sure the data block is big enough */
1045 if (SVAL(req->in.data, 1) < io->write.in.count) {
1046 req_reply_error(req, NT_STATUS_FOOBAR);
1050 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1051 req->async_states->send_fn = reply_write_send;
1052 req->async_states->private_data = io;
1055 req->async_states->status = ntvfs_write(req, io);
1061 /****************************************************************************
1062 Reply to a write and X (async reply)
1063 ****************************************************************************/
1064 static void reply_write_and_X_send(struct smbsrv_request *req)
1066 union smb_write *io = req->async_states->private_data;
1070 /* construct reply */
1071 req_setup_reply(req, 6, 0);
1073 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1074 SSVAL(req->out.vwv, VWV(1), 0);
1075 SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
1076 SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
1077 SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
1078 REQ_VWV_RESERVED(5, 1);
1083 /****************************************************************************
1084 Reply to a write and X.
1085 ****************************************************************************/
1086 void reply_write_and_X(struct smbsrv_request *req)
1088 union smb_write *io;
1090 if (req->in.wct != 14) {
1091 REQ_CHECK_WCT(req, 12);
1094 REQ_TALLOC(io, sizeof(*io));
1096 io->writex.level = RAW_WRITE_WRITEX;
1097 io->writex.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
1098 io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
1099 io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
1100 io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1101 io->writex.in.count = SVAL(req->in.vwv, VWV(10));
1102 io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1104 if (req->in.wct == 14) {
1105 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1106 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1107 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1108 io->writex.in.count |= ((uint32_t)count_high) << 16;
1111 /* make sure the data is in bounds */
1112 if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1113 req_reply_error(req, NT_STATUS_FOOBAR);
1117 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1118 req->async_states->send_fn = reply_write_and_X_send;
1119 req->async_states->private_data = io;
1122 req->async_states->status = ntvfs_write(req, io);
1128 /****************************************************************************
1129 Reply to a lseek (async reply)
1130 ****************************************************************************/
1131 static void reply_lseek_send(struct smbsrv_request *req)
1133 struct smb_seek *io = req->async_states->private_data;
1137 /* construct reply */
1138 req_setup_reply(req, 2, 0);
1140 SIVALS(req->out.vwv, VWV(0), io->out.offset);
1142 req_send_reply(req);
1145 /****************************************************************************
1147 ****************************************************************************/
1148 void reply_lseek(struct smbsrv_request *req)
1150 struct smb_seek *io;
1152 REQ_CHECK_WCT(req, 4);
1153 REQ_TALLOC(io, sizeof(*io));
1155 io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1156 io->in.mode = SVAL(req->in.vwv, VWV(1));
1157 io->in.offset = IVALS(req->in.vwv, VWV(2));
1159 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1160 req->async_states->send_fn = reply_lseek_send;
1161 req->async_states->private_data = io;
1164 req->async_states->status = ntvfs_seek(req, io);
1169 /****************************************************************************
1171 ****************************************************************************/
1172 void reply_flush(struct smbsrv_request *req)
1174 struct smb_flush *io;
1177 REQ_CHECK_WCT(req, 1);
1178 REQ_TALLOC(io, sizeof(*io));
1180 io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1182 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1183 req->async_states->send_fn = reply_simple_send;
1186 req->async_states->status = ntvfs_flush(req, io);
1192 /****************************************************************************
1193 Reply to a exit. This closes all files open by a smbpid
1194 ****************************************************************************/
1195 void reply_exit(struct smbsrv_request *req)
1198 struct smbsrv_tcon *tcon;
1199 REQ_CHECK_WCT(req, 0);
1201 for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
1203 status = ntvfs_exit(req);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 req_reply_error(req, status);
1211 req_setup_reply(req, 0, 0);
1212 req_send_reply(req);
1216 /****************************************************************************
1219 Note that this has to deal with closing a directory opened by NT SMB's.
1220 ****************************************************************************/
1221 void reply_close(struct smbsrv_request *req)
1223 union smb_close *io;
1226 REQ_CHECK_WCT(req, 3);
1227 REQ_TALLOC(io, sizeof(*io));
1229 io->close.level = RAW_CLOSE_CLOSE;
1230 io->close.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1231 io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1233 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1234 req->async_states->send_fn = reply_simple_send;
1237 req->async_states->status = ntvfs_close(req, io);
1244 /****************************************************************************
1245 Reply to a writeclose (async reply)
1246 ****************************************************************************/
1247 static void reply_writeclose_send(struct smbsrv_request *req)
1249 union smb_write *io = req->async_states->private_data;
1253 /* construct reply */
1254 req_setup_reply(req, 1, 0);
1256 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1258 req_send_reply(req);
1261 /****************************************************************************
1262 Reply to a writeclose (Core+ protocol).
1263 ****************************************************************************/
1264 void reply_writeclose(struct smbsrv_request *req)
1266 union smb_write *io;
1268 /* this one is pretty weird - the wct can be 6 or 12 */
1269 if (req->in.wct != 12) {
1270 REQ_CHECK_WCT(req, 6);
1273 REQ_TALLOC(io, sizeof(*io));
1275 io->writeclose.level = RAW_WRITE_WRITECLOSE;
1276 io->writeclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1277 io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
1278 io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1279 io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1280 io->writeclose.in.data = req->in.data + 1;
1282 /* make sure they gave us the data they promised */
1283 if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1284 req_reply_error(req, NT_STATUS_FOOBAR);
1288 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1289 req->async_states->send_fn = reply_writeclose_send;
1290 req->async_states->private_data = io;
1293 req->async_states->status = ntvfs_write(req, io);
1298 /****************************************************************************
1300 ****************************************************************************/
1301 void reply_lock(struct smbsrv_request *req)
1303 union smb_lock *lck;
1306 REQ_CHECK_WCT(req, 5);
1307 REQ_TALLOC(lck, sizeof(*lck));
1309 lck->lock.level = RAW_LOCK_LOCK;
1310 lck->lock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1311 lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
1312 lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1314 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1315 req->async_states->send_fn = reply_simple_send;
1318 req->async_states->status = ntvfs_lock(req, lck);
1324 /****************************************************************************
1326 ****************************************************************************/
1327 void reply_unlock(struct smbsrv_request *req)
1329 union smb_lock *lck;
1332 REQ_CHECK_WCT(req, 5);
1333 REQ_TALLOC(lck, sizeof(*lck));
1335 lck->unlock.level = RAW_LOCK_UNLOCK;
1336 lck->unlock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1337 lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
1338 lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1340 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1341 req->async_states->send_fn = reply_simple_send;
1344 req->async_states->status = ntvfs_lock(req, lck);
1350 /****************************************************************************
1352 ****************************************************************************/
1353 void reply_tdis(struct smbsrv_request *req)
1355 REQ_CHECK_WCT(req, 0);
1357 close_cnum(req->tcon);
1359 /* construct reply */
1360 req_setup_reply(req, 0, 0);
1362 req_send_reply(req);
1366 /****************************************************************************
1367 Reply to a echo. This is one of the few calls that is handled directly (the
1368 backends don't see it at all)
1369 ****************************************************************************/
1370 void reply_echo(struct smbsrv_request *req)
1375 REQ_CHECK_WCT(req, 0);
1377 count = SVAL(req->in.vwv, VWV(0));
1379 req_setup_reply(req, 1, req->in.data_size);
1381 memcpy(req->out.data, req->in.data, req->in.data_size);
1383 for (i=1; i <= count;i++) {
1384 struct smbsrv_request *this_req;
1387 this_req = req_setup_secondary(req);
1392 SSVAL(this_req->out.vwv, VWV(0), i);
1393 req_send_reply(this_req);
1399 /****************************************************************************
1400 Reply to a printopen (async reply)
1401 ****************************************************************************/
1402 static void reply_printopen_send(struct smbsrv_request *req)
1404 union smb_open *oi = req->async_states->private_data;
1408 /* construct reply */
1409 req_setup_reply(req, 1, 0);
1411 SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
1413 req_send_reply(req);
1416 /****************************************************************************
1417 Reply to a printopen.
1418 ****************************************************************************/
1419 void reply_printopen(struct smbsrv_request *req)
1424 REQ_CHECK_WCT(req, 2);
1425 REQ_TALLOC(oi, sizeof(*oi));
1427 oi->splopen.level = RAW_OPEN_SPLOPEN;
1428 oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1429 oi->splopen.in.mode = SVAL(req->in.vwv, VWV(1));
1431 req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1433 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1434 req->async_states->send_fn = reply_printopen_send;
1435 req->async_states->private_data = oi;
1438 req->async_states->status = ntvfs_openfile(req, oi);
1443 /****************************************************************************
1444 Reply to a printclose.
1445 ****************************************************************************/
1446 void reply_printclose(struct smbsrv_request *req)
1448 union smb_close *io;
1451 REQ_CHECK_WCT(req, 3);
1452 REQ_TALLOC(io, sizeof(*io));
1454 io->splclose.level = RAW_CLOSE_SPLCLOSE;
1455 io->splclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1457 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1458 req->async_states->send_fn = reply_simple_send;
1461 req->async_states->status = ntvfs_close(req, io);
1466 /****************************************************************************
1467 Reply to a printqueue.
1468 ****************************************************************************/
1469 void reply_printqueue_send(struct smbsrv_request *req)
1471 union smb_lpq *lpq = req->async_states->private_data;
1473 const uint_t el_size = 28;
1477 /* construct reply */
1478 req_setup_reply(req, 2, 0);
1480 /* truncate the returned list to fit in the negotiated buffer size */
1481 maxcount = (req_max_data(req) - 3) / el_size;
1482 if (maxcount < lpq->retq.out.count) {
1483 lpq->retq.out.count = maxcount;
1486 /* setup enough space in the reply */
1487 req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1489 /* and fill it in */
1490 SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1491 SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1493 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1494 SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1496 req->out.ptr = req->out.data + 3;
1498 for (i=0;i<lpq->retq.out.count;i++) {
1499 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1500 SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
1501 SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
1502 SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
1503 SCVAL(req->out.ptr, 11, 0); /* reserved */
1504 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1505 req->out.ptr += el_size;
1508 req_send_reply(req);
1511 /****************************************************************************
1512 Reply to a printqueue.
1513 ****************************************************************************/
1514 void reply_printqueue(struct smbsrv_request *req)
1519 REQ_CHECK_WCT(req, 2);
1520 REQ_TALLOC(lpq, sizeof(*lpq));
1522 lpq->retq.level = RAW_LPQ_RETQ;
1523 lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
1524 lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
1526 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1527 req->async_states->send_fn = reply_printqueue_send;
1528 req->async_states->private_data = lpq;
1531 req->async_states->status = ntvfs_lpq(req, lpq);
1537 /****************************************************************************
1538 Reply to a printwrite.
1539 ****************************************************************************/
1540 void reply_printwrite(struct smbsrv_request *req)
1542 union smb_write *io;
1545 REQ_CHECK_WCT(req, 1);
1546 REQ_TALLOC(io, sizeof(*io));
1548 io->splwrite.level = RAW_WRITE_SPLWRITE;
1550 if (req->in.data_size < 3) {
1551 req_reply_error(req, NT_STATUS_FOOBAR);
1555 io->splwrite.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1556 io->splwrite.in.count = SVAL(req->in.data, 1);
1557 io->splwrite.in.data = req->in.data + 3;
1559 /* make sure they gave us the data they promised */
1560 if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1561 req_reply_error(req, NT_STATUS_FOOBAR);
1565 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1566 req->async_states->send_fn = reply_simple_send;
1569 req->async_states->status = ntvfs_write(req, io);
1575 /****************************************************************************
1577 ****************************************************************************/
1578 void reply_mkdir(struct smbsrv_request *req)
1580 union smb_mkdir *io;
1582 /* parse the request */
1583 REQ_CHECK_WCT(req, 0);
1584 REQ_TALLOC(io, sizeof(*io));
1586 io->generic.level = RAW_MKDIR_MKDIR;
1587 req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1589 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1590 req->async_states->send_fn = reply_simple_send;
1593 req->async_states->status = ntvfs_mkdir(req, io);
1599 /****************************************************************************
1601 ****************************************************************************/
1602 void reply_rmdir(struct smbsrv_request *req)
1604 struct smb_rmdir *io;
1606 /* parse the request */
1607 REQ_CHECK_WCT(req, 0);
1608 REQ_TALLOC(io, sizeof(*io));
1610 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1612 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1613 req->async_states->send_fn = reply_simple_send;
1616 req->async_states->status = ntvfs_rmdir(req, io);
1622 /****************************************************************************
1624 ****************************************************************************/
1625 void reply_mv(struct smbsrv_request *req)
1627 union smb_rename *io;
1630 /* parse the request */
1631 REQ_CHECK_WCT(req, 1);
1632 REQ_TALLOC(io, sizeof(*io));
1634 io->generic.level = RAW_RENAME_RENAME;
1635 io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1638 p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1639 p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1641 if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1642 req_reply_error(req, NT_STATUS_FOOBAR);
1646 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1647 req->async_states->send_fn = reply_simple_send;
1650 req->async_states->status = ntvfs_rename(req, io);
1656 /****************************************************************************
1657 Reply to an NT rename.
1658 ****************************************************************************/
1659 void reply_ntrename(struct smbsrv_request *req)
1661 union smb_rename *io;
1664 /* parse the request */
1665 REQ_CHECK_WCT(req, 4);
1666 REQ_TALLOC(io, sizeof(*io));
1668 io->generic.level = RAW_RENAME_NTRENAME;
1669 io->ntrename.in.attrib = SVAL(req->in.vwv, VWV(0));
1670 io->ntrename.in.flags = SVAL(req->in.vwv, VWV(1));
1671 io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1674 p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1675 p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1677 if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1678 req_reply_error(req, NT_STATUS_FOOBAR);
1682 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1683 req->async_states->send_fn = reply_simple_send;
1686 req->async_states->status = ntvfs_rename(req, io);
1691 /****************************************************************************
1692 Reply to a file copy (async reply)
1693 ****************************************************************************/
1694 static void reply_copy_send(struct smbsrv_request *req)
1696 struct smb_copy *cp = req->async_states->private_data;
1700 /* build the reply */
1701 req_setup_reply(req, 1, 0);
1703 SSVAL(req->out.vwv, VWV(0), cp->out.count);
1705 req_send_reply(req);
1708 /****************************************************************************
1709 Reply to a file copy.
1710 ****************************************************************************/
1711 void reply_copy(struct smbsrv_request *req)
1713 struct smb_copy *cp;
1717 REQ_CHECK_WCT(req, 3);
1718 REQ_TALLOC(cp, sizeof(*cp));
1720 cp->in.tid2 = SVAL(req->in.vwv, VWV(0));
1721 cp->in.ofun = SVAL(req->in.vwv, VWV(1));
1722 cp->in.flags = SVAL(req->in.vwv, VWV(2));
1725 p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1726 p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1728 if (!cp->in.path1 || !cp->in.path2) {
1729 req_reply_error(req, NT_STATUS_FOOBAR);
1733 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1734 req->async_states->send_fn = reply_copy_send;
1735 req->async_states->private_data = cp;
1738 req->async_states->status = ntvfs_copy(req, cp);
1743 /****************************************************************************
1744 Reply to a lockingX request (async send)
1745 ****************************************************************************/
1746 static void reply_lockingX_send(struct smbsrv_request *req)
1748 union smb_lock *lck = req->async_states->private_data;
1752 /* if it was an oplock break ack then we only send a reply if
1753 there was an error */
1754 if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1759 /* construct reply */
1760 req_setup_reply(req, 2, 0);
1762 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1763 SSVAL(req->out.vwv, VWV(1), 0);
1769 /****************************************************************************
1770 Reply to a lockingX request.
1771 ****************************************************************************/
1772 void reply_lockingX(struct smbsrv_request *req)
1774 union smb_lock *lck;
1775 uint_t total_locks, i;
1780 REQ_CHECK_WCT(req, 8);
1781 REQ_TALLOC(lck, sizeof(*lck));
1783 lck->lockx.level = RAW_LOCK_LOCKX;
1784 lck->lockx.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
1785 lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
1786 lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
1787 lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1788 lck->lockx.in.lock_cnt = SVAL(req->in.vwv, VWV(7));
1790 total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1792 /* there are two variants, one with 64 bit offsets and counts */
1793 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1799 /* make sure we got the promised data */
1800 if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1801 req_reply_error(req, NT_STATUS_FOOBAR);
1805 /* allocate the locks array */
1807 REQ_TALLOC(lck->lockx.in.locks, total_locks * sizeof(lck->lockx.in.locks[0]));
1812 /* construct the locks array */
1813 for (i=0;i<total_locks;i++) {
1814 uint32_t ofs_high=0, count_high=0;
1816 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1818 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1819 ofs_high = IVAL(p, 4);
1820 lck->lockx.in.locks[i].offset = IVAL(p, 8);
1821 count_high = IVAL(p, 12);
1822 lck->lockx.in.locks[i].count = IVAL(p, 16);
1824 lck->lockx.in.locks[i].offset = IVAL(p, 2);
1825 lck->lockx.in.locks[i].count = IVAL(p, 6);
1827 if (ofs_high != 0 || count_high != 0) {
1828 lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32;
1829 lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1834 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1835 req->async_states->send_fn = reply_lockingX_send;
1836 req->async_states->private_data = lck;
1839 req->async_states->status = ntvfs_lock(req, lck);
1844 /****************************************************************************
1845 Reply to a SMBreadbmpx (read block multiplex) request.
1846 ****************************************************************************/
1847 void reply_readbmpx(struct smbsrv_request *req)
1849 /* tell the client to not use a multiplexed read - its too broken to use */
1850 req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1854 /****************************************************************************
1855 Reply to a SMBsetattrE.
1856 ****************************************************************************/
1857 void reply_setattrE(struct smbsrv_request *req)
1859 union smb_setfileinfo *info;
1862 REQ_CHECK_WCT(req, 7);
1863 REQ_TALLOC(info, sizeof(*info));
1865 info->setattre.level = RAW_SFILEINFO_SETATTRE;
1866 info->setattre.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1867 info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1868 info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1869 info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1871 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1872 req->async_states->send_fn = reply_simple_send;
1875 req->async_states->status = ntvfs_setfileinfo(req, info);
1881 /****************************************************************************
1882 Reply to a SMBwritebmpx (write block multiplex primary) request.
1883 ****************************************************************************/
1884 void reply_writebmpx(struct smbsrv_request *req)
1886 req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1890 /****************************************************************************
1891 Reply to a SMBwritebs (write block multiplex secondary) request.
1892 ****************************************************************************/
1893 void reply_writebs(struct smbsrv_request *req)
1895 req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1900 /****************************************************************************
1901 Reply to a SMBgetattrE (async reply)
1902 ****************************************************************************/
1903 static void reply_getattrE_send(struct smbsrv_request *req)
1905 union smb_fileinfo *info = req->async_states->private_data;
1910 req_setup_reply(req, 11, 0);
1912 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1913 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1914 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1915 SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
1916 SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
1917 SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
1919 req_send_reply(req);
1922 /****************************************************************************
1923 Reply to a SMBgetattrE.
1924 ****************************************************************************/
1925 void reply_getattrE(struct smbsrv_request *req)
1927 union smb_fileinfo *info;
1930 REQ_CHECK_WCT(req, 1);
1931 REQ_TALLOC(info, sizeof(*info));
1933 info->getattr.level = RAW_FILEINFO_GETATTRE;
1934 info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1936 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1937 req->async_states->send_fn = reply_getattrE_send;
1938 req->async_states->private_data = info;
1941 req->async_states->status = ntvfs_qfileinfo(req, info);
1947 /****************************************************************************
1948 reply to an old style session setup command
1949 ****************************************************************************/
1950 static void reply_sesssetup_old(struct smbsrv_request *req)
1953 union smb_sesssetup sess;
1957 sess.old.level = RAW_SESSSETUP_OLD;
1960 sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1961 sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1962 sess.old.in.vc_num = SVAL(req->in.vwv, VWV(4));
1963 sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1964 passlen = SVAL(req->in.vwv, VWV(7));
1966 /* check the request isn't malformed */
1967 if (req_data_oob(req, req->in.data, passlen)) {
1968 req_reply_error(req, NT_STATUS_FOOBAR);
1973 if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1974 req_reply_error(req, NT_STATUS_FOOBAR);
1979 p += req_pull_string(req, &sess.old.in.user, p, -1, STR_TERMINATE);
1980 p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1981 p += req_pull_string(req, &sess.old.in.os, p, -1, STR_TERMINATE);
1982 p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
1984 /* call the generic handler */
1985 status = sesssetup_backend(req, &sess);
1987 if (!NT_STATUS_IS_OK(status)) {
1988 req_reply_error(req, status);
1992 /* construct reply */
1993 req_setup_reply(req, 3, 0);
1995 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1996 SSVAL(req->out.vwv, VWV(1), 0);
1997 SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
1999 SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
2005 /****************************************************************************
2006 reply to an NT1 style session setup command
2007 ****************************************************************************/
2008 static void reply_sesssetup_nt1(struct smbsrv_request *req)
2011 union smb_sesssetup sess;
2013 uint16_t passlen1, passlen2;
2015 sess.nt1.level = RAW_SESSSETUP_NT1;
2018 sess.nt1.in.bufsize = SVAL(req->in.vwv, VWV(2));
2019 sess.nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2020 sess.nt1.in.vc_num = SVAL(req->in.vwv, VWV(4));
2021 sess.nt1.in.sesskey = IVAL(req->in.vwv, VWV(5));
2022 passlen1 = SVAL(req->in.vwv, VWV(7));
2023 passlen2 = SVAL(req->in.vwv, VWV(8));
2024 sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
2026 /* check the request isn't malformed */
2027 if (req_data_oob(req, req->in.data, passlen1) ||
2028 req_data_oob(req, req->in.data + passlen1, passlen2)) {
2029 req_reply_error(req, NT_STATUS_FOOBAR);
2034 if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
2035 req_reply_error(req, NT_STATUS_FOOBAR);
2039 if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
2040 req_reply_error(req, NT_STATUS_FOOBAR);
2045 p += req_pull_string(req, &sess.nt1.in.user, p, -1, STR_TERMINATE);
2046 p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
2047 p += req_pull_string(req, &sess.nt1.in.os, p, -1, STR_TERMINATE);
2048 p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
2050 /* call the generic handler */
2051 status = sesssetup_backend(req, &sess);
2053 if (!NT_STATUS_IS_OK(status)) {
2054 req_reply_error(req, status);
2058 /* construct reply */
2059 req_setup_reply(req, 3, 0);
2061 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2062 SSVAL(req->out.vwv, VWV(1), 0);
2063 SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
2065 SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
2067 req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
2068 req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
2069 req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
2075 /****************************************************************************
2076 reply to an SPNEGO style session setup command
2077 ****************************************************************************/
2078 static void reply_sesssetup_spnego(struct smbsrv_request *req)
2081 union smb_sesssetup sess;
2085 sess.spnego.level = RAW_SESSSETUP_SPNEGO;
2088 sess.spnego.in.bufsize = SVAL(req->in.vwv, VWV(2));
2089 sess.spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2090 sess.spnego.in.vc_num = SVAL(req->in.vwv, VWV(4));
2091 sess.spnego.in.sesskey = IVAL(req->in.vwv, VWV(5));
2092 blob_len = SVAL(req->in.vwv, VWV(7));
2093 sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
2096 if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
2097 req_reply_error(req, NT_STATUS_FOOBAR);
2102 p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE);
2103 p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE);
2104 p += req_pull_string(req, &sess.spnego.in.domain, p, -1, STR_TERMINATE);
2106 /* call the generic handler */
2107 status = sesssetup_backend(req, &sess);
2109 if (!NT_STATUS_IS_OK(status) &&
2110 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2111 req_reply_error(req, status);
2115 /* construct reply */
2116 req_setup_reply(req, 4, sess.spnego.out.secblob.length);
2118 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2119 req_setup_error(req, status);
2122 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2123 SSVAL(req->out.vwv, VWV(1), 0);
2124 SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
2125 SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
2127 SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
2129 memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
2130 req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
2131 req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
2132 req_push_str(req, NULL, sess.spnego.out.domain, -1, STR_TERMINATE);
2138 /****************************************************************************
2139 reply to a session setup command
2140 ****************************************************************************/
2141 void reply_sesssetup(struct smbsrv_request *req)
2143 switch (req->in.wct) {
2145 /* a pre-NT1 call */
2146 reply_sesssetup_old(req);
2150 reply_sesssetup_nt1(req);
2154 reply_sesssetup_spnego(req);
2158 /* unsupported variant */
2159 req_reply_error(req, NT_STATUS_FOOBAR);
2162 /****************************************************************************
2163 Reply to a SMBulogoffX.
2164 ****************************************************************************/
2165 void reply_ulogoffX(struct smbsrv_request *req)
2167 struct smbsrv_tcon *tcon;
2171 vuid = SVAL(req->in.hdr, HDR_UID);
2173 /* in user level security we are supposed to close any files
2174 open by this user on all open tree connects */
2175 if ((vuid != 0) && (lp_security() != SEC_SHARE)) {
2176 for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
2178 status = ntvfs_logoff(req);
2180 if (!NT_STATUS_IS_OK(status)) {
2181 req_reply_error(req, status);
2187 smbsrv_invalidate_vuid(req->smb_conn, vuid);
2189 req_setup_reply(req, 2, 0);
2191 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2192 SSVAL(req->out.vwv, VWV(1), 0);
2198 /****************************************************************************
2199 Reply to an SMBfindclose request
2200 ****************************************************************************/
2201 void reply_findclose(struct smbsrv_request *req)
2204 union smb_search_close io;
2206 io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2209 REQ_CHECK_WCT(req, 1);
2211 io.findclose.in.handle = SVAL(req->in.vwv, VWV(0));
2214 status = ntvfs_search_close(req, &io);
2216 if (!NT_STATUS_IS_OK(status)) {
2217 req_reply_error(req, status);
2221 /* construct reply */
2222 req_setup_reply(req, 0, 0);
2224 req_send_reply(req);
2227 /****************************************************************************
2228 Reply to an SMBfindnclose request
2229 ****************************************************************************/
2230 void reply_findnclose(struct smbsrv_request *req)
2232 req_reply_error(req, NT_STATUS_FOOBAR);
2236 /****************************************************************************
2237 Reply to an SMBntcreateX request (async send)
2238 ****************************************************************************/
2239 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
2241 union smb_open *io = req->async_states->private_data;
2245 /* construct reply */
2246 req_setup_reply(req, 34, 0);
2248 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2249 SSVAL(req->out.vwv, VWV(1), 0);
2250 SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2252 /* the rest of the parameters are not aligned! */
2253 SSVAL(req->out.vwv, 5, io->ntcreatex.out.fnum);
2254 SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
2255 push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2256 push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2257 push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2258 push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2259 SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
2260 SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
2261 SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
2262 SSVAL(req->out.vwv, 63, io->ntcreatex.out.file_type);
2263 SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
2264 SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
2269 /****************************************************************************
2270 Reply to an SMBntcreateX request
2271 ****************************************************************************/
2272 void reply_ntcreate_and_X(struct smbsrv_request *req)
2277 /* parse the request */
2278 REQ_CHECK_WCT(req, 24);
2279 REQ_TALLOC(io, sizeof(*io));
2281 io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2283 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2284 fname_len = SVAL(req->in.vwv, 5);
2285 io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
2286 io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
2287 io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
2288 io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
2289 io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
2290 io->ntcreatex.in.share_access = IVAL(req->in.vwv, 31);
2291 io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2292 io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
2293 io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
2294 io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
2295 io->ntcreatex.in.ea_list = NULL;
2296 io->ntcreatex.in.sec_desc = NULL;
2298 /* we need a neater way to handle this alignment */
2299 if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
2300 ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2304 req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2305 if (!io->ntcreatex.in.fname) {
2306 req_reply_error(req, NT_STATUS_FOOBAR);
2310 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
2311 req->async_states->send_fn = reply_ntcreate_and_X_send;
2312 req->async_states->private_data = io;
2314 /* call the backend */
2315 req->async_states->status = ntvfs_openfile(req, io);
2321 /****************************************************************************
2322 Reply to an SMBntcancel request
2323 ****************************************************************************/
2324 void reply_ntcancel(struct smbsrv_request *req)
2326 /* NOTE: this request does not generate a reply */
2327 req_signing_no_reply(req);
2332 /****************************************************************************
2333 Reply to an SMBsends request
2334 ****************************************************************************/
2335 void reply_sends(struct smbsrv_request *req)
2337 req_reply_error(req, NT_STATUS_FOOBAR);
2340 /****************************************************************************
2341 Reply to an SMBsendstrt request
2342 ****************************************************************************/
2343 void reply_sendstrt(struct smbsrv_request *req)
2345 req_reply_error(req, NT_STATUS_FOOBAR);
2348 /****************************************************************************
2349 Reply to an SMBsendend request
2350 ****************************************************************************/
2351 void reply_sendend(struct smbsrv_request *req)
2353 req_reply_error(req, NT_STATUS_FOOBAR);
2356 /****************************************************************************
2357 Reply to an SMBsendtxt request
2358 ****************************************************************************/
2359 void reply_sendtxt(struct smbsrv_request *req)
2361 req_reply_error(req, NT_STATUS_FOOBAR);
2366 /****************************************************************************
2367 Reply to a special message - a SMB packet with non zero NBT message type
2368 ****************************************************************************/
2369 void reply_special(struct smbsrv_request *req)
2372 uint8_t *buf = talloc_zero_array_p(req, uint8_t, 4);
2374 msg_type = CVAL(req->in.buffer,0);
2379 case 0x81: /* session request */
2380 if (req->smb_conn->negotiate.done_nbt_session) {
2381 smbsrv_terminate_connection(req->smb_conn,
2382 "multiple session request not permitted");
2389 DEBUG(0,("REWRITE: not parsing netbios names in NBT session request!\n"));
2390 /* TODO: store the name for the session setup 'remote
2391 machine' code, as well as smbstatus */
2393 req->smb_conn->negotiate.done_nbt_session = True;
2395 req->out.buffer = buf;
2397 req_send_reply_nosign(req);
2400 case 0x89: /* session keepalive request
2401 (some old clients produce this?) */
2402 SCVAL(buf, 0, SMBkeepalive);
2404 req->out.buffer = buf;
2406 req_send_reply_nosign(req);
2410 /* session keepalive - swallow it */
2415 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));