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
28 /* useful way of catching wct errors with file and line number */
29 #define REQ_CHECK_WCT(req, wcount) do { \
30 if ((req)->in.wct != (wcount)) { \
31 DEBUG(1,("Unexpected WCT %d at %s(%d) - expected %d\n", \
32 (req)->in.wct, __FILE__, __LINE__, wcount)); \
33 req_reply_dos_error(req, ERRSRV, ERRerror); \
37 /* check req->async_states->status and if not OK then send an error reply */
38 #define CHECK_ASYNC_STATUS do { \
39 if (!NT_STATUS_IS_OK(req->async_states->status)) { \
40 req_reply_error(req, req->async_states->status); \
44 /* useful wrapper for talloc with NO_MEMORY reply */
45 #define REQ_TALLOC(ptr, size) do { \
46 ptr = talloc(req, size); \
48 req_reply_error(req, NT_STATUS_NO_MEMORY); \
53 check if the backend wants to handle the request asynchronously.
54 if it wants it handled synchronously then call the send function
57 #define REQ_ASYNC_TAIL do { \
58 if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
59 req->async_states->send_fn(req); \
62 /* zero out some reserved fields in a reply */
63 #define REQ_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)
65 /****************************************************************************
66 Reply to a simple request (async send)
67 ****************************************************************************/
68 static void reply_simple_send(struct smbsrv_request *req)
72 req_setup_reply(req, 0, 0);
77 /****************************************************************************
79 ****************************************************************************/
80 void reply_tcon(struct smbsrv_request *req)
87 REQ_CHECK_WCT(req, 0);
89 con.tcon.level = RAW_TCON_TCON;
92 p += req_pull_ascii4(req, &con.tcon.in.service, p, STR_TERMINATE);
93 p += req_pull_ascii4(req, &con.tcon.in.password, p, STR_TERMINATE);
94 p += req_pull_ascii4(req, &con.tcon.in.dev, p, STR_TERMINATE);
96 if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
97 req_reply_error(req, NT_STATUS_INVALID_PARAMETER);
102 status = tcon_backend(req, &con);
104 if (!NT_STATUS_IS_OK(status)) {
105 req_reply_error(req, status);
109 /* construct reply */
110 req_setup_reply(req, 2, 0);
112 SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
113 SSVAL(req->out.vwv, VWV(1), con.tcon.out.cnum);
114 SSVAL(req->out.hdr, HDR_TID, req->tcon->cnum);
120 /****************************************************************************
121 Reply to a tcon and X.
122 ****************************************************************************/
123 void reply_tcon_and_X(struct smbsrv_request *req)
130 con.tconx.level = RAW_TCON_TCONX;
133 REQ_CHECK_WCT(req, 4);
135 con.tconx.in.flags = SVAL(req->in.vwv, VWV(2));
136 passlen = SVAL(req->in.vwv, VWV(3));
140 if (!req_pull_blob(req, p, passlen, &con.tconx.in.password)) {
141 req_reply_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
146 p += req_pull_string(req, &con.tconx.in.path, p, -1, STR_TERMINATE);
147 p += req_pull_string(req, &con.tconx.in.device, p, -1, STR_ASCII);
149 if (!con.tconx.in.path || !con.tconx.in.device) {
150 req_reply_error(req, NT_STATUS_BAD_DEVICE_TYPE);
155 status = tcon_backend(req, &con);
157 if (!NT_STATUS_IS_OK(status)) {
158 req_reply_error(req, status);
162 /* construct reply - two variants */
163 if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
164 req_setup_reply(req, 2, 0);
166 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
167 SSVAL(req->out.vwv, VWV(1), 0);
169 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
171 req_setup_reply(req, 3, 0);
173 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
174 SSVAL(req->out.vwv, VWV(1), 0);
175 SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
177 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
178 req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
181 /* set the incoming and outgoing tid to the just created one */
182 SSVAL(req->in.hdr, HDR_TID, con.tconx.out.cnum);
183 SSVAL(req->out.hdr,HDR_TID, con.tconx.out.cnum);
189 /****************************************************************************
190 Reply to an unknown request
191 ****************************************************************************/
192 void reply_unknown(struct smbsrv_request *req)
196 type = CVAL(req->in.hdr, HDR_COM);
198 DEBUG(0,("unknown command type %d (0x%X)\n", type, type));
200 req_reply_dos_error(req, ERRSRV, ERRunknownsmb);
204 /****************************************************************************
205 Reply to an ioctl (async reply)
206 ****************************************************************************/
207 static void reply_ioctl_send(struct smbsrv_request *req)
209 union smb_ioctl *io = req->async_states->private_data;
213 /* the +1 is for nicer alignment */
214 req_setup_reply(req, 8, io->ioctl.out.blob.length+1);
215 SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length);
216 SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length);
217 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1);
219 memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length);
224 /****************************************************************************
226 ****************************************************************************/
227 void reply_ioctl(struct smbsrv_request *req)
232 REQ_CHECK_WCT(req, 3);
233 REQ_TALLOC(io, sizeof(*io));
235 io->ioctl.level = RAW_IOCTL_IOCTL;
236 io->ioctl.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
237 io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
239 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
240 req->async_states->send_fn = reply_ioctl_send;
241 req->async_states->private_data = io;
244 req->async_states->status = ntvfs_ioctl(req, io);
250 /****************************************************************************
252 ****************************************************************************/
253 void reply_chkpth(struct smbsrv_request *req)
255 struct smb_chkpath *io;
257 REQ_TALLOC(io, sizeof(*io));
259 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
261 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
262 req->async_states->send_fn = reply_simple_send;
264 req->async_states->status = ntvfs_chkpath(req, io);
269 /****************************************************************************
270 Reply to a getatr (async reply)
271 ****************************************************************************/
272 static void reply_getatr_send(struct smbsrv_request *req)
274 union smb_fileinfo *st = req->async_states->private_data;
278 /* construct reply */
279 req_setup_reply(req, 10, 0);
281 SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib);
282 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
283 SIVAL(req->out.vwv, VWV(3), st->getattr.out.size);
285 REQ_VWV_RESERVED(5, 5);
291 /****************************************************************************
293 ****************************************************************************/
294 void reply_getatr(struct smbsrv_request *req)
296 union smb_fileinfo *st;
298 REQ_TALLOC(st, sizeof(*st));
300 st->getattr.level = RAW_FILEINFO_GETATTR;
303 req_pull_ascii4(req, &st->getattr.in.fname, req->in.data, STR_TERMINATE);
304 if (!st->getattr.in.fname) {
305 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
309 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
310 req->async_states->send_fn = reply_getatr_send;
311 req->async_states->private_data = st;
314 req->async_states->status = ntvfs_qpathinfo(req, st);
320 /****************************************************************************
322 ****************************************************************************/
323 void reply_setatr(struct smbsrv_request *req)
325 union smb_setfileinfo *st;
328 REQ_CHECK_WCT(req, 8);
329 REQ_TALLOC(st, sizeof(*st));
331 st->setattr.level = RAW_SFILEINFO_SETATTR;
332 st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0));
333 st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
335 req_pull_ascii4(req, &st->setattr.file.fname, req->in.data, STR_TERMINATE);
337 if (!st->setattr.file.fname) {
338 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
342 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
343 req->async_states->send_fn = reply_simple_send;
346 req->async_states->status = ntvfs_setpathinfo(req, st);
352 /****************************************************************************
353 Reply to a dskattr (async reply)
354 ****************************************************************************/
355 static void reply_dskattr_send(struct smbsrv_request *req)
357 union smb_fsinfo *fs = req->async_states->private_data;
361 /* construct reply */
362 req_setup_reply(req, 5, 0);
364 SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total);
365 SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit);
366 SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size);
367 SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free);
369 REQ_VWV_RESERVED(4, 1);
375 /****************************************************************************
377 ****************************************************************************/
378 void reply_dskattr(struct smbsrv_request *req)
380 union smb_fsinfo *fs;
382 REQ_TALLOC(fs, sizeof(*fs));
384 fs->dskattr.level = RAW_QFS_DSKATTR;
386 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
387 req->async_states->send_fn = reply_dskattr_send;
388 req->async_states->private_data = fs;
391 req->async_states->status = ntvfs_fsinfo(req, fs);
398 /****************************************************************************
399 Reply to an open (async reply)
400 ****************************************************************************/
401 static void reply_open_send(struct smbsrv_request *req)
403 union smb_open *oi = req->async_states->private_data;
407 /* construct reply */
408 req_setup_reply(req, 7, 0);
410 SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
411 SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
412 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
413 SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
414 SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
419 /****************************************************************************
421 ****************************************************************************/
422 void reply_open(struct smbsrv_request *req)
427 REQ_CHECK_WCT(req, 2);
428 REQ_TALLOC(oi, sizeof(*oi));
430 oi->openold.level = RAW_OPEN_OPEN;
431 oi->openold.in.flags = SVAL(req->in.vwv, VWV(0));
432 oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
434 req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
436 if (!oi->openold.in.fname) {
437 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
441 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
442 req->async_states->send_fn = reply_open_send;
443 req->async_states->private_data = oi;
446 req->async_states->status = ntvfs_open(req, oi);
452 /****************************************************************************
453 Reply to an open and X (async reply)
454 ****************************************************************************/
455 static void reply_open_and_X_send(struct smbsrv_request *req)
457 union smb_open *oi = req->async_states->private_data;
461 /* build the reply */
462 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
463 req_setup_reply(req, 19, 0);
465 req_setup_reply(req, 15, 0);
468 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
469 SSVAL(req->out.vwv, VWV(1), 0);
470 SSVAL(req->out.vwv, VWV(2), oi->openx.out.fnum);
471 SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
472 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
473 SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
474 SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
475 SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
476 SSVAL(req->out.vwv, VWV(10),oi->openx.out.devstate);
477 SSVAL(req->out.vwv, VWV(11),oi->openx.out.action);
478 SIVAL(req->out.vwv, VWV(12),oi->openx.out.unique_fid);
479 SSVAL(req->out.vwv, VWV(14),0); /* reserved */
480 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
481 SIVAL(req->out.vwv, VWV(15),oi->openx.out.access_mask);
482 REQ_VWV_RESERVED(17, 2);
489 /****************************************************************************
490 Reply to an open and X.
491 ****************************************************************************/
492 void reply_open_and_X(struct smbsrv_request *req)
496 /* parse the request */
497 REQ_CHECK_WCT(req, 15);
498 REQ_TALLOC(oi, sizeof(*oi));
500 oi->openx.level = RAW_OPEN_OPENX;
501 oi->openx.in.flags = SVAL(req->in.vwv, VWV(2));
502 oi->openx.in.open_mode = SVAL(req->in.vwv, VWV(3));
503 oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
504 oi->openx.in.file_attrs = SVAL(req->in.vwv, VWV(5));
505 oi->openx.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
506 oi->openx.in.open_func = SVAL(req->in.vwv, VWV(8));
507 oi->openx.in.size = IVAL(req->in.vwv, VWV(9));
508 oi->openx.in.timeout = IVAL(req->in.vwv, VWV(11));
510 req_pull_ascii4(req, &oi->openx.in.fname, req->in.data, STR_TERMINATE);
512 if (!oi->openx.in.fname) {
513 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
517 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
518 req->async_states->send_fn = reply_open_and_X_send;
519 req->async_states->private_data = oi;
521 /* call the backend */
522 req->async_states->status = ntvfs_open(req, oi);
528 /****************************************************************************
529 Reply to a mknew or a create.
530 ****************************************************************************/
531 static void reply_mknew_send(struct smbsrv_request *req)
533 union smb_open *oi = req->async_states->private_data;
537 /* build the reply */
538 req_setup_reply(req, 1, 0);
540 SSVAL(req->out.vwv, VWV(0), oi->mknew.out.fnum);
546 /****************************************************************************
547 Reply to a mknew or a create.
548 ****************************************************************************/
549 void reply_mknew(struct smbsrv_request *req)
553 /* parse the request */
554 REQ_CHECK_WCT(req, 3);
555 REQ_TALLOC(oi, sizeof(*oi));
557 oi->mknew.level = RAW_OPEN_MKNEW;
558 oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0));
559 oi->mknew.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
561 req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
563 if (!oi->mknew.in.fname) {
564 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
568 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
569 req->async_states->send_fn = reply_mknew_send;
570 req->async_states->private_data = oi;
572 /* call the backend */
573 req->async_states->status = ntvfs_open(req, oi);
578 /****************************************************************************
579 Reply to a create temporary file (async reply)
580 ****************************************************************************/
581 static void reply_ctemp_send(struct smbsrv_request *req)
583 union smb_open *oi = req->async_states->private_data;
587 /* build the reply */
588 req_setup_reply(req, 1, 0);
590 SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.fnum);
592 /* the returned filename is relative to the directory */
593 req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE);
598 /****************************************************************************
599 Reply to a create temporary file.
600 ****************************************************************************/
601 void reply_ctemp(struct smbsrv_request *req)
605 /* parse the request */
606 REQ_CHECK_WCT(req, 3);
607 REQ_TALLOC(oi, sizeof(*oi));
609 oi->ctemp.level = RAW_OPEN_CTEMP;
610 oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
611 oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
613 /* the filename is actually a directory name, the server provides a filename
615 req_pull_ascii4(req, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
617 if (!oi->ctemp.in.directory) {
618 req_reply_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
622 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
623 req->async_states->send_fn = reply_ctemp_send;
624 req->async_states->private_data = oi;
626 /* call the backend */
627 req->async_states->status = ntvfs_open(req, oi);
633 /****************************************************************************
635 ****************************************************************************/
636 void reply_unlink(struct smbsrv_request *req)
638 struct smb_unlink *unl;
640 /* parse the request */
641 REQ_CHECK_WCT(req, 1);
642 REQ_TALLOC(unl, sizeof(*unl));
644 unl->in.attrib = SVAL(req->in.vwv, VWV(0));
646 req_pull_ascii4(req, &unl->in.pattern, req->in.data, STR_TERMINATE);
648 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
649 req->async_states->send_fn = reply_simple_send;
652 req->async_states->status = ntvfs_unlink(req, unl);
658 /****************************************************************************
659 Reply to a readbraw (core+ protocol).
660 this is a strange packet because it doesn't use a standard SMB header in the reply,
661 only the 4 byte NBT header
662 This command must be replied to synchronously
663 ****************************************************************************/
664 void reply_readbraw(struct smbsrv_request *req)
669 io.readbraw.level = RAW_READ_READBRAW;
671 /* there are two variants, one with 10 and one with 8 command words */
672 if (req->in.wct < 8) {
676 io.readbraw.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
677 io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
678 io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3));
679 io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4));
680 io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
682 /* the 64 bit variant */
683 if (req->in.wct == 10) {
684 uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
685 io.readbraw.in.offset |= (((off_t)offset_high) << 32);
688 /* before calling the backend we setup the raw buffer. This
689 * saves a copy later */
690 req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
691 req->out.buffer = talloc(req, req->out.size);
692 if (req->out.buffer == NULL) {
695 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
697 /* tell the backend where to put the data */
698 io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
700 /* call the backend */
701 status = ntvfs_read(req, &io);
703 if (!NT_STATUS_IS_OK(status)) {
707 req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
709 req_send_reply_nosign(req);
713 /* any failure in readbraw is equivalent to reading zero bytes */
715 req->out.buffer = talloc(req, req->out.size);
716 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
718 req_send_reply_nosign(req);
722 /****************************************************************************
723 Reply to a lockread (async reply)
724 ****************************************************************************/
725 static void reply_lockread_send(struct smbsrv_request *req)
727 union smb_read *io = req->async_states->private_data;
732 io->lockread.out.nread = MIN(io->lockread.out.nread,
733 req_max_data(req) - 3);
734 req_grow_data(req, 3 + io->lockread.out.nread);
736 /* construct reply */
737 SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
738 REQ_VWV_RESERVED(1, 4);
740 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
741 SSVAL(req->out.data, 1, io->lockread.out.nread);
747 /****************************************************************************
748 Reply to a lockread (core+ protocol).
749 note that the lock is a write lock, not a read lock!
750 ****************************************************************************/
751 void reply_lockread(struct smbsrv_request *req)
756 REQ_CHECK_WCT(req, 5);
757 REQ_TALLOC(io, sizeof(*io));
759 io->lockread.level = RAW_READ_LOCKREAD;
760 io->lockread.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
761 io->lockread.in.count = SVAL(req->in.vwv, VWV(1));
762 io->lockread.in.offset = IVAL(req->in.vwv, VWV(2));
763 io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
765 /* setup the reply packet assuming the maximum possible read */
766 req_setup_reply(req, 5, 3 + io->lockread.in.count);
768 /* tell the backend where to put the data */
769 io->lockread.out.data = req->out.data + 3;
771 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
772 req->async_states->send_fn = reply_lockread_send;
773 req->async_states->private_data = io;
776 req->async_states->status = ntvfs_read(req, io);
783 /****************************************************************************
784 Reply to a read (async reply)
785 ****************************************************************************/
786 static void reply_read_send(struct smbsrv_request *req)
788 union smb_read *io = req->async_states->private_data;
793 io->read.out.nread = MIN(io->read.out.nread,
794 req_max_data(req) - 3);
795 req_grow_data(req, 3 + io->read.out.nread);
797 /* construct reply */
798 SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
799 REQ_VWV_RESERVED(1, 4);
801 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
802 SSVAL(req->out.data, 1, io->read.out.nread);
807 /****************************************************************************
809 ****************************************************************************/
810 void reply_read(struct smbsrv_request *req)
815 REQ_CHECK_WCT(req, 5);
816 REQ_TALLOC(io, sizeof(*io));
818 io->read.level = RAW_READ_READ;
819 io->read.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
820 io->read.in.count = SVAL(req->in.vwv, VWV(1));
821 io->read.in.offset = IVAL(req->in.vwv, VWV(2));
822 io->read.in.remaining = SVAL(req->in.vwv, VWV(4));
824 /* setup the reply packet assuming the maximum possible read */
825 req_setup_reply(req, 5, 3 + io->read.in.count);
827 /* tell the backend where to put the data */
828 io->read.out.data = req->out.data + 3;
830 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
831 req->async_states->send_fn = reply_read_send;
832 req->async_states->private_data = io;
835 req->async_states->status = ntvfs_read(req, io);
842 /****************************************************************************
843 Reply to a read and X (async reply)
844 ****************************************************************************/
845 static void reply_read_and_X_send(struct smbsrv_request *req)
847 union smb_read *io = req->async_states->private_data;
851 /* readx reply packets can be over-sized */
852 req->control_flags |= REQ_CONTROL_LARGE;
853 if (io->readx.in.maxcnt != 0xFFFF &&
854 io->readx.in.mincnt != 0xFFFF) {
855 req_grow_data(req, 1 + io->readx.out.nread);
856 SCVAL(req->out.data, 0, 0); /* padding */
858 req_grow_data(req, io->readx.out.nread);
861 /* construct reply */
862 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
863 SSVAL(req->out.vwv, VWV(1), 0);
864 SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
865 SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
866 REQ_VWV_RESERVED(4, 1);
867 SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
868 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
869 REQ_VWV_RESERVED(7, 5);
874 /****************************************************************************
875 Reply to a read and X.
876 ****************************************************************************/
877 void reply_read_and_X(struct smbsrv_request *req)
882 if (req->in.wct != 12) {
883 REQ_CHECK_WCT(req, 10);
886 REQ_TALLOC(io, sizeof(*io));
888 io->readx.level = RAW_READ_READX;
889 io->readx.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
890 io->readx.in.offset = IVAL(req->in.vwv, VWV(3));
891 io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
892 io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
893 io->readx.in.maxcnt |= IVAL(req->in.vwv, VWV(7)) << 16;
894 io->readx.in.remaining = SVAL(req->in.vwv, VWV(9));
896 /* the 64 bit variant */
897 if (req->in.wct == 12) {
898 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
899 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
902 /* setup the reply packet assuming the maximum possible read */
903 req_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
905 /* tell the backend where to put the data. Notice the pad byte. */
906 if (io->readx.in.maxcnt != 0xFFFF &&
907 io->readx.in.mincnt != 0xFFFF) {
908 io->readx.out.data = req->out.data + 1;
910 io->readx.out.data = req->out.data;
913 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
914 req->async_states->send_fn = reply_read_and_X_send;
915 req->async_states->private_data = io;
918 req->async_states->status = ntvfs_read(req, io);
924 /****************************************************************************
925 Reply to a writebraw (core+ or LANMAN1.0 protocol).
926 ****************************************************************************/
927 void reply_writebraw(struct smbsrv_request *req)
929 /* this one is damn complex - put it off for now */
930 req_reply_error(req, NT_STATUS_FOOBAR);
934 /****************************************************************************
935 Reply to a writeunlock (async reply)
936 ****************************************************************************/
937 static void reply_writeunlock_send(struct smbsrv_request *req)
939 union smb_write *io = req->async_states->private_data;
943 /* construct reply */
944 req_setup_reply(req, 1, 0);
946 SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
951 /****************************************************************************
952 Reply to a writeunlock (core+).
953 ****************************************************************************/
954 void reply_writeunlock(struct smbsrv_request *req)
958 REQ_CHECK_WCT(req, 5);
959 REQ_TALLOC(io, sizeof(*io));
961 io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
962 io->writeunlock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
963 io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
964 io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
965 io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
966 io->writeunlock.in.data = req->in.data + 3;
968 /* make sure they gave us the data they promised */
969 if (io->writeunlock.in.count+3 > req->in.data_size) {
970 req_reply_error(req, NT_STATUS_FOOBAR);
974 /* make sure the data block is big enough */
975 if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
976 req_reply_error(req, NT_STATUS_FOOBAR);
980 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
981 req->async_states->send_fn = reply_writeunlock_send;
982 req->async_states->private_data = io;
985 req->async_states->status = ntvfs_write(req, io);
992 /****************************************************************************
993 Reply to a write (async reply)
994 ****************************************************************************/
995 static void reply_write_send(struct smbsrv_request *req)
997 union smb_write *io = req->async_states->private_data;
1001 /* construct reply */
1002 req_setup_reply(req, 1, 0);
1004 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1006 req_send_reply(req);
1009 /****************************************************************************
1011 ****************************************************************************/
1012 void reply_write(struct smbsrv_request *req)
1014 union smb_write *io;
1016 REQ_CHECK_WCT(req, 5);
1017 REQ_TALLOC(io, sizeof(*io));
1019 io->write.level = RAW_WRITE_WRITE;
1020 io->write.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1021 io->write.in.count = SVAL(req->in.vwv, VWV(1));
1022 io->write.in.offset = IVAL(req->in.vwv, VWV(2));
1023 io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
1024 io->write.in.data = req->in.data + 3;
1026 /* make sure they gave us the data they promised */
1027 if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
1028 req_reply_error(req, NT_STATUS_FOOBAR);
1032 /* make sure the data block is big enough */
1033 if (SVAL(req->in.data, 1) < io->write.in.count) {
1034 req_reply_error(req, NT_STATUS_FOOBAR);
1038 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1039 req->async_states->send_fn = reply_write_send;
1040 req->async_states->private_data = io;
1043 req->async_states->status = ntvfs_write(req, io);
1049 /****************************************************************************
1050 Reply to a write and X (async reply)
1051 ****************************************************************************/
1052 static void reply_write_and_X_send(struct smbsrv_request *req)
1054 union smb_write *io = req->async_states->private_data;
1058 /* construct reply */
1059 req_setup_reply(req, 6, 0);
1061 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1062 SSVAL(req->out.vwv, VWV(1), 0);
1063 SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
1064 SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
1065 SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
1066 REQ_VWV_RESERVED(5, 1);
1071 /****************************************************************************
1072 Reply to a write and X.
1073 ****************************************************************************/
1074 void reply_write_and_X(struct smbsrv_request *req)
1076 union smb_write *io;
1078 if (req->in.wct != 14) {
1079 REQ_CHECK_WCT(req, 12);
1082 REQ_TALLOC(io, sizeof(*io));
1084 io->writex.level = RAW_WRITE_WRITEX;
1085 io->writex.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
1086 io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
1087 io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
1088 io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1089 io->writex.in.count = SVAL(req->in.vwv, VWV(10));
1090 io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1092 if (req->in.wct == 14) {
1093 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1094 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1095 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1096 io->writex.in.count |= ((uint32_t)count_high) << 16;
1099 /* make sure the data is in bounds */
1100 if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1101 req_reply_error(req, NT_STATUS_FOOBAR);
1105 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1106 req->async_states->send_fn = reply_write_and_X_send;
1107 req->async_states->private_data = io;
1110 req->async_states->status = ntvfs_write(req, io);
1116 /****************************************************************************
1117 Reply to a lseek (async reply)
1118 ****************************************************************************/
1119 static void reply_lseek_send(struct smbsrv_request *req)
1121 struct smb_seek *io = req->async_states->private_data;
1125 /* construct reply */
1126 req_setup_reply(req, 2, 0);
1128 SIVALS(req->out.vwv, VWV(0), io->out.offset);
1130 req_send_reply(req);
1133 /****************************************************************************
1135 ****************************************************************************/
1136 void reply_lseek(struct smbsrv_request *req)
1138 struct smb_seek *io;
1140 REQ_CHECK_WCT(req, 4);
1141 REQ_TALLOC(io, sizeof(*io));
1143 io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1144 io->in.mode = SVAL(req->in.vwv, VWV(1));
1145 io->in.offset = IVALS(req->in.vwv, VWV(2));
1147 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1148 req->async_states->send_fn = reply_lseek_send;
1149 req->async_states->private_data = io;
1152 req->async_states->status = ntvfs_seek(req, io);
1157 /****************************************************************************
1159 ****************************************************************************/
1160 void reply_flush(struct smbsrv_request *req)
1162 struct smb_flush *io;
1165 REQ_CHECK_WCT(req, 1);
1166 REQ_TALLOC(io, sizeof(*io));
1168 io->in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1170 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1171 req->async_states->send_fn = reply_simple_send;
1174 req->async_states->status = ntvfs_flush(req, io);
1180 /****************************************************************************
1181 Reply to a exit. This closes all files open by a smbpid
1182 ****************************************************************************/
1183 void reply_exit(struct smbsrv_request *req)
1186 struct smbsrv_tcon *tcon;
1187 REQ_CHECK_WCT(req, 0);
1189 for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
1191 status = ntvfs_exit(req);
1193 if (!NT_STATUS_IS_OK(status)) {
1194 req_reply_error(req, status);
1199 req_setup_reply(req, 0, 0);
1200 req_send_reply(req);
1204 /****************************************************************************
1207 Note that this has to deal with closing a directory opened by NT SMB's.
1208 ****************************************************************************/
1209 void reply_close(struct smbsrv_request *req)
1211 union smb_close *io;
1214 REQ_CHECK_WCT(req, 3);
1215 REQ_TALLOC(io, sizeof(*io));
1217 io->close.level = RAW_CLOSE_CLOSE;
1218 io->close.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1219 io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1221 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1222 req->async_states->send_fn = reply_simple_send;
1225 req->async_states->status = ntvfs_close(req, io);
1232 /****************************************************************************
1233 Reply to a writeclose (async reply)
1234 ****************************************************************************/
1235 static void reply_writeclose_send(struct smbsrv_request *req)
1237 union smb_write *io = req->async_states->private_data;
1241 /* construct reply */
1242 req_setup_reply(req, 1, 0);
1244 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1246 req_send_reply(req);
1249 /****************************************************************************
1250 Reply to a writeclose (Core+ protocol).
1251 ****************************************************************************/
1252 void reply_writeclose(struct smbsrv_request *req)
1254 union smb_write *io;
1256 /* this one is pretty weird - the wct can be 6 or 12 */
1257 if (req->in.wct != 12) {
1258 REQ_CHECK_WCT(req, 6);
1261 REQ_TALLOC(io, sizeof(*io));
1263 io->writeclose.level = RAW_WRITE_WRITECLOSE;
1264 io->writeclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1265 io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
1266 io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1267 io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1268 io->writeclose.in.data = req->in.data + 1;
1270 /* make sure they gave us the data they promised */
1271 if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1272 req_reply_error(req, NT_STATUS_FOOBAR);
1276 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1277 req->async_states->send_fn = reply_writeclose_send;
1278 req->async_states->private_data = io;
1281 req->async_states->status = ntvfs_write(req, io);
1286 /****************************************************************************
1288 ****************************************************************************/
1289 void reply_lock(struct smbsrv_request *req)
1291 union smb_lock *lck;
1294 REQ_CHECK_WCT(req, 5);
1295 REQ_TALLOC(lck, sizeof(*lck));
1297 lck->lock.level = RAW_LOCK_LOCK;
1298 lck->lock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1299 lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
1300 lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1302 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1303 req->async_states->send_fn = reply_simple_send;
1306 req->async_states->status = ntvfs_lock(req, lck);
1312 /****************************************************************************
1314 ****************************************************************************/
1315 void reply_unlock(struct smbsrv_request *req)
1317 union smb_lock *lck;
1320 REQ_CHECK_WCT(req, 5);
1321 REQ_TALLOC(lck, sizeof(*lck));
1323 lck->unlock.level = RAW_LOCK_UNLOCK;
1324 lck->unlock.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1325 lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
1326 lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1328 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1329 req->async_states->send_fn = reply_simple_send;
1332 req->async_states->status = ntvfs_lock(req, lck);
1338 /****************************************************************************
1340 ****************************************************************************/
1341 void reply_tdis(struct smbsrv_request *req)
1343 REQ_CHECK_WCT(req, 0);
1345 close_cnum(req->tcon);
1347 /* construct reply */
1348 req_setup_reply(req, 0, 0);
1350 req_send_reply(req);
1354 /****************************************************************************
1355 Reply to a echo. This is one of the few calls that is handled directly (the
1356 backends don't see it at all)
1357 ****************************************************************************/
1358 void reply_echo(struct smbsrv_request *req)
1363 REQ_CHECK_WCT(req, 0);
1365 count = SVAL(req->in.vwv, VWV(0));
1367 req_setup_reply(req, 1, req->in.data_size);
1369 memcpy(req->out.data, req->in.data, req->in.data_size);
1371 for (i=1; i <= count;i++) {
1372 struct smbsrv_request *this_req;
1375 this_req = req_setup_secondary(req);
1380 SSVAL(this_req->out.vwv, VWV(0), i);
1381 req_send_reply(this_req);
1387 /****************************************************************************
1388 Reply to a printopen (async reply)
1389 ****************************************************************************/
1390 static void reply_printopen_send(struct smbsrv_request *req)
1392 union smb_open *oi = req->async_states->private_data;
1396 /* construct reply */
1397 req_setup_reply(req, 1, 0);
1399 SSVAL(req->out.vwv, VWV(0), oi->openold.out.fnum);
1401 req_send_reply(req);
1404 /****************************************************************************
1405 Reply to a printopen.
1406 ****************************************************************************/
1407 void reply_printopen(struct smbsrv_request *req)
1412 REQ_CHECK_WCT(req, 2);
1413 REQ_TALLOC(oi, sizeof(*oi));
1415 oi->splopen.level = RAW_OPEN_SPLOPEN;
1416 oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1417 oi->splopen.in.mode = SVAL(req->in.vwv, VWV(1));
1419 req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1421 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1422 req->async_states->send_fn = reply_printopen_send;
1423 req->async_states->private_data = oi;
1426 req->async_states->status = ntvfs_open(req, oi);
1431 /****************************************************************************
1432 Reply to a printclose.
1433 ****************************************************************************/
1434 void reply_printclose(struct smbsrv_request *req)
1436 union smb_close *io;
1439 REQ_CHECK_WCT(req, 3);
1440 REQ_TALLOC(io, sizeof(*io));
1442 io->splclose.level = RAW_CLOSE_SPLCLOSE;
1443 io->splclose.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1445 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1446 req->async_states->send_fn = reply_simple_send;
1449 req->async_states->status = ntvfs_close(req, io);
1454 /****************************************************************************
1455 Reply to a printqueue.
1456 ****************************************************************************/
1457 void reply_printqueue_send(struct smbsrv_request *req)
1459 union smb_lpq *lpq = req->async_states->private_data;
1461 const uint_t el_size = 28;
1465 /* construct reply */
1466 req_setup_reply(req, 2, 0);
1468 /* truncate the returned list to fit in the negotiated buffer size */
1469 maxcount = (req_max_data(req) - 3) / el_size;
1470 if (maxcount < lpq->retq.out.count) {
1471 lpq->retq.out.count = maxcount;
1474 /* setup enough space in the reply */
1475 req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1477 /* and fill it in */
1478 SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1479 SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1481 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1482 SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1484 req->out.ptr = req->out.data + 3;
1486 for (i=0;i<lpq->retq.out.count;i++) {
1487 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1488 SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
1489 SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
1490 SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
1491 SCVAL(req->out.ptr, 11, 0); /* reserved */
1492 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1493 req->out.ptr += el_size;
1496 req_send_reply(req);
1499 /****************************************************************************
1500 Reply to a printqueue.
1501 ****************************************************************************/
1502 void reply_printqueue(struct smbsrv_request *req)
1507 REQ_CHECK_WCT(req, 2);
1508 REQ_TALLOC(lpq, sizeof(*lpq));
1510 lpq->retq.level = RAW_LPQ_RETQ;
1511 lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
1512 lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
1514 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1515 req->async_states->send_fn = reply_printqueue_send;
1516 req->async_states->private_data = lpq;
1519 req->async_states->status = ntvfs_lpq(req, lpq);
1525 /****************************************************************************
1526 Reply to a printwrite.
1527 ****************************************************************************/
1528 void reply_printwrite(struct smbsrv_request *req)
1530 union smb_write *io;
1533 REQ_CHECK_WCT(req, 1);
1534 REQ_TALLOC(io, sizeof(*io));
1536 io->splwrite.level = RAW_WRITE_SPLWRITE;
1538 if (req->in.data_size < 3) {
1539 req_reply_error(req, NT_STATUS_FOOBAR);
1543 io->splwrite.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1544 io->splwrite.in.count = SVAL(req->in.data, 1);
1545 io->splwrite.in.data = req->in.data + 3;
1547 /* make sure they gave us the data they promised */
1548 if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1549 req_reply_error(req, NT_STATUS_FOOBAR);
1553 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1554 req->async_states->send_fn = reply_simple_send;
1557 req->async_states->status = ntvfs_write(req, io);
1563 /****************************************************************************
1565 ****************************************************************************/
1566 void reply_mkdir(struct smbsrv_request *req)
1568 union smb_mkdir *io;
1570 /* parse the request */
1571 REQ_CHECK_WCT(req, 0);
1572 REQ_TALLOC(io, sizeof(*io));
1574 io->generic.level = RAW_MKDIR_MKDIR;
1575 req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1577 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1578 req->async_states->send_fn = reply_simple_send;
1581 req->async_states->status = ntvfs_mkdir(req, io);
1587 /****************************************************************************
1589 ****************************************************************************/
1590 void reply_rmdir(struct smbsrv_request *req)
1592 struct smb_rmdir *io;
1594 /* parse the request */
1595 REQ_CHECK_WCT(req, 0);
1596 REQ_TALLOC(io, sizeof(*io));
1598 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1600 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1601 req->async_states->send_fn = reply_simple_send;
1604 req->async_states->status = ntvfs_rmdir(req, io);
1610 /****************************************************************************
1612 ****************************************************************************/
1613 void reply_mv(struct smbsrv_request *req)
1615 union smb_rename *io;
1618 /* parse the request */
1619 REQ_CHECK_WCT(req, 1);
1620 REQ_TALLOC(io, sizeof(*io));
1622 io->generic.level = RAW_RENAME_RENAME;
1623 io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1626 p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1627 p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1629 if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1630 req_reply_error(req, NT_STATUS_FOOBAR);
1634 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1635 req->async_states->send_fn = reply_simple_send;
1638 req->async_states->status = ntvfs_rename(req, io);
1644 /****************************************************************************
1645 Reply to an NT rename.
1646 ****************************************************************************/
1647 void reply_ntrename(struct smbsrv_request *req)
1649 union smb_rename *io;
1652 /* parse the request */
1653 REQ_CHECK_WCT(req, 4);
1654 REQ_TALLOC(io, sizeof(*io));
1656 io->generic.level = RAW_RENAME_NTRENAME;
1657 io->ntrename.in.attrib = SVAL(req->in.vwv, VWV(0));
1658 io->ntrename.in.flags = SVAL(req->in.vwv, VWV(1));
1659 io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1662 p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1663 p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1665 if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1666 req_reply_error(req, NT_STATUS_FOOBAR);
1670 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1671 req->async_states->send_fn = reply_simple_send;
1674 req->async_states->status = ntvfs_rename(req, io);
1679 /****************************************************************************
1680 Reply to a file copy (async reply)
1681 ****************************************************************************/
1682 static void reply_copy_send(struct smbsrv_request *req)
1684 struct smb_copy *cp = req->async_states->private_data;
1688 /* build the reply */
1689 req_setup_reply(req, 1, 0);
1691 SSVAL(req->out.vwv, VWV(0), cp->out.count);
1693 req_send_reply(req);
1696 /****************************************************************************
1697 Reply to a file copy.
1698 ****************************************************************************/
1699 void reply_copy(struct smbsrv_request *req)
1701 struct smb_copy *cp;
1705 REQ_CHECK_WCT(req, 3);
1706 REQ_TALLOC(cp, sizeof(*cp));
1708 cp->in.tid2 = SVAL(req->in.vwv, VWV(0));
1709 cp->in.ofun = SVAL(req->in.vwv, VWV(1));
1710 cp->in.flags = SVAL(req->in.vwv, VWV(2));
1713 p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1714 p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1716 if (!cp->in.path1 || !cp->in.path2) {
1717 req_reply_error(req, NT_STATUS_FOOBAR);
1721 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1722 req->async_states->send_fn = reply_copy_send;
1723 req->async_states->private_data = cp;
1726 req->async_states->status = ntvfs_copy(req, cp);
1731 /****************************************************************************
1732 Reply to a lockingX request (async send)
1733 ****************************************************************************/
1734 static void reply_lockingX_send(struct smbsrv_request *req)
1736 union smb_lock *lck = req->async_states->private_data;
1740 /* if it was an oplock break ack then we only send a reply if
1741 there was an error */
1742 if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1747 /* construct reply */
1748 req_setup_reply(req, 2, 0);
1750 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1751 SSVAL(req->out.vwv, VWV(1), 0);
1757 /****************************************************************************
1758 Reply to a lockingX request.
1759 ****************************************************************************/
1760 void reply_lockingX(struct smbsrv_request *req)
1762 union smb_lock *lck;
1763 uint_t total_locks, i;
1768 REQ_CHECK_WCT(req, 8);
1769 REQ_TALLOC(lck, sizeof(*lck));
1771 lck->lockx.level = RAW_LOCK_LOCKX;
1772 lck->lockx.in.fnum = req_fnum(req, req->in.vwv, VWV(2));
1773 lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
1774 lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
1775 lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1776 lck->lockx.in.lock_cnt = SVAL(req->in.vwv, VWV(7));
1778 total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1780 /* there are two variants, one with 64 bit offsets and counts */
1781 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1787 /* make sure we got the promised data */
1788 if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1789 req_reply_error(req, NT_STATUS_FOOBAR);
1793 /* allocate the locks array */
1795 REQ_TALLOC(lck->lockx.in.locks, total_locks * sizeof(lck->lockx.in.locks[0]));
1800 /* construct the locks array */
1801 for (i=0;i<total_locks;i++) {
1802 uint32_t ofs_high=0, count_high=0;
1804 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1806 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1807 ofs_high = IVAL(p, 4);
1808 lck->lockx.in.locks[i].offset = IVAL(p, 8);
1809 count_high = IVAL(p, 12);
1810 lck->lockx.in.locks[i].count = IVAL(p, 16);
1812 lck->lockx.in.locks[i].offset = IVAL(p, 2);
1813 lck->lockx.in.locks[i].count = IVAL(p, 6);
1815 if (ofs_high != 0 || count_high != 0) {
1816 lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32;
1817 lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1822 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1823 req->async_states->send_fn = reply_lockingX_send;
1824 req->async_states->private_data = lck;
1827 req->async_states->status = ntvfs_lock(req, lck);
1832 /****************************************************************************
1833 Reply to a SMBreadbmpx (read block multiplex) request.
1834 ****************************************************************************/
1835 void reply_readbmpx(struct smbsrv_request *req)
1837 /* tell the client to not use a multiplexed read - its too broken to use */
1838 req_reply_dos_error(req, ERRSRV, ERRuseSTD);
1842 /****************************************************************************
1843 Reply to a SMBsetattrE.
1844 ****************************************************************************/
1845 void reply_setattrE(struct smbsrv_request *req)
1847 union smb_setfileinfo *info;
1850 REQ_CHECK_WCT(req, 7);
1851 REQ_TALLOC(info, sizeof(*info));
1853 info->setattre.level = RAW_SFILEINFO_SETATTRE;
1854 info->setattre.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1855 info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1856 info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1857 info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1859 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1860 req->async_states->send_fn = reply_simple_send;
1863 req->async_states->status = ntvfs_setfileinfo(req, info);
1869 /****************************************************************************
1870 Reply to a SMBwritebmpx (write block multiplex primary) request.
1871 ****************************************************************************/
1872 void reply_writebmpx(struct smbsrv_request *req)
1874 /* we will need to implement this one for OS/2, but right now I can't be bothered */
1875 req_reply_error(req, NT_STATUS_FOOBAR);
1879 /****************************************************************************
1880 Reply to a SMBwritebs (write block multiplex secondary) request.
1881 ****************************************************************************/
1882 void reply_writebs(struct smbsrv_request *req)
1884 /* see reply_writebmpx */
1885 req_reply_error(req, NT_STATUS_FOOBAR);
1890 /****************************************************************************
1891 Reply to a SMBgetattrE (async reply)
1892 ****************************************************************************/
1893 static void reply_getattrE_send(struct smbsrv_request *req)
1895 union smb_fileinfo *info = req->async_states->private_data;
1900 req_setup_reply(req, 11, 0);
1902 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1903 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1904 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1905 SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
1906 SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
1907 SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
1909 req_send_reply(req);
1912 /****************************************************************************
1913 Reply to a SMBgetattrE.
1914 ****************************************************************************/
1915 void reply_getattrE(struct smbsrv_request *req)
1917 union smb_fileinfo *info;
1920 REQ_CHECK_WCT(req, 1);
1921 REQ_TALLOC(info, sizeof(*info));
1923 info->getattr.level = RAW_FILEINFO_GETATTRE;
1924 info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
1926 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1927 req->async_states->send_fn = reply_getattrE_send;
1928 req->async_states->private_data = info;
1931 req->async_states->status = ntvfs_qfileinfo(req, info);
1937 /****************************************************************************
1938 reply to an old style session setup command
1939 ****************************************************************************/
1940 static void reply_sesssetup_old(struct smbsrv_request *req)
1943 union smb_sesssetup sess;
1947 sess.old.level = RAW_SESSSETUP_OLD;
1950 sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1951 sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1952 sess.old.in.vc_num = SVAL(req->in.vwv, VWV(4));
1953 sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1954 passlen = SVAL(req->in.vwv, VWV(7));
1956 /* check the request isn't malformed */
1957 if (req_data_oob(req, req->in.data, passlen)) {
1958 req_reply_error(req, NT_STATUS_FOOBAR);
1963 if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1964 req_reply_error(req, NT_STATUS_FOOBAR);
1969 p += req_pull_string(req, &sess.old.in.user, p, -1, STR_TERMINATE);
1970 p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1971 p += req_pull_string(req, &sess.old.in.os, p, -1, STR_TERMINATE);
1972 p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
1974 /* call the generic handler */
1975 status = sesssetup_backend(req, &sess);
1977 if (!NT_STATUS_IS_OK(status)) {
1978 req_reply_error(req, status);
1982 /* construct reply */
1983 req_setup_reply(req, 3, 0);
1985 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1986 SSVAL(req->out.vwv, VWV(1), 0);
1987 SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
1989 SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
1995 /****************************************************************************
1996 reply to an NT1 style session setup command
1997 ****************************************************************************/
1998 static void reply_sesssetup_nt1(struct smbsrv_request *req)
2001 union smb_sesssetup sess;
2003 uint16_t passlen1, passlen2;
2005 sess.nt1.level = RAW_SESSSETUP_NT1;
2008 sess.nt1.in.bufsize = SVAL(req->in.vwv, VWV(2));
2009 sess.nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2010 sess.nt1.in.vc_num = SVAL(req->in.vwv, VWV(4));
2011 sess.nt1.in.sesskey = IVAL(req->in.vwv, VWV(5));
2012 passlen1 = SVAL(req->in.vwv, VWV(7));
2013 passlen2 = SVAL(req->in.vwv, VWV(8));
2014 sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
2016 /* check the request isn't malformed */
2017 if (req_data_oob(req, req->in.data, passlen1) ||
2018 req_data_oob(req, req->in.data + passlen1, passlen2)) {
2019 req_reply_error(req, NT_STATUS_FOOBAR);
2024 if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
2025 req_reply_error(req, NT_STATUS_FOOBAR);
2029 if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
2030 req_reply_error(req, NT_STATUS_FOOBAR);
2035 p += req_pull_string(req, &sess.nt1.in.user, p, -1, STR_TERMINATE);
2036 p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
2037 p += req_pull_string(req, &sess.nt1.in.os, p, -1, STR_TERMINATE);
2038 p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
2040 /* call the generic handler */
2041 status = sesssetup_backend(req, &sess);
2043 if (!NT_STATUS_IS_OK(status)) {
2044 req_reply_error(req, status);
2048 /* construct reply */
2049 req_setup_reply(req, 3, 0);
2051 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2052 SSVAL(req->out.vwv, VWV(1), 0);
2053 SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
2055 SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
2057 req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
2058 req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
2059 req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
2065 /****************************************************************************
2066 reply to an SPNEGO style session setup command
2067 ****************************************************************************/
2068 static void reply_sesssetup_spnego(struct smbsrv_request *req)
2071 union smb_sesssetup sess;
2075 sess.spnego.level = RAW_SESSSETUP_SPNEGO;
2078 sess.spnego.in.bufsize = SVAL(req->in.vwv, VWV(2));
2079 sess.spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2080 sess.spnego.in.vc_num = SVAL(req->in.vwv, VWV(4));
2081 sess.spnego.in.sesskey = IVAL(req->in.vwv, VWV(5));
2082 blob_len = SVAL(req->in.vwv, VWV(7));
2083 sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
2086 if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
2087 req_reply_error(req, NT_STATUS_FOOBAR);
2092 p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE);
2093 p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE);
2094 p += req_pull_string(req, &sess.spnego.in.domain, p, -1, STR_TERMINATE);
2096 /* call the generic handler */
2097 status = sesssetup_backend(req, &sess);
2099 if (!NT_STATUS_IS_OK(status) &&
2100 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2101 req_reply_error(req, status);
2105 /* construct reply */
2106 req_setup_reply(req, 4, sess.spnego.out.secblob.length);
2108 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2109 req_setup_error(req, status);
2112 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2113 SSVAL(req->out.vwv, VWV(1), 0);
2114 SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
2115 SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
2117 SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
2119 memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
2120 req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
2121 req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
2122 req_push_str(req, NULL, sess.spnego.out.domain, -1, STR_TERMINATE);
2128 /****************************************************************************
2129 reply to a session setup command
2130 ****************************************************************************/
2131 void reply_sesssetup(struct smbsrv_request *req)
2133 switch (req->in.wct) {
2135 /* a pre-NT1 call */
2136 reply_sesssetup_old(req);
2140 reply_sesssetup_nt1(req);
2144 reply_sesssetup_spnego(req);
2148 /* unsupported variant */
2149 req_reply_error(req, NT_STATUS_FOOBAR);
2152 /****************************************************************************
2153 Reply to a SMBulogoffX.
2154 ****************************************************************************/
2155 void reply_ulogoffX(struct smbsrv_request *req)
2157 struct smbsrv_tcon *tcon;
2161 vuid = SVAL(req->in.hdr, HDR_UID);
2163 /* in user level security we are supposed to close any files
2164 open by this user on all open tree connects */
2165 if ((vuid != 0) && (lp_security() != SEC_SHARE)) {
2166 for (tcon=req->smb_conn->tree.tcons;tcon;tcon=tcon->next) {
2168 status = ntvfs_logoff(req);
2170 if (!NT_STATUS_IS_OK(status)) {
2171 req_reply_error(req, status);
2177 smbsrv_invalidate_vuid(req->smb_conn, vuid);
2179 req_setup_reply(req, 2, 0);
2181 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2182 SSVAL(req->out.vwv, VWV(1), 0);
2188 /****************************************************************************
2189 Reply to an SMBfindclose request
2190 ****************************************************************************/
2191 void reply_findclose(struct smbsrv_request *req)
2194 union smb_search_close io;
2196 io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2199 REQ_CHECK_WCT(req, 1);
2201 io.findclose.in.handle = SVAL(req->in.vwv, VWV(0));
2204 status = ntvfs_search_close(req, &io);
2206 if (!NT_STATUS_IS_OK(status)) {
2207 req_reply_error(req, status);
2211 /* construct reply */
2212 req_setup_reply(req, 0, 0);
2214 req_send_reply(req);
2217 /****************************************************************************
2218 Reply to an SMBfindnclose request
2219 ****************************************************************************/
2220 void reply_findnclose(struct smbsrv_request *req)
2222 req_reply_error(req, NT_STATUS_FOOBAR);
2226 /****************************************************************************
2227 Reply to an SMBntcreateX request (async send)
2228 ****************************************************************************/
2229 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
2231 union smb_open *io = req->async_states->private_data;
2235 /* construct reply */
2236 req_setup_reply(req, 34, 0);
2238 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2239 SSVAL(req->out.vwv, VWV(1), 0);
2240 SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2242 /* the rest of the parameters are not aligned! */
2243 SSVAL(req->out.vwv, 5, io->ntcreatex.out.fnum);
2244 SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
2245 push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2246 push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2247 push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2248 push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2249 SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
2250 SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
2251 SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
2252 SSVAL(req->out.vwv, 63, io->ntcreatex.out.file_type);
2253 SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
2254 SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
2259 /****************************************************************************
2260 Reply to an SMBntcreateX request
2261 ****************************************************************************/
2262 void reply_ntcreate_and_X(struct smbsrv_request *req)
2267 /* parse the request */
2268 REQ_CHECK_WCT(req, 24);
2269 REQ_TALLOC(io, sizeof(*io));
2271 io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2273 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2274 fname_len = SVAL(req->in.vwv, 5);
2275 io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
2276 io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
2277 io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
2278 io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
2279 io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
2280 io->ntcreatex.in.share_access = IVAL(req->in.vwv, 31);
2281 io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2282 io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
2283 io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
2284 io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
2286 /* we need a neater way to handle this alignment */
2287 if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
2288 ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2292 req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2293 if (!io->ntcreatex.in.fname) {
2294 req_reply_error(req, NT_STATUS_FOOBAR);
2298 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
2299 req->async_states->send_fn = reply_ntcreate_and_X_send;
2300 req->async_states->private_data = io;
2302 /* call the backend */
2303 req->async_states->status = ntvfs_open(req, io);
2309 /****************************************************************************
2310 Reply to an SMBntcancel request
2311 ****************************************************************************/
2312 void reply_ntcancel(struct smbsrv_request *req)
2314 req_reply_error(req, NT_STATUS_FOOBAR);
2317 /****************************************************************************
2318 Reply to an SMBsends request
2319 ****************************************************************************/
2320 void reply_sends(struct smbsrv_request *req)
2322 req_reply_error(req, NT_STATUS_FOOBAR);
2325 /****************************************************************************
2326 Reply to an SMBsendstrt request
2327 ****************************************************************************/
2328 void reply_sendstrt(struct smbsrv_request *req)
2330 req_reply_error(req, NT_STATUS_FOOBAR);
2333 /****************************************************************************
2334 Reply to an SMBsendend request
2335 ****************************************************************************/
2336 void reply_sendend(struct smbsrv_request *req)
2338 req_reply_error(req, NT_STATUS_FOOBAR);
2341 /****************************************************************************
2342 Reply to an SMBsendtxt request
2343 ****************************************************************************/
2344 void reply_sendtxt(struct smbsrv_request *req)
2346 req_reply_error(req, NT_STATUS_FOOBAR);
2351 /****************************************************************************
2352 Reply to a special message - a SMB packet with non zero NBT message type
2353 ****************************************************************************/
2354 void reply_special(struct smbsrv_request *req)
2359 msg_type = CVAL(req->in.buffer,0);
2364 case 0x81: /* session request */
2365 if (req->smb_conn->negotiate.done_nbt_session) {
2366 smbsrv_terminate_connection(req->smb_conn, "multiple session request not permitted");
2372 DEBUG(0,("REWRITE: not parsing netbios names in NBT session request!\n"));
2373 /* TODO: store the name for the session setup 'remote machine' code, as well as smbstatus */
2375 req->smb_conn->negotiate.done_nbt_session = True;
2377 req->out.buffer = buf;
2379 req_send_reply_nosign(req);
2382 case 0x89: /* session keepalive request
2383 (some old clients produce this?) */
2384 SCVAL(buf, 0, SMBkeepalive);
2386 req->out.buffer = buf;
2388 req_send_reply_nosign(req);
2392 /* session keepalive - swallow it */
2397 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));