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"
31 /* useful way of catching wct errors with file and line number */
32 #define REQ_CHECK_WCT(req, wcount) do { \
33 if ((req)->in.wct != (wcount)) { \
34 DEBUG(1,("Unexpected WCT %d at %s(%d) - expected %d\n", \
35 (req)->in.wct, __FILE__, __LINE__, wcount)); \
36 req_reply_dos_error(req, ERRSRV, ERRerror); \
40 /* check req->async_states->status and if not OK then send an error reply */
41 #define CHECK_ASYNC_STATUS do { \
42 if (!NT_STATUS_IS_OK(req->async_states->status)) { \
43 req_reply_error(req, req->async_states->status); \
47 /* useful wrapper for talloc with NO_MEMORY reply */
48 #define REQ_TALLOC(ptr, size) do { \
49 ptr = talloc_size(req, size); \
51 req_reply_error(req, NT_STATUS_NO_MEMORY); \
56 check if the backend wants to handle the request asynchronously.
57 if it wants it handled synchronously then call the send function
60 #define REQ_ASYNC_TAIL do { \
61 if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
62 req->async_states->send_fn(req); \
65 /* zero out some reserved fields in a reply */
66 #define REQ_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)
68 /****************************************************************************
69 Reply to a simple request (async send)
70 ****************************************************************************/
71 static void reply_simple_send(struct smbsrv_request *req)
75 req_setup_reply(req, 0, 0);
80 /****************************************************************************
82 ****************************************************************************/
83 void reply_tcon(struct smbsrv_request *req)
90 REQ_CHECK_WCT(req, 0);
92 con.tcon.level = RAW_TCON_TCON;
95 p += req_pull_ascii4(req, &con.tcon.in.service, p, STR_TERMINATE);
96 p += req_pull_ascii4(req, &con.tcon.in.password, p, STR_TERMINATE);
97 p += req_pull_ascii4(req, &con.tcon.in.dev, p, STR_TERMINATE);
99 if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
100 req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
105 status = tcon_backend(req, &con);
107 if (!NT_STATUS_IS_OK(status)) {
108 req_reply_error(req, status);
112 /* construct reply */
113 req_setup_reply(req, 2, 0);
115 SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
116 SSVAL(req->out.vwv, VWV(1), con.tcon.out.tid);
117 SSVAL(req->out.hdr, HDR_TID, req->tcon->tid);
123 /****************************************************************************
124 Reply to a tcon and X.
125 ****************************************************************************/
126 void reply_tcon_and_X(struct smbsrv_request *req)
133 con.tconx.level = RAW_TCON_TCONX;
136 REQ_CHECK_WCT(req, 4);
138 con.tconx.in.flags = SVAL(req->in.vwv, VWV(2));
139 passlen = SVAL(req->in.vwv, VWV(3));
143 if (!req_pull_blob(req, p, passlen, &con.tconx.in.password)) {
144 req_reply_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
149 p += req_pull_string(req, &con.tconx.in.path, p, -1, STR_TERMINATE);
150 p += req_pull_string(req, &con.tconx.in.device, p, -1, STR_ASCII);
152 if (!con.tconx.in.path || !con.tconx.in.device) {
153 req_reply_error(req, NT_STATUS_BAD_DEVICE_TYPE);
158 status = tcon_backend(req, &con);
160 if (!NT_STATUS_IS_OK(status)) {
161 req_reply_error(req, status);
165 /* construct reply - two variants */
166 if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
167 req_setup_reply(req, 2, 0);
169 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
170 SSVAL(req->out.vwv, VWV(1), 0);
172 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
174 req_setup_reply(req, 3, 0);
176 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
177 SSVAL(req->out.vwv, VWV(1), 0);
178 SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
180 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
181 req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
184 /* set the incoming and outgoing tid to the just created one */
185 SSVAL(req->in.hdr, HDR_TID, con.tconx.out.tid);
186 SSVAL(req->out.hdr,HDR_TID, con.tconx.out.tid);
192 /****************************************************************************
193 Reply to an unknown request
194 ****************************************************************************/
195 void reply_unknown(struct smbsrv_request *req)
199 type = CVAL(req->in.hdr, HDR_COM);
201 DEBUG(0,("unknown command type %d (0x%X)\n", type, type));
203 req_reply_dos_error(req, ERRSRV, ERRunknownsmb);
207 /****************************************************************************
208 Reply to an ioctl (async reply)
209 ****************************************************************************/
210 static void reply_ioctl_send(struct smbsrv_request *req)
212 union smb_ioctl *io = req->async_states->private_data;
216 /* the +1 is for nicer alignment */
217 req_setup_reply(req, 8, io->ioctl.out.blob.length+1);
218 SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length);
219 SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length);
220 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1);
222 memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length);
227 /****************************************************************************
229 ****************************************************************************/
230 void reply_ioctl(struct smbsrv_request *req)
235 REQ_CHECK_WCT(req, 3);
236 REQ_TALLOC(io, sizeof(*io));
238 io->ioctl.level = RAW_IOCTL_IOCTL;
239 io->ioctl.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
240 io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
242 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
243 req->async_states->send_fn = reply_ioctl_send;
244 req->async_states->private_data = io;
247 req->async_states->status = ntvfs_ioctl(req, io);
253 /****************************************************************************
255 ****************************************************************************/
256 void reply_chkpth(struct smbsrv_request *req)
258 struct smb_chkpath *io;
260 REQ_TALLOC(io, sizeof(*io));
262 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
264 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
265 req->async_states->send_fn = reply_simple_send;
267 req->async_states->status = ntvfs_chkpath(req, io);
272 /****************************************************************************
273 Reply to a getatr (async reply)
274 ****************************************************************************/
275 static void reply_getatr_send(struct smbsrv_request *req)
277 union smb_fileinfo *st = req->async_states->private_data;
281 /* construct reply */
282 req_setup_reply(req, 10, 0);
284 SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib);
285 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
286 SIVAL(req->out.vwv, VWV(3), st->getattr.out.size);
288 REQ_VWV_RESERVED(5, 5);
294 /****************************************************************************
296 ****************************************************************************/
297 void reply_getatr(struct smbsrv_request *req)
299 union smb_fileinfo *st;
301 REQ_TALLOC(st, sizeof(*st));
303 st->getattr.level = RAW_FILEINFO_GETATTR;
306 req_pull_ascii4(req, &st->getattr.in.fname, req->in.data, STR_TERMINATE);
307 if (!st->getattr.in.fname) {
308 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
312 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
313 req->async_states->send_fn = reply_getatr_send;
314 req->async_states->private_data = st;
317 req->async_states->status = ntvfs_qpathinfo(req, st);
323 /****************************************************************************
325 ****************************************************************************/
326 void reply_setatr(struct smbsrv_request *req)
328 union smb_setfileinfo *st;
331 REQ_CHECK_WCT(req, 8);
332 REQ_TALLOC(st, sizeof(*st));
334 st->setattr.level = RAW_SFILEINFO_SETATTR;
335 st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0));
336 st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
338 req_pull_ascii4(req, &st->setattr.file.fname, req->in.data, STR_TERMINATE);
340 if (!st->setattr.file.fname) {
341 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
345 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
346 req->async_states->send_fn = reply_simple_send;
349 req->async_states->status = ntvfs_setpathinfo(req, st);
355 /****************************************************************************
356 Reply to a dskattr (async reply)
357 ****************************************************************************/
358 static void reply_dskattr_send(struct smbsrv_request *req)
360 union smb_fsinfo *fs = req->async_states->private_data;
364 /* construct reply */
365 req_setup_reply(req, 5, 0);
367 SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total);
368 SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit);
369 SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size);
370 SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free);
372 REQ_VWV_RESERVED(4, 1);
378 /****************************************************************************
380 ****************************************************************************/
381 void reply_dskattr(struct smbsrv_request *req)
383 union smb_fsinfo *fs;
385 REQ_TALLOC(fs, sizeof(*fs));
387 fs->dskattr.level = RAW_QFS_DSKATTR;
389 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
390 req->async_states->send_fn = reply_dskattr_send;
391 req->async_states->private_data = fs;
394 req->async_states->status = ntvfs_fsinfo(req, fs);
401 /****************************************************************************
402 Reply to an open (async reply)
403 ****************************************************************************/
404 static void reply_open_send(struct smbsrv_request *req)
406 union smb_open *oi = req->async_states->private_data;
410 /* construct reply */
411 req_setup_reply(req, 7, 0);
413 SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
414 SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
415 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
416 SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
417 SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
422 /****************************************************************************
424 ****************************************************************************/
425 void reply_open(struct smbsrv_request *req)
430 REQ_CHECK_WCT(req, 2);
431 REQ_TALLOC(oi, sizeof(*oi));
433 oi->openold.level = RAW_OPEN_OPEN;
434 oi->openold.in.open_mode = SVAL(req->in.vwv, VWV(0));
435 oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
437 req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
439 if (!oi->openold.in.fname) {
440 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
444 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
445 req->async_states->send_fn = reply_open_send;
446 req->async_states->private_data = oi;
449 req->async_states->status = ntvfs_openfile(req, oi);
455 /****************************************************************************
456 Reply to an open and X (async reply)
457 ****************************************************************************/
458 static void reply_open_and_X_send(struct smbsrv_request *req)
460 union smb_open *oi = req->async_states->private_data;
464 /* build the reply */
465 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
466 req_setup_reply(req, 19, 0);
468 req_setup_reply(req, 15, 0);
471 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
472 SSVAL(req->out.vwv, VWV(1), 0);
473 SSVAL(req->out.vwv, VWV(2), oi->openx.out.fnum);
474 SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
475 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
476 SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
477 SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
478 SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
479 SSVAL(req->out.vwv, VWV(10),oi->openx.out.devstate);
480 SSVAL(req->out.vwv, VWV(11),oi->openx.out.action);
481 SIVAL(req->out.vwv, VWV(12),oi->openx.out.unique_fid);
482 SSVAL(req->out.vwv, VWV(14),0); /* reserved */
483 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
484 SIVAL(req->out.vwv, VWV(15),oi->openx.out.access_mask);
485 REQ_VWV_RESERVED(17, 2);
488 req->chained_fnum = oi->openx.out.fnum;
494 /****************************************************************************
495 Reply to an open and X.
496 ****************************************************************************/
497 void reply_open_and_X(struct smbsrv_request *req)
501 /* parse the request */
502 REQ_CHECK_WCT(req, 15);
503 REQ_TALLOC(oi, sizeof(*oi));
505 oi->openx.level = RAW_OPEN_OPENX;
506 oi->openx.in.flags = SVAL(req->in.vwv, VWV(2));
507 oi->openx.in.open_mode = SVAL(req->in.vwv, VWV(3));
508 oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
509 oi->openx.in.file_attrs = SVAL(req->in.vwv, VWV(5));
510 oi->openx.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
511 oi->openx.in.open_func = SVAL(req->in.vwv, VWV(8));
512 oi->openx.in.size = IVAL(req->in.vwv, VWV(9));
513 oi->openx.in.timeout = IVAL(req->in.vwv, VWV(11));
515 req_pull_ascii4(req, &oi->openx.in.fname, req->in.data, STR_TERMINATE);
517 if (!oi->openx.in.fname) {
518 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
522 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
523 req->async_states->send_fn = reply_open_and_X_send;
524 req->async_states->private_data = oi;
526 /* call the backend */
527 req->async_states->status = ntvfs_openfile(req, oi);
533 /****************************************************************************
534 Reply to a mknew or a create.
535 ****************************************************************************/
536 static void reply_mknew_send(struct smbsrv_request *req)
538 union smb_open *oi = req->async_states->private_data;
542 /* build the reply */
543 req_setup_reply(req, 1, 0);
545 SSVAL(req->out.vwv, VWV(0), oi->mknew.out.fnum);
551 /****************************************************************************
552 Reply to a mknew or a create.
553 ****************************************************************************/
554 void reply_mknew(struct smbsrv_request *req)
558 /* parse the request */
559 REQ_CHECK_WCT(req, 3);
560 REQ_TALLOC(oi, sizeof(*oi));
562 if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
563 oi->mknew.level = RAW_OPEN_MKNEW;
565 oi->mknew.level = RAW_OPEN_CREATE;
567 oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0));
568 oi->mknew.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
570 req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
572 if (!oi->mknew.in.fname) {
573 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
577 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
578 req->async_states->send_fn = reply_mknew_send;
579 req->async_states->private_data = oi;
581 /* call the backend */
582 req->async_states->status = ntvfs_openfile(req, oi);
587 /****************************************************************************
588 Reply to a create temporary file (async reply)
589 ****************************************************************************/
590 static void reply_ctemp_send(struct smbsrv_request *req)
592 union smb_open *oi = req->async_states->private_data;
596 /* build the reply */
597 req_setup_reply(req, 1, 0);
599 SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.fnum);
601 /* the returned filename is relative to the directory */
602 req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
607 /****************************************************************************
608 Reply to a create temporary file.
609 ****************************************************************************/
610 void reply_ctemp(struct smbsrv_request *req)
614 /* parse the request */
615 REQ_CHECK_WCT(req, 3);
616 REQ_TALLOC(oi, sizeof(*oi));
618 oi->ctemp.level = RAW_OPEN_CTEMP;
619 oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
620 oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
622 /* the filename is actually a directory name, the server provides a filename
624 req_pull_ascii4(req, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
626 if (!oi->ctemp.in.directory) {
627 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
631 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
632 req->async_states->send_fn = reply_ctemp_send;
633 req->async_states->private_data = oi;
635 /* call the backend */
636 req->async_states->status = ntvfs_openfile(req, oi);
642 /****************************************************************************
644 ****************************************************************************/
645 void reply_unlink(struct smbsrv_request *req)
647 struct smb_unlink *unl;
649 /* parse the request */
650 REQ_CHECK_WCT(req, 1);
651 REQ_TALLOC(unl, sizeof(*unl));
653 unl->in.attrib = SVAL(req->in.vwv, VWV(0));
655 req_pull_ascii4(req, &unl->in.pattern, req->in.data, STR_TERMINATE);
657 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
658 req->async_states->send_fn = reply_simple_send;
661 req->async_states->status = ntvfs_unlink(req, unl);
667 /****************************************************************************
668 Reply to a readbraw (core+ protocol).
669 this is a strange packet because it doesn't use a standard SMB header in the reply,
670 only the 4 byte NBT header
671 This command must be replied to synchronously
672 ****************************************************************************/
673 void reply_readbraw(struct smbsrv_request *req)
678 io.readbraw.level = RAW_READ_READBRAW;
680 /* there are two variants, one with 10 and one with 8 command words */
681 if (req->in.wct < 8) {
685 io.readbraw.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
686 io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
687 io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3));
688 io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4));
689 io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
691 /* the 64 bit variant */
692 if (req->in.wct == 10) {
693 uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
694 io.readbraw.in.offset |= (((off_t)offset_high) << 32);
697 /* before calling the backend we setup the raw buffer. This
698 * saves a copy later */
699 req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
700 req->out.buffer = talloc_size(req, req->out.size);
701 if (req->out.buffer == NULL) {
704 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
706 /* tell the backend where to put the data */
707 io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
709 /* call the backend */
710 status = ntvfs_read(req, &io);
712 if (!NT_STATUS_IS_OK(status)) {
716 req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
718 req_send_reply_nosign(req);
722 /* any failure in readbraw is equivalent to reading zero bytes */
724 req->out.buffer = talloc_size(req, req->out.size);
725 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
727 req_send_reply_nosign(req);
731 /****************************************************************************
732 Reply to a lockread (async reply)
733 ****************************************************************************/
734 static void reply_lockread_send(struct smbsrv_request *req)
736 union smb_read *io = req->async_states->private_data;
741 io->lockread.out.nread = MIN(io->lockread.out.nread,
742 req_max_data(req) - 3);
743 req_grow_data(req, 3 + io->lockread.out.nread);
745 /* construct reply */
746 SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
747 REQ_VWV_RESERVED(1, 4);
749 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
750 SSVAL(req->out.data, 1, io->lockread.out.nread);
756 /****************************************************************************
757 Reply to a lockread (core+ protocol).
758 note that the lock is a write lock, not a read lock!
759 ****************************************************************************/
760 void reply_lockread(struct smbsrv_request *req)
765 REQ_CHECK_WCT(req, 5);
766 REQ_TALLOC(io, sizeof(*io));
768 io->lockread.level = RAW_READ_LOCKREAD;
769 io->lockread.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
770 io->lockread.in.count = SVAL(req->in.vwv, VWV(1));
771 io->lockread.in.offset = IVAL(req->in.vwv, VWV(2));
772 io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
774 /* setup the reply packet assuming the maximum possible read */
775 req_setup_reply(req, 5, 3 + io->lockread.in.count);
777 /* tell the backend where to put the data */
778 io->lockread.out.data = req->out.data + 3;
780 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
781 req->async_states->send_fn = reply_lockread_send;
782 req->async_states->private_data = io;
785 req->async_states->status = ntvfs_read(req, io);
792 /****************************************************************************
793 Reply to a read (async reply)
794 ****************************************************************************/
795 static void reply_read_send(struct smbsrv_request *req)
797 union smb_read *io = req->async_states->private_data;
802 io->read.out.nread = MIN(io->read.out.nread,
803 req_max_data(req) - 3);
804 req_grow_data(req, 3 + io->read.out.nread);
806 /* construct reply */
807 SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
808 REQ_VWV_RESERVED(1, 4);
810 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
811 SSVAL(req->out.data, 1, io->read.out.nread);
816 /****************************************************************************
818 ****************************************************************************/
819 void reply_read(struct smbsrv_request *req)
824 REQ_CHECK_WCT(req, 5);
825 REQ_TALLOC(io, sizeof(*io));
827 io->read.level = RAW_READ_READ;
828 io->read.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
829 io->read.in.count = SVAL(req->in.vwv, VWV(1));
830 io->read.in.offset = IVAL(req->in.vwv, VWV(2));
831 io->read.in.remaining = SVAL(req->in.vwv, VWV(4));
833 /* setup the reply packet assuming the maximum possible read */
834 req_setup_reply(req, 5, 3 + io->read.in.count);
836 /* tell the backend where to put the data */
837 io->read.out.data = req->out.data + 3;
839 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
840 req->async_states->send_fn = reply_read_send;
841 req->async_states->private_data = io;
844 req->async_states->status = ntvfs_read(req, io);
851 /****************************************************************************
852 Reply to a read and X (async reply)
853 ****************************************************************************/
854 static void reply_read_and_X_send(struct smbsrv_request *req)
856 union smb_read *io = req->async_states->private_data;
860 /* readx reply packets can be over-sized */
861 req->control_flags |= REQ_CONTROL_LARGE;
862 if (io->readx.in.maxcnt != 0xFFFF &&
863 io->readx.in.mincnt != 0xFFFF) {
864 req_grow_data(req, 1 + io->readx.out.nread);
865 SCVAL(req->out.data, 0, 0); /* padding */
867 req_grow_data(req, io->readx.out.nread);
870 /* construct reply */
871 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
872 SSVAL(req->out.vwv, VWV(1), 0);
873 SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
874 SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
875 REQ_VWV_RESERVED(4, 1);
876 SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
877 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
878 REQ_VWV_RESERVED(7, 5);
883 /****************************************************************************
884 Reply to a read and X.
885 ****************************************************************************/
886 void reply_read_and_X(struct smbsrv_request *req)
891 if (req->in.wct != 12) {
892 REQ_CHECK_WCT(req, 10);
895 REQ_TALLOC(io, sizeof(*io));
897 io->readx.level = RAW_READ_READX;
898 io->readx.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
899 io->readx.in.offset = IVAL(req->in.vwv, VWV(3));
900 io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
901 io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
902 io->readx.in.remaining = SVAL(req->in.vwv, VWV(9));
904 if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
905 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
906 if (high_part == 1) {
907 io->readx.in.maxcnt |= high_part << 16;
911 /* the 64 bit variant */
912 if (req->in.wct == 12) {
913 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
914 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
917 /* setup the reply packet assuming the maximum possible read */
918 req_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
920 /* tell the backend where to put the data. Notice the pad byte. */
921 if (io->readx.in.maxcnt != 0xFFFF &&
922 io->readx.in.mincnt != 0xFFFF) {
923 io->readx.out.data = req->out.data + 1;
925 io->readx.out.data = req->out.data;
928 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
929 req->async_states->send_fn = reply_read_and_X_send;
930 req->async_states->private_data = io;
933 req->async_states->status = ntvfs_read(req, io);
939 /****************************************************************************
940 Reply to a writebraw (core+ or LANMAN1.0 protocol).
941 ****************************************************************************/
942 void reply_writebraw(struct smbsrv_request *req)
944 req_reply_dos_error(req, ERRSRV, ERRuseSTD);
948 /****************************************************************************
949 Reply to a writeunlock (async reply)
950 ****************************************************************************/
951 static void reply_writeunlock_send(struct smbsrv_request *req)
953 union smb_write *io = req->async_states->private_data;
957 /* construct reply */
958 req_setup_reply(req, 1, 0);
960 SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
965 /****************************************************************************
966 Reply to a writeunlock (core+).
967 ****************************************************************************/
968 void reply_writeunlock(struct smbsrv_request *req)
972 REQ_CHECK_WCT(req, 5);
973 REQ_TALLOC(io, sizeof(*io));
975 io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
976 io->writeunlock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
977 io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
978 io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
979 io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
980 io->writeunlock.in.data = req->in.data + 3;
982 /* make sure they gave us the data they promised */
983 if (io->writeunlock.in.count+3 > req->in.data_size) {
984 req_reply_error(req, NT_STATUS_FOOBAR);
988 /* make sure the data block is big enough */
989 if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
990 req_reply_error(req, NT_STATUS_FOOBAR);
994 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
995 req->async_states->send_fn = reply_writeunlock_send;
996 req->async_states->private_data = io;
999 req->async_states->status = ntvfs_write(req, io);
1006 /****************************************************************************
1007 Reply to a write (async reply)
1008 ****************************************************************************/
1009 static void reply_write_send(struct smbsrv_request *req)
1011 union smb_write *io = req->async_states->private_data;
1015 /* construct reply */
1016 req_setup_reply(req, 1, 0);
1018 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1020 req_send_reply(req);
1023 /****************************************************************************
1025 ****************************************************************************/
1026 void reply_write(struct smbsrv_request *req)
1028 union smb_write *io;
1030 REQ_CHECK_WCT(req, 5);
1031 REQ_TALLOC(io, sizeof(*io));
1033 io->write.level = RAW_WRITE_WRITE;
1034 io->write.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1035 io->write.in.count = SVAL(req->in.vwv, VWV(1));
1036 io->write.in.offset = IVAL(req->in.vwv, VWV(2));
1037 io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
1038 io->write.in.data = req->in.data + 3;
1040 /* make sure they gave us the data they promised */
1041 if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
1042 req_reply_error(req, NT_STATUS_FOOBAR);
1046 /* make sure the data block is big enough */
1047 if (SVAL(req->in.data, 1) < io->write.in.count) {
1048 req_reply_error(req, NT_STATUS_FOOBAR);
1052 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1053 req->async_states->send_fn = reply_write_send;
1054 req->async_states->private_data = io;
1057 req->async_states->status = ntvfs_write(req, io);
1063 /****************************************************************************
1064 Reply to a write and X (async reply)
1065 ****************************************************************************/
1066 static void reply_write_and_X_send(struct smbsrv_request *req)
1068 union smb_write *io = req->async_states->private_data;
1072 /* construct reply */
1073 req_setup_reply(req, 6, 0);
1075 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1076 SSVAL(req->out.vwv, VWV(1), 0);
1077 SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
1078 SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
1079 SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
1080 REQ_VWV_RESERVED(5, 1);
1085 /****************************************************************************
1086 Reply to a write and X.
1087 ****************************************************************************/
1088 void reply_write_and_X(struct smbsrv_request *req)
1090 union smb_write *io;
1092 if (req->in.wct != 14) {
1093 REQ_CHECK_WCT(req, 12);
1096 REQ_TALLOC(io, sizeof(*io));
1098 io->writex.level = RAW_WRITE_WRITEX;
1099 io->writex.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
1100 io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
1101 io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
1102 io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1103 io->writex.in.count = SVAL(req->in.vwv, VWV(10));
1104 io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1106 if (req->in.wct == 14) {
1107 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1108 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1109 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1110 io->writex.in.count |= ((uint32_t)count_high) << 16;
1113 /* make sure the data is in bounds */
1114 if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1115 req_reply_error(req, NT_STATUS_FOOBAR);
1119 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1120 req->async_states->send_fn = reply_write_and_X_send;
1121 req->async_states->private_data = io;
1124 req->async_states->status = ntvfs_write(req, io);
1130 /****************************************************************************
1131 Reply to a lseek (async reply)
1132 ****************************************************************************/
1133 static void reply_lseek_send(struct smbsrv_request *req)
1135 struct smb_seek *io = req->async_states->private_data;
1139 /* construct reply */
1140 req_setup_reply(req, 2, 0);
1142 SIVALS(req->out.vwv, VWV(0), io->out.offset);
1144 req_send_reply(req);
1147 /****************************************************************************
1149 ****************************************************************************/
1150 void reply_lseek(struct smbsrv_request *req)
1152 struct smb_seek *io;
1154 REQ_CHECK_WCT(req, 4);
1155 REQ_TALLOC(io, sizeof(*io));
1157 io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1158 io->in.mode = SVAL(req->in.vwv, VWV(1));
1159 io->in.offset = IVALS(req->in.vwv, VWV(2));
1161 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1162 req->async_states->send_fn = reply_lseek_send;
1163 req->async_states->private_data = io;
1166 req->async_states->status = ntvfs_seek(req, io);
1171 /****************************************************************************
1173 ****************************************************************************/
1174 void reply_flush(struct smbsrv_request *req)
1176 struct smb_flush *io;
1179 REQ_CHECK_WCT(req, 1);
1180 REQ_TALLOC(io, sizeof(*io));
1182 io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1184 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1185 req->async_states->send_fn = reply_simple_send;
1188 req->async_states->status = ntvfs_flush(req, io);
1194 /****************************************************************************
1195 Reply to a exit. This closes all files open by a smbpid
1196 ****************************************************************************/
1197 void reply_exit(struct smbsrv_request *req)
1200 struct smbsrv_tcon *tcon;
1201 REQ_CHECK_WCT(req, 0);
1203 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
1205 status = ntvfs_exit(req);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 req_reply_error(req, status);
1213 req_setup_reply(req, 0, 0);
1214 req_send_reply(req);
1218 /****************************************************************************
1221 Note that this has to deal with closing a directory opened by NT SMB's.
1222 ****************************************************************************/
1223 void reply_close(struct smbsrv_request *req)
1225 union smb_close *io;
1228 REQ_CHECK_WCT(req, 3);
1229 REQ_TALLOC(io, sizeof(*io));
1231 io->close.level = RAW_CLOSE_CLOSE;
1232 io->close.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1233 io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1235 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1236 req->async_states->send_fn = reply_simple_send;
1239 req->async_states->status = ntvfs_close(req, io);
1246 /****************************************************************************
1247 Reply to a writeclose (async reply)
1248 ****************************************************************************/
1249 static void reply_writeclose_send(struct smbsrv_request *req)
1251 union smb_write *io = req->async_states->private_data;
1255 /* construct reply */
1256 req_setup_reply(req, 1, 0);
1258 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1260 req_send_reply(req);
1263 /****************************************************************************
1264 Reply to a writeclose (Core+ protocol).
1265 ****************************************************************************/
1266 void reply_writeclose(struct smbsrv_request *req)
1268 union smb_write *io;
1270 /* this one is pretty weird - the wct can be 6 or 12 */
1271 if (req->in.wct != 12) {
1272 REQ_CHECK_WCT(req, 6);
1275 REQ_TALLOC(io, sizeof(*io));
1277 io->writeclose.level = RAW_WRITE_WRITECLOSE;
1278 io->writeclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1279 io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
1280 io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1281 io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1282 io->writeclose.in.data = req->in.data + 1;
1284 /* make sure they gave us the data they promised */
1285 if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1286 req_reply_error(req, NT_STATUS_FOOBAR);
1290 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1291 req->async_states->send_fn = reply_writeclose_send;
1292 req->async_states->private_data = io;
1295 req->async_states->status = ntvfs_write(req, io);
1300 /****************************************************************************
1302 ****************************************************************************/
1303 void reply_lock(struct smbsrv_request *req)
1305 union smb_lock *lck;
1308 REQ_CHECK_WCT(req, 5);
1309 REQ_TALLOC(lck, sizeof(*lck));
1311 lck->lock.level = RAW_LOCK_LOCK;
1312 lck->lock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1313 lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
1314 lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1316 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1317 req->async_states->send_fn = reply_simple_send;
1320 req->async_states->status = ntvfs_lock(req, lck);
1326 /****************************************************************************
1328 ****************************************************************************/
1329 void reply_unlock(struct smbsrv_request *req)
1331 union smb_lock *lck;
1334 REQ_CHECK_WCT(req, 5);
1335 REQ_TALLOC(lck, sizeof(*lck));
1337 lck->unlock.level = RAW_LOCK_UNLOCK;
1338 lck->unlock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1339 lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
1340 lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1342 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1343 req->async_states->send_fn = reply_simple_send;
1346 req->async_states->status = ntvfs_lock(req, lck);
1352 /****************************************************************************
1354 ****************************************************************************/
1355 void reply_tdis(struct smbsrv_request *req)
1357 REQ_CHECK_WCT(req, 0);
1359 if (req->tcon == NULL) {
1360 req_reply_error(req, NT_STATUS_INVALID_HANDLE);
1364 talloc_free(req->tcon);
1366 /* construct reply */
1367 req_setup_reply(req, 0, 0);
1369 req_send_reply(req);
1373 /****************************************************************************
1374 Reply to a echo. This is one of the few calls that is handled directly (the
1375 backends don't see it at all)
1376 ****************************************************************************/
1377 void reply_echo(struct smbsrv_request *req)
1382 REQ_CHECK_WCT(req, 0);
1384 count = SVAL(req->in.vwv, VWV(0));
1386 req_setup_reply(req, 1, req->in.data_size);
1388 memcpy(req->out.data, req->in.data, req->in.data_size);
1390 for (i=1; i <= count;i++) {
1391 struct smbsrv_request *this_req;
1394 this_req = req_setup_secondary(req);
1399 SSVAL(this_req->out.vwv, VWV(0), i);
1400 req_send_reply(this_req);
1406 /****************************************************************************
1407 Reply to a printopen (async reply)
1408 ****************************************************************************/
1409 static void reply_printopen_send(struct smbsrv_request *req)
1411 union smb_open *oi = req->async_states->private_data;
1415 /* construct reply */
1416 req_setup_reply(req, 1, 0);
1418 SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
1420 req_send_reply(req);
1423 /****************************************************************************
1424 Reply to a printopen.
1425 ****************************************************************************/
1426 void reply_printopen(struct smbsrv_request *req)
1431 REQ_CHECK_WCT(req, 2);
1432 REQ_TALLOC(oi, sizeof(*oi));
1434 oi->splopen.level = RAW_OPEN_SPLOPEN;
1435 oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1436 oi->splopen.in.mode = SVAL(req->in.vwv, VWV(1));
1438 req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1440 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1441 req->async_states->send_fn = reply_printopen_send;
1442 req->async_states->private_data = oi;
1445 req->async_states->status = ntvfs_openfile(req, oi);
1450 /****************************************************************************
1451 Reply to a printclose.
1452 ****************************************************************************/
1453 void reply_printclose(struct smbsrv_request *req)
1455 union smb_close *io;
1458 REQ_CHECK_WCT(req, 3);
1459 REQ_TALLOC(io, sizeof(*io));
1461 io->splclose.level = RAW_CLOSE_SPLCLOSE;
1462 io->splclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1464 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1465 req->async_states->send_fn = reply_simple_send;
1468 req->async_states->status = ntvfs_close(req, io);
1473 /****************************************************************************
1474 Reply to a printqueue.
1475 ****************************************************************************/
1476 void reply_printqueue_send(struct smbsrv_request *req)
1478 union smb_lpq *lpq = req->async_states->private_data;
1480 const uint_t el_size = 28;
1484 /* construct reply */
1485 req_setup_reply(req, 2, 0);
1487 /* truncate the returned list to fit in the negotiated buffer size */
1488 maxcount = (req_max_data(req) - 3) / el_size;
1489 if (maxcount < lpq->retq.out.count) {
1490 lpq->retq.out.count = maxcount;
1493 /* setup enough space in the reply */
1494 req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1496 /* and fill it in */
1497 SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1498 SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1500 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1501 SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1503 req->out.ptr = req->out.data + 3;
1505 for (i=0;i<lpq->retq.out.count;i++) {
1506 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1507 SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
1508 SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
1509 SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
1510 SCVAL(req->out.ptr, 11, 0); /* reserved */
1511 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1512 req->out.ptr += el_size;
1515 req_send_reply(req);
1518 /****************************************************************************
1519 Reply to a printqueue.
1520 ****************************************************************************/
1521 void reply_printqueue(struct smbsrv_request *req)
1526 REQ_CHECK_WCT(req, 2);
1527 REQ_TALLOC(lpq, sizeof(*lpq));
1529 lpq->retq.level = RAW_LPQ_RETQ;
1530 lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
1531 lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
1533 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1534 req->async_states->send_fn = reply_printqueue_send;
1535 req->async_states->private_data = lpq;
1538 req->async_states->status = ntvfs_lpq(req, lpq);
1544 /****************************************************************************
1545 Reply to a printwrite.
1546 ****************************************************************************/
1547 void reply_printwrite(struct smbsrv_request *req)
1549 union smb_write *io;
1552 REQ_CHECK_WCT(req, 1);
1553 REQ_TALLOC(io, sizeof(*io));
1555 io->splwrite.level = RAW_WRITE_SPLWRITE;
1557 if (req->in.data_size < 3) {
1558 req_reply_error(req, NT_STATUS_FOOBAR);
1562 io->splwrite.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1563 io->splwrite.in.count = SVAL(req->in.data, 1);
1564 io->splwrite.in.data = req->in.data + 3;
1566 /* make sure they gave us the data they promised */
1567 if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1568 req_reply_error(req, NT_STATUS_FOOBAR);
1572 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1573 req->async_states->send_fn = reply_simple_send;
1576 req->async_states->status = ntvfs_write(req, io);
1582 /****************************************************************************
1584 ****************************************************************************/
1585 void reply_mkdir(struct smbsrv_request *req)
1587 union smb_mkdir *io;
1589 /* parse the request */
1590 REQ_CHECK_WCT(req, 0);
1591 REQ_TALLOC(io, sizeof(*io));
1593 io->generic.level = RAW_MKDIR_MKDIR;
1594 req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1596 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1597 req->async_states->send_fn = reply_simple_send;
1600 req->async_states->status = ntvfs_mkdir(req, io);
1606 /****************************************************************************
1608 ****************************************************************************/
1609 void reply_rmdir(struct smbsrv_request *req)
1611 struct smb_rmdir *io;
1613 /* parse the request */
1614 REQ_CHECK_WCT(req, 0);
1615 REQ_TALLOC(io, sizeof(*io));
1617 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1619 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1620 req->async_states->send_fn = reply_simple_send;
1623 req->async_states->status = ntvfs_rmdir(req, io);
1629 /****************************************************************************
1631 ****************************************************************************/
1632 void reply_mv(struct smbsrv_request *req)
1634 union smb_rename *io;
1637 /* parse the request */
1638 REQ_CHECK_WCT(req, 1);
1639 REQ_TALLOC(io, sizeof(*io));
1641 io->generic.level = RAW_RENAME_RENAME;
1642 io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1645 p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1646 p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1648 if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1649 req_reply_error(req, NT_STATUS_FOOBAR);
1653 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1654 req->async_states->send_fn = reply_simple_send;
1657 req->async_states->status = ntvfs_rename(req, io);
1663 /****************************************************************************
1664 Reply to an NT rename.
1665 ****************************************************************************/
1666 void reply_ntrename(struct smbsrv_request *req)
1668 union smb_rename *io;
1671 /* parse the request */
1672 REQ_CHECK_WCT(req, 4);
1673 REQ_TALLOC(io, sizeof(*io));
1675 io->generic.level = RAW_RENAME_NTRENAME;
1676 io->ntrename.in.attrib = SVAL(req->in.vwv, VWV(0));
1677 io->ntrename.in.flags = SVAL(req->in.vwv, VWV(1));
1678 io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1681 p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1682 p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1684 if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1685 req_reply_error(req, NT_STATUS_FOOBAR);
1689 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1690 req->async_states->send_fn = reply_simple_send;
1693 req->async_states->status = ntvfs_rename(req, io);
1698 /****************************************************************************
1699 Reply to a file copy (async reply)
1700 ****************************************************************************/
1701 static void reply_copy_send(struct smbsrv_request *req)
1703 struct smb_copy *cp = req->async_states->private_data;
1707 /* build the reply */
1708 req_setup_reply(req, 1, 0);
1710 SSVAL(req->out.vwv, VWV(0), cp->out.count);
1712 req_send_reply(req);
1715 /****************************************************************************
1716 Reply to a file copy.
1717 ****************************************************************************/
1718 void reply_copy(struct smbsrv_request *req)
1720 struct smb_copy *cp;
1724 REQ_CHECK_WCT(req, 3);
1725 REQ_TALLOC(cp, sizeof(*cp));
1727 cp->in.tid2 = SVAL(req->in.vwv, VWV(0));
1728 cp->in.ofun = SVAL(req->in.vwv, VWV(1));
1729 cp->in.flags = SVAL(req->in.vwv, VWV(2));
1732 p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1733 p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1735 if (!cp->in.path1 || !cp->in.path2) {
1736 req_reply_error(req, NT_STATUS_FOOBAR);
1740 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1741 req->async_states->send_fn = reply_copy_send;
1742 req->async_states->private_data = cp;
1745 req->async_states->status = ntvfs_copy(req, cp);
1750 /****************************************************************************
1751 Reply to a lockingX request (async send)
1752 ****************************************************************************/
1753 static void reply_lockingX_send(struct smbsrv_request *req)
1755 union smb_lock *lck = req->async_states->private_data;
1759 /* if it was an oplock break ack then we only send a reply if
1760 there was an error */
1761 if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1766 /* construct reply */
1767 req_setup_reply(req, 2, 0);
1769 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1770 SSVAL(req->out.vwv, VWV(1), 0);
1776 /****************************************************************************
1777 Reply to a lockingX request.
1778 ****************************************************************************/
1779 void reply_lockingX(struct smbsrv_request *req)
1781 union smb_lock *lck;
1782 uint_t total_locks, i;
1787 REQ_CHECK_WCT(req, 8);
1788 REQ_TALLOC(lck, sizeof(*lck));
1790 lck->lockx.level = RAW_LOCK_LOCKX;
1791 lck->lockx.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
1792 lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
1793 lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
1794 lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1795 lck->lockx.in.lock_cnt = SVAL(req->in.vwv, VWV(7));
1797 total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1799 /* there are two variants, one with 64 bit offsets and counts */
1800 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1806 /* make sure we got the promised data */
1807 if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1808 req_reply_error(req, NT_STATUS_FOOBAR);
1812 /* allocate the locks array */
1814 REQ_TALLOC(lck->lockx.in.locks, total_locks * sizeof(lck->lockx.in.locks[0]));
1819 /* construct the locks array */
1820 for (i=0;i<total_locks;i++) {
1821 uint32_t ofs_high=0, count_high=0;
1823 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1825 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1826 ofs_high = IVAL(p, 4);
1827 lck->lockx.in.locks[i].offset = IVAL(p, 8);
1828 count_high = IVAL(p, 12);
1829 lck->lockx.in.locks[i].count = IVAL(p, 16);
1831 lck->lockx.in.locks[i].offset = IVAL(p, 2);
1832 lck->lockx.in.locks[i].count = IVAL(p, 6);
1834 if (ofs_high != 0 || count_high != 0) {
1835 lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32;
1836 lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1841 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1842 req->async_states->send_fn = reply_lockingX_send;
1843 req->async_states->private_data = lck;
1846 req->async_states->status = ntvfs_lock(req, lck);
1851 /****************************************************************************
1852 Reply to a SMBreadbmpx (read block multiplex) request.
1853 ****************************************************************************/
1854 void reply_readbmpx(struct smbsrv_request *req)
1856 /* tell the client to not use a multiplexed read - its too broken to use */
1857 req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1861 /****************************************************************************
1862 Reply to a SMBsetattrE.
1863 ****************************************************************************/
1864 void reply_setattrE(struct smbsrv_request *req)
1866 union smb_setfileinfo *info;
1869 REQ_CHECK_WCT(req, 7);
1870 REQ_TALLOC(info, sizeof(*info));
1872 info->setattre.level = RAW_SFILEINFO_SETATTRE;
1873 info->setattre.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1874 info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1875 info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1876 info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1878 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1879 req->async_states->send_fn = reply_simple_send;
1882 req->async_states->status = ntvfs_setfileinfo(req, info);
1888 /****************************************************************************
1889 Reply to a SMBwritebmpx (write block multiplex primary) request.
1890 ****************************************************************************/
1891 void reply_writebmpx(struct smbsrv_request *req)
1893 req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1897 /****************************************************************************
1898 Reply to a SMBwritebs (write block multiplex secondary) request.
1899 ****************************************************************************/
1900 void reply_writebs(struct smbsrv_request *req)
1902 req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1907 /****************************************************************************
1908 Reply to a SMBgetattrE (async reply)
1909 ****************************************************************************/
1910 static void reply_getattrE_send(struct smbsrv_request *req)
1912 union smb_fileinfo *info = req->async_states->private_data;
1917 req_setup_reply(req, 11, 0);
1919 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1920 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1921 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1922 SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
1923 SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
1924 SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
1926 req_send_reply(req);
1929 /****************************************************************************
1930 Reply to a SMBgetattrE.
1931 ****************************************************************************/
1932 void reply_getattrE(struct smbsrv_request *req)
1934 union smb_fileinfo *info;
1937 REQ_CHECK_WCT(req, 1);
1938 REQ_TALLOC(info, sizeof(*info));
1940 info->getattr.level = RAW_FILEINFO_GETATTRE;
1941 info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1943 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1944 req->async_states->send_fn = reply_getattrE_send;
1945 req->async_states->private_data = info;
1948 req->async_states->status = ntvfs_qfileinfo(req, info);
1954 /****************************************************************************
1955 reply to an old style session setup command
1956 ****************************************************************************/
1957 static void reply_sesssetup_old(struct smbsrv_request *req)
1960 union smb_sesssetup sess;
1964 sess.old.level = RAW_SESSSETUP_OLD;
1967 sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1968 sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1969 sess.old.in.vc_num = SVAL(req->in.vwv, VWV(4));
1970 sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1971 passlen = SVAL(req->in.vwv, VWV(7));
1973 /* check the request isn't malformed */
1974 if (req_data_oob(req, req->in.data, passlen)) {
1975 req_reply_error(req, NT_STATUS_FOOBAR);
1980 if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1981 req_reply_error(req, NT_STATUS_FOOBAR);
1986 p += req_pull_string(req, &sess.old.in.user, p, -1, STR_TERMINATE);
1987 p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1988 p += req_pull_string(req, &sess.old.in.os, p, -1, STR_TERMINATE);
1989 p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
1991 /* call the generic handler */
1992 status = sesssetup_backend(req, &sess);
1994 if (!NT_STATUS_IS_OK(status)) {
1995 req_reply_error(req, status);
1999 /* construct reply */
2000 req_setup_reply(req, 3, 0);
2002 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2003 SSVAL(req->out.vwv, VWV(1), 0);
2004 SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
2006 SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
2012 /****************************************************************************
2013 reply to an NT1 style session setup command
2014 ****************************************************************************/
2015 static void reply_sesssetup_nt1(struct smbsrv_request *req)
2018 union smb_sesssetup sess;
2020 uint16_t passlen1, passlen2;
2022 sess.nt1.level = RAW_SESSSETUP_NT1;
2025 sess.nt1.in.bufsize = SVAL(req->in.vwv, VWV(2));
2026 sess.nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2027 sess.nt1.in.vc_num = SVAL(req->in.vwv, VWV(4));
2028 sess.nt1.in.sesskey = IVAL(req->in.vwv, VWV(5));
2029 passlen1 = SVAL(req->in.vwv, VWV(7));
2030 passlen2 = SVAL(req->in.vwv, VWV(8));
2031 sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
2033 /* check the request isn't malformed */
2034 if (req_data_oob(req, req->in.data, passlen1) ||
2035 req_data_oob(req, req->in.data + passlen1, passlen2)) {
2036 req_reply_error(req, NT_STATUS_FOOBAR);
2041 if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
2042 req_reply_error(req, NT_STATUS_FOOBAR);
2046 if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
2047 req_reply_error(req, NT_STATUS_FOOBAR);
2052 p += req_pull_string(req, &sess.nt1.in.user, p, -1, STR_TERMINATE);
2053 p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
2054 p += req_pull_string(req, &sess.nt1.in.os, p, -1, STR_TERMINATE);
2055 p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
2057 /* call the generic handler */
2058 status = sesssetup_backend(req, &sess);
2060 if (!NT_STATUS_IS_OK(status)) {
2061 req_reply_error(req, status);
2065 /* construct reply */
2066 req_setup_reply(req, 3, 0);
2068 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2069 SSVAL(req->out.vwv, VWV(1), 0);
2070 SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
2072 SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
2074 req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
2075 req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
2076 req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
2082 /****************************************************************************
2083 reply to an SPNEGO style session setup command
2084 ****************************************************************************/
2085 static void reply_sesssetup_spnego(struct smbsrv_request *req)
2088 union smb_sesssetup sess;
2092 sess.spnego.level = RAW_SESSSETUP_SPNEGO;
2095 sess.spnego.in.bufsize = SVAL(req->in.vwv, VWV(2));
2096 sess.spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2097 sess.spnego.in.vc_num = SVAL(req->in.vwv, VWV(4));
2098 sess.spnego.in.sesskey = IVAL(req->in.vwv, VWV(5));
2099 blob_len = SVAL(req->in.vwv, VWV(7));
2100 sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
2103 if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
2104 req_reply_error(req, NT_STATUS_FOOBAR);
2109 p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE);
2110 p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE);
2111 p += req_pull_string(req, &sess.spnego.in.workgroup, p, -1, STR_TERMINATE);
2113 /* call the generic handler */
2114 status = sesssetup_backend(req, &sess);
2116 if (!NT_STATUS_IS_OK(status) &&
2117 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2118 req_reply_error(req, status);
2122 /* construct reply */
2123 req_setup_reply(req, 4, sess.spnego.out.secblob.length);
2125 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2126 req_setup_error(req, status);
2129 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2130 SSVAL(req->out.vwv, VWV(1), 0);
2131 SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
2132 SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
2134 SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
2136 memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
2137 req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
2138 req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
2139 req_push_str(req, NULL, sess.spnego.out.workgroup, -1, STR_TERMINATE);
2145 /****************************************************************************
2146 reply to a session setup command
2147 ****************************************************************************/
2148 void reply_sesssetup(struct smbsrv_request *req)
2150 switch (req->in.wct) {
2152 /* a pre-NT1 call */
2153 reply_sesssetup_old(req);
2157 reply_sesssetup_nt1(req);
2161 reply_sesssetup_spnego(req);
2165 /* unsupported variant */
2166 req_reply_error(req, NT_STATUS_FOOBAR);
2169 /****************************************************************************
2170 Reply to a SMBulogoffX.
2171 ****************************************************************************/
2172 void reply_ulogoffX(struct smbsrv_request *req)
2174 struct smbsrv_tcon *tcon;
2177 if (!req->session) {
2178 req_reply_error(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
2182 /* in user level security we are supposed to close any files
2183 open by this user on all open tree connects */
2184 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
2186 status = ntvfs_logoff(req);
2188 if (!NT_STATUS_IS_OK(status)) {
2189 req_reply_error(req, status);
2194 talloc_free(req->session);
2195 req->session = NULL; /* it is now invalid, don't use on
2196 any chained packets */
2198 req_setup_reply(req, 2, 0);
2200 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2201 SSVAL(req->out.vwv, VWV(1), 0);
2207 /****************************************************************************
2208 Reply to an SMBfindclose request
2209 ****************************************************************************/
2210 void reply_findclose(struct smbsrv_request *req)
2213 union smb_search_close io;
2215 io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2218 REQ_CHECK_WCT(req, 1);
2220 io.findclose.in.handle = SVAL(req->in.vwv, VWV(0));
2223 status = ntvfs_search_close(req, &io);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 req_reply_error(req, status);
2230 /* construct reply */
2231 req_setup_reply(req, 0, 0);
2233 req_send_reply(req);
2236 /****************************************************************************
2237 Reply to an SMBfindnclose request
2238 ****************************************************************************/
2239 void reply_findnclose(struct smbsrv_request *req)
2241 req_reply_error(req, NT_STATUS_FOOBAR);
2245 /****************************************************************************
2246 Reply to an SMBntcreateX request (async send)
2247 ****************************************************************************/
2248 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
2250 union smb_open *io = req->async_states->private_data;
2254 /* construct reply */
2255 req_setup_reply(req, 34, 0);
2257 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2258 SSVAL(req->out.vwv, VWV(1), 0);
2259 SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2261 /* the rest of the parameters are not aligned! */
2262 SSVAL(req->out.vwv, 5, io->ntcreatex.out.fnum);
2263 SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
2264 push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2265 push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2266 push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2267 push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2268 SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
2269 SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
2270 SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
2271 SSVAL(req->out.vwv, 63, io->ntcreatex.out.file_type);
2272 SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
2273 SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
2275 req->chained_fnum = io->ntcreatex.out.fnum;
2280 /****************************************************************************
2281 Reply to an SMBntcreateX request
2282 ****************************************************************************/
2283 void reply_ntcreate_and_X(struct smbsrv_request *req)
2288 /* parse the request */
2289 REQ_CHECK_WCT(req, 24);
2290 REQ_TALLOC(io, sizeof(*io));
2292 io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2294 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2295 fname_len = SVAL(req->in.vwv, 5);
2296 io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
2297 io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
2298 io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
2299 io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
2300 io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
2301 io->ntcreatex.in.share_access = IVAL(req->in.vwv, 31);
2302 io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2303 io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
2304 io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
2305 io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
2306 io->ntcreatex.in.ea_list = NULL;
2307 io->ntcreatex.in.sec_desc = NULL;
2309 /* we need a neater way to handle this alignment */
2310 if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
2311 ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2315 req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2316 if (!io->ntcreatex.in.fname) {
2317 req_reply_error(req, NT_STATUS_FOOBAR);
2321 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
2322 req->async_states->send_fn = reply_ntcreate_and_X_send;
2323 req->async_states->private_data = io;
2325 /* call the backend */
2326 req->async_states->status = ntvfs_openfile(req, io);
2332 /****************************************************************************
2333 Reply to an SMBntcancel request
2334 ****************************************************************************/
2335 void reply_ntcancel(struct smbsrv_request *req)
2337 /* NOTE: this request does not generate a reply */
2342 /****************************************************************************
2343 Reply to an SMBsends request
2344 ****************************************************************************/
2345 void reply_sends(struct smbsrv_request *req)
2347 req_reply_error(req, NT_STATUS_FOOBAR);
2350 /****************************************************************************
2351 Reply to an SMBsendstrt request
2352 ****************************************************************************/
2353 void reply_sendstrt(struct smbsrv_request *req)
2355 req_reply_error(req, NT_STATUS_FOOBAR);
2358 /****************************************************************************
2359 Reply to an SMBsendend request
2360 ****************************************************************************/
2361 void reply_sendend(struct smbsrv_request *req)
2363 req_reply_error(req, NT_STATUS_FOOBAR);
2366 /****************************************************************************
2367 Reply to an SMBsendtxt request
2368 ****************************************************************************/
2369 void reply_sendtxt(struct smbsrv_request *req)
2371 req_reply_error(req, NT_STATUS_FOOBAR);
2376 parse the called/calling names from session request
2378 static NTSTATUS parse_session_request(struct smbsrv_request *req)
2383 blob.data = req->in.buffer + 4;
2384 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2385 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2387 req->smb_conn->negotiate.called_name = talloc(req->smb_conn, struct nbt_name);
2388 req->smb_conn->negotiate.calling_name = talloc(req->smb_conn, struct nbt_name);
2389 if (req->smb_conn->negotiate.called_name == NULL ||
2390 req->smb_conn->negotiate.calling_name == NULL) {
2391 return NT_STATUS_NO_MEMORY;
2394 status = nbt_name_from_blob(req->smb_conn, &blob,
2395 req->smb_conn->negotiate.called_name);
2396 NT_STATUS_NOT_OK_RETURN(status);
2398 blob.data += blob.length;
2399 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2400 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2402 status = nbt_name_from_blob(req->smb_conn, &blob,
2403 req->smb_conn->negotiate.calling_name);
2404 NT_STATUS_NOT_OK_RETURN(status);
2406 req->smb_conn->negotiate.done_nbt_session = True;
2408 return NT_STATUS_OK;
2413 /****************************************************************************
2414 Reply to a special message - a SMB packet with non zero NBT message type
2415 ****************************************************************************/
2416 void reply_special(struct smbsrv_request *req)
2419 uint8_t *buf = talloc_zero_array(req, uint8_t, 4);
2421 msg_type = CVAL(req->in.buffer,0);
2426 case 0x81: /* session request */
2427 if (req->smb_conn->negotiate.done_nbt_session) {
2428 DEBUG(0,("Warning: ignoring secondary session request\n"));
2435 /* we don't check the status - samba always accepts session
2436 requests for any name */
2437 parse_session_request(req);
2439 req->out.buffer = buf;
2441 req_send_reply_nosign(req);
2444 case 0x89: /* session keepalive request
2445 (some old clients produce this?) */
2446 SCVAL(buf, 0, SMBkeepalive);
2448 req->out.buffer = buf;
2450 req_send_reply_nosign(req);
2454 /* session keepalive - swallow it */
2459 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));