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 smbsrv_send_error(req, NT_STATUS_DOS(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 smbsrv_send_error(req, req->async_states->status); \
47 /* useful wrapper for talloc with NO_MEMORY reply */
48 #define REQ_TALLOC(ptr, type) do { \
49 ptr = talloc(req, type); \
51 smbsrv_send_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 smbsrv_setup_reply(req, 0, 0);
76 smbsrv_send_reply(req);
80 /****************************************************************************
82 ****************************************************************************/
83 void smbsrv_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 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
105 status = smbsrv_tcon_backend(req, &con);
107 if (!NT_STATUS_IS_OK(status)) {
108 smbsrv_send_error(req, status);
112 /* construct reply */
113 smbsrv_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);
119 smbsrv_send_reply(req);
123 /****************************************************************************
124 Reply to a tcon and X.
125 ****************************************************************************/
126 void smbsrv_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 smbsrv_send_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 smbsrv_send_error(req, NT_STATUS_BAD_DEVICE_TYPE);
158 status = smbsrv_tcon_backend(req, &con);
160 if (!NT_STATUS_IS_OK(status)) {
161 smbsrv_send_error(req, status);
165 /* construct reply - two variants */
166 if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
167 smbsrv_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 smbsrv_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);
188 smbsrv_chain_reply(req);
192 /****************************************************************************
193 Reply to an unknown request
194 ****************************************************************************/
195 void smbsrv_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 smbsrv_send_error(req, NT_STATUS_DOS(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 smbsrv_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);
224 smbsrv_send_reply(req);
227 /****************************************************************************
229 ****************************************************************************/
230 void smbsrv_reply_ioctl(struct smbsrv_request *req)
235 REQ_CHECK_WCT(req, 3);
236 REQ_TALLOC(io, union smb_ioctl);
238 io->ioctl.level = RAW_IOCTL_IOCTL;
239 io->ioctl.file.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 smbsrv_reply_chkpth(struct smbsrv_request *req)
258 union smb_chkpath *io;
260 REQ_TALLOC(io, union smb_chkpath);
262 req_pull_ascii4(req, &io->chkpath.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 smbsrv_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);
290 smbsrv_send_reply(req);
294 /****************************************************************************
296 ****************************************************************************/
297 void smbsrv_reply_getatr(struct smbsrv_request *req)
299 union smb_fileinfo *st;
301 REQ_TALLOC(st, union smb_fileinfo);
303 st->getattr.level = RAW_FILEINFO_GETATTR;
306 req_pull_ascii4(req, &st->getattr.file.path, req->in.data, STR_TERMINATE);
307 if (!st->getattr.file.path) {
308 smbsrv_send_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 smbsrv_reply_setatr(struct smbsrv_request *req)
328 union smb_setfileinfo *st;
331 REQ_CHECK_WCT(req, 8);
332 REQ_TALLOC(st, union smb_setfileinfo);
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.path, req->in.data, STR_TERMINATE);
340 if (!st->setattr.file.path) {
341 smbsrv_send_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 smbsrv_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);
374 smbsrv_send_reply(req);
378 /****************************************************************************
380 ****************************************************************************/
381 void smbsrv_reply_dskattr(struct smbsrv_request *req)
383 union smb_fsinfo *fs;
385 REQ_TALLOC(fs, union smb_fsinfo);
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 smbsrv_setup_reply(req, 7, 0);
413 SSVAL(req->out.vwv, VWV(0), oi->openold.file.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);
419 smbsrv_send_reply(req);
422 /****************************************************************************
424 ****************************************************************************/
425 void smbsrv_reply_open(struct smbsrv_request *req)
430 REQ_CHECK_WCT(req, 2);
431 REQ_TALLOC(oi, union smb_open);
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 smbsrv_send_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_open(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 smbsrv_setup_reply(req, 19, 0);
468 smbsrv_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.file.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.file.fnum;
490 smbsrv_chain_reply(req);
494 /****************************************************************************
495 Reply to an open and X.
496 ****************************************************************************/
497 void smbsrv_reply_open_and_X(struct smbsrv_request *req)
501 /* parse the request */
502 REQ_CHECK_WCT(req, 15);
503 REQ_TALLOC(oi, union smb_open);
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 smbsrv_send_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_open(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 smbsrv_setup_reply(req, 1, 0);
545 SSVAL(req->out.vwv, VWV(0), oi->mknew.file.fnum);
547 smbsrv_send_reply(req);
551 /****************************************************************************
552 Reply to a mknew or a create.
553 ****************************************************************************/
554 void smbsrv_reply_mknew(struct smbsrv_request *req)
558 /* parse the request */
559 REQ_CHECK_WCT(req, 3);
560 REQ_TALLOC(oi, union smb_open);
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 smbsrv_send_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_open(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 smbsrv_setup_reply(req, 1, 0);
599 SSVAL(req->out.vwv, VWV(0), oi->ctemp.file.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);
604 smbsrv_send_reply(req);
607 /****************************************************************************
608 Reply to a create temporary file.
609 ****************************************************************************/
610 void smbsrv_reply_ctemp(struct smbsrv_request *req)
614 /* parse the request */
615 REQ_CHECK_WCT(req, 3);
616 REQ_TALLOC(oi, union smb_open);
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 smbsrv_send_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_open(req, oi);
642 /****************************************************************************
644 ****************************************************************************/
645 void smbsrv_reply_unlink(struct smbsrv_request *req)
647 union smb_unlink *unl;
649 /* parse the request */
650 REQ_CHECK_WCT(req, 1);
651 REQ_TALLOC(unl, union smb_unlink);
653 unl->unlink.in.attrib = SVAL(req->in.vwv, VWV(0));
655 req_pull_ascii4(req, &unl->unlink.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 smbsrv_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.file.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 smbsrv_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 smbsrv_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);
752 smbsrv_send_reply(req);
756 /****************************************************************************
757 Reply to a lockread (core+ protocol).
758 note that the lock is a write lock, not a read lock!
759 ****************************************************************************/
760 void smbsrv_reply_lockread(struct smbsrv_request *req)
765 REQ_CHECK_WCT(req, 5);
766 REQ_TALLOC(io, union smb_read);
768 io->lockread.level = RAW_READ_LOCKREAD;
769 io->lockread.file.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 smbsrv_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);
813 smbsrv_send_reply(req);
816 /****************************************************************************
818 ****************************************************************************/
819 void smbsrv_reply_read(struct smbsrv_request *req)
824 REQ_CHECK_WCT(req, 5);
825 REQ_TALLOC(io, union smb_read);
827 io->read.level = RAW_READ_READ;
828 io->read.file.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 smbsrv_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);
880 smbsrv_chain_reply(req);
883 /****************************************************************************
884 Reply to a read and X.
885 ****************************************************************************/
886 void smbsrv_reply_read_and_X(struct smbsrv_request *req)
891 if (req->in.wct != 12) {
892 REQ_CHECK_WCT(req, 10);
895 REQ_TALLOC(io, union smb_read);
897 io->readx.level = RAW_READ_READX;
898 io->readx.file.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));
903 if (req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) {
904 io->readx.in.read_for_execute = True;
906 io->readx.in.read_for_execute = False;
909 if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
910 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
911 if (high_part == 1) {
912 io->readx.in.maxcnt |= high_part << 16;
916 /* the 64 bit variant */
917 if (req->in.wct == 12) {
918 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
919 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
922 /* setup the reply packet assuming the maximum possible read */
923 smbsrv_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
925 /* tell the backend where to put the data. Notice the pad byte. */
926 if (io->readx.in.maxcnt != 0xFFFF &&
927 io->readx.in.mincnt != 0xFFFF) {
928 io->readx.out.data = req->out.data + 1;
930 io->readx.out.data = req->out.data;
933 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
934 req->async_states->send_fn = reply_read_and_X_send;
935 req->async_states->private_data = io;
938 req->async_states->status = ntvfs_read(req, io);
944 /****************************************************************************
945 Reply to a writebraw (core+ or LANMAN1.0 protocol).
946 ****************************************************************************/
947 void smbsrv_reply_writebraw(struct smbsrv_request *req)
949 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
953 /****************************************************************************
954 Reply to a writeunlock (async reply)
955 ****************************************************************************/
956 static void reply_writeunlock_send(struct smbsrv_request *req)
958 union smb_write *io = req->async_states->private_data;
962 /* construct reply */
963 smbsrv_setup_reply(req, 1, 0);
965 SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
967 smbsrv_send_reply(req);
970 /****************************************************************************
971 Reply to a writeunlock (core+).
972 ****************************************************************************/
973 void smbsrv_reply_writeunlock(struct smbsrv_request *req)
977 REQ_CHECK_WCT(req, 5);
978 REQ_TALLOC(io, union smb_write);
980 io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
981 io->writeunlock.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
982 io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
983 io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
984 io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
985 io->writeunlock.in.data = req->in.data + 3;
987 /* make sure they gave us the data they promised */
988 if (io->writeunlock.in.count+3 > req->in.data_size) {
989 smbsrv_send_error(req, NT_STATUS_FOOBAR);
993 /* make sure the data block is big enough */
994 if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
995 smbsrv_send_error(req, NT_STATUS_FOOBAR);
999 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1000 req->async_states->send_fn = reply_writeunlock_send;
1001 req->async_states->private_data = io;
1004 req->async_states->status = ntvfs_write(req, io);
1011 /****************************************************************************
1012 Reply to a write (async reply)
1013 ****************************************************************************/
1014 static void reply_write_send(struct smbsrv_request *req)
1016 union smb_write *io = req->async_states->private_data;
1020 /* construct reply */
1021 smbsrv_setup_reply(req, 1, 0);
1023 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1025 smbsrv_send_reply(req);
1028 /****************************************************************************
1030 ****************************************************************************/
1031 void smbsrv_reply_write(struct smbsrv_request *req)
1033 union smb_write *io;
1035 REQ_CHECK_WCT(req, 5);
1036 REQ_TALLOC(io, union smb_write);
1038 io->write.level = RAW_WRITE_WRITE;
1039 io->write.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1040 io->write.in.count = SVAL(req->in.vwv, VWV(1));
1041 io->write.in.offset = IVAL(req->in.vwv, VWV(2));
1042 io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
1043 io->write.in.data = req->in.data + 3;
1045 /* make sure they gave us the data they promised */
1046 if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
1047 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1051 /* make sure the data block is big enough */
1052 if (SVAL(req->in.data, 1) < io->write.in.count) {
1053 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1057 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1058 req->async_states->send_fn = reply_write_send;
1059 req->async_states->private_data = io;
1062 req->async_states->status = ntvfs_write(req, io);
1068 /****************************************************************************
1069 Reply to a write and X (async reply)
1070 ****************************************************************************/
1071 static void reply_write_and_X_send(struct smbsrv_request *req)
1073 union smb_write *io = req->async_states->private_data;
1077 /* construct reply */
1078 smbsrv_setup_reply(req, 6, 0);
1080 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1081 SSVAL(req->out.vwv, VWV(1), 0);
1082 SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
1083 SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
1084 SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
1085 REQ_VWV_RESERVED(5, 1);
1087 smbsrv_chain_reply(req);
1090 /****************************************************************************
1091 Reply to a write and X.
1092 ****************************************************************************/
1093 void smbsrv_reply_write_and_X(struct smbsrv_request *req)
1095 union smb_write *io;
1097 if (req->in.wct != 14) {
1098 REQ_CHECK_WCT(req, 12);
1101 REQ_TALLOC(io, union smb_write);
1103 io->writex.level = RAW_WRITE_WRITEX;
1104 io->writex.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
1105 io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
1106 io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
1107 io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1108 io->writex.in.count = SVAL(req->in.vwv, VWV(10));
1109 io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1111 if (req->in.wct == 14) {
1112 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1113 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1114 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1115 io->writex.in.count |= ((uint32_t)count_high) << 16;
1118 /* make sure the data is in bounds */
1119 if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1120 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1124 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1125 req->async_states->send_fn = reply_write_and_X_send;
1126 req->async_states->private_data = io;
1129 req->async_states->status = ntvfs_write(req, io);
1135 /****************************************************************************
1136 Reply to a lseek (async reply)
1137 ****************************************************************************/
1138 static void reply_lseek_send(struct smbsrv_request *req)
1140 union smb_seek *io = req->async_states->private_data;
1144 /* construct reply */
1145 smbsrv_setup_reply(req, 2, 0);
1147 SIVALS(req->out.vwv, VWV(0), io->lseek.out.offset);
1149 smbsrv_send_reply(req);
1152 /****************************************************************************
1154 ****************************************************************************/
1155 void smbsrv_reply_lseek(struct smbsrv_request *req)
1159 REQ_CHECK_WCT(req, 4);
1160 REQ_TALLOC(io, union smb_seek);
1162 io->lseek.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1163 io->lseek.in.mode = SVAL(req->in.vwv, VWV(1));
1164 io->lseek.in.offset = IVALS(req->in.vwv, VWV(2));
1166 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1167 req->async_states->send_fn = reply_lseek_send;
1168 req->async_states->private_data = io;
1171 req->async_states->status = ntvfs_seek(req, io);
1176 /****************************************************************************
1178 ****************************************************************************/
1179 void smbsrv_reply_flush(struct smbsrv_request *req)
1181 union smb_flush *io;
1184 REQ_CHECK_WCT(req, 1);
1185 REQ_TALLOC(io, union smb_flush);
1187 io->flush.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1189 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1190 req->async_states->send_fn = reply_simple_send;
1193 req->async_states->status = ntvfs_flush(req, io);
1199 /****************************************************************************
1200 Reply to a exit. This closes all files open by a smbpid
1201 ****************************************************************************/
1202 void smbsrv_reply_exit(struct smbsrv_request *req)
1205 struct smbsrv_tcon *tcon;
1206 REQ_CHECK_WCT(req, 0);
1208 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
1210 status = ntvfs_exit(req);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 smbsrv_send_error(req, status);
1218 smbsrv_setup_reply(req, 0, 0);
1219 smbsrv_send_reply(req);
1223 /****************************************************************************
1226 Note that this has to deal with closing a directory opened by NT SMB's.
1227 ****************************************************************************/
1228 void smbsrv_reply_close(struct smbsrv_request *req)
1230 union smb_close *io;
1233 REQ_CHECK_WCT(req, 3);
1234 REQ_TALLOC(io, union smb_close);
1236 io->close.level = RAW_CLOSE_CLOSE;
1237 io->close.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1238 io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1240 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1241 req->async_states->send_fn = reply_simple_send;
1244 req->async_states->status = ntvfs_close(req, io);
1251 /****************************************************************************
1252 Reply to a writeclose (async reply)
1253 ****************************************************************************/
1254 static void reply_writeclose_send(struct smbsrv_request *req)
1256 union smb_write *io = req->async_states->private_data;
1260 /* construct reply */
1261 smbsrv_setup_reply(req, 1, 0);
1263 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1265 smbsrv_send_reply(req);
1268 /****************************************************************************
1269 Reply to a writeclose (Core+ protocol).
1270 ****************************************************************************/
1271 void smbsrv_reply_writeclose(struct smbsrv_request *req)
1273 union smb_write *io;
1275 /* this one is pretty weird - the wct can be 6 or 12 */
1276 if (req->in.wct != 12) {
1277 REQ_CHECK_WCT(req, 6);
1280 REQ_TALLOC(io, union smb_write);
1282 io->writeclose.level = RAW_WRITE_WRITECLOSE;
1283 io->writeclose.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1284 io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
1285 io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1286 io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1287 io->writeclose.in.data = req->in.data + 1;
1289 /* make sure they gave us the data they promised */
1290 if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1291 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1295 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1296 req->async_states->send_fn = reply_writeclose_send;
1297 req->async_states->private_data = io;
1300 req->async_states->status = ntvfs_write(req, io);
1305 /****************************************************************************
1307 ****************************************************************************/
1308 void smbsrv_reply_lock(struct smbsrv_request *req)
1310 union smb_lock *lck;
1313 REQ_CHECK_WCT(req, 5);
1314 REQ_TALLOC(lck, union smb_lock);
1316 lck->lock.level = RAW_LOCK_LOCK;
1317 lck->lock.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1318 lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
1319 lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1321 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1322 req->async_states->send_fn = reply_simple_send;
1325 req->async_states->status = ntvfs_lock(req, lck);
1331 /****************************************************************************
1333 ****************************************************************************/
1334 void smbsrv_reply_unlock(struct smbsrv_request *req)
1336 union smb_lock *lck;
1339 REQ_CHECK_WCT(req, 5);
1340 REQ_TALLOC(lck, union smb_lock);
1342 lck->unlock.level = RAW_LOCK_UNLOCK;
1343 lck->unlock.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1344 lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
1345 lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1347 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1348 req->async_states->send_fn = reply_simple_send;
1351 req->async_states->status = ntvfs_lock(req, lck);
1357 /****************************************************************************
1359 ****************************************************************************/
1360 void smbsrv_reply_tdis(struct smbsrv_request *req)
1362 REQ_CHECK_WCT(req, 0);
1364 if (req->tcon == NULL) {
1365 smbsrv_send_error(req, NT_STATUS_INVALID_HANDLE);
1369 talloc_free(req->tcon);
1371 /* construct reply */
1372 smbsrv_setup_reply(req, 0, 0);
1374 smbsrv_send_reply(req);
1378 /****************************************************************************
1379 Reply to a echo. This is one of the few calls that is handled directly (the
1380 backends don't see it at all)
1381 ****************************************************************************/
1382 void smbsrv_reply_echo(struct smbsrv_request *req)
1387 REQ_CHECK_WCT(req, 0);
1389 count = SVAL(req->in.vwv, VWV(0));
1391 smbsrv_setup_reply(req, 1, req->in.data_size);
1393 memcpy(req->out.data, req->in.data, req->in.data_size);
1395 for (i=1; i <= count;i++) {
1396 struct smbsrv_request *this_req;
1399 this_req = smbsrv_setup_secondary_request(req);
1404 SSVAL(this_req->out.vwv, VWV(0), i);
1405 smbsrv_send_reply(this_req);
1411 /****************************************************************************
1412 Reply to a printopen (async reply)
1413 ****************************************************************************/
1414 static void reply_printopen_send(struct smbsrv_request *req)
1416 union smb_open *oi = req->async_states->private_data;
1420 /* construct reply */
1421 smbsrv_setup_reply(req, 1, 0);
1423 SSVAL(req->out.vwv, VWV(0), oi->openold.file.fnum);
1425 smbsrv_send_reply(req);
1428 /****************************************************************************
1429 Reply to a printopen.
1430 ****************************************************************************/
1431 void smbsrv_reply_printopen(struct smbsrv_request *req)
1436 REQ_CHECK_WCT(req, 2);
1437 REQ_TALLOC(oi, union smb_open);
1439 oi->splopen.level = RAW_OPEN_SPLOPEN;
1440 oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1441 oi->splopen.in.mode = SVAL(req->in.vwv, VWV(1));
1443 req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1445 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1446 req->async_states->send_fn = reply_printopen_send;
1447 req->async_states->private_data = oi;
1450 req->async_states->status = ntvfs_open(req, oi);
1455 /****************************************************************************
1456 Reply to a printclose.
1457 ****************************************************************************/
1458 void smbsrv_reply_printclose(struct smbsrv_request *req)
1460 union smb_close *io;
1463 REQ_CHECK_WCT(req, 3);
1464 REQ_TALLOC(io, union smb_close);
1466 io->splclose.level = RAW_CLOSE_SPLCLOSE;
1467 io->splclose.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1469 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1470 req->async_states->send_fn = reply_simple_send;
1473 req->async_states->status = ntvfs_close(req, io);
1478 /****************************************************************************
1479 Reply to a printqueue.
1480 ****************************************************************************/
1481 static void reply_printqueue_send(struct smbsrv_request *req)
1483 union smb_lpq *lpq = req->async_states->private_data;
1485 const uint_t el_size = 28;
1489 /* construct reply */
1490 smbsrv_setup_reply(req, 2, 0);
1492 /* truncate the returned list to fit in the negotiated buffer size */
1493 maxcount = (req_max_data(req) - 3) / el_size;
1494 if (maxcount < lpq->retq.out.count) {
1495 lpq->retq.out.count = maxcount;
1498 /* setup enough space in the reply */
1499 req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1501 /* and fill it in */
1502 SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1503 SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1505 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1506 SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1508 req->out.ptr = req->out.data + 3;
1510 for (i=0;i<lpq->retq.out.count;i++) {
1511 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1512 SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
1513 SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
1514 SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
1515 SCVAL(req->out.ptr, 11, 0); /* reserved */
1516 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1517 req->out.ptr += el_size;
1520 smbsrv_send_reply(req);
1523 /****************************************************************************
1524 Reply to a printqueue.
1525 ****************************************************************************/
1526 void smbsrv_reply_printqueue(struct smbsrv_request *req)
1531 REQ_CHECK_WCT(req, 2);
1532 REQ_TALLOC(lpq, union smb_lpq);
1534 lpq->retq.level = RAW_LPQ_RETQ;
1535 lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
1536 lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
1538 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1539 req->async_states->send_fn = reply_printqueue_send;
1540 req->async_states->private_data = lpq;
1543 req->async_states->status = ntvfs_lpq(req, lpq);
1549 /****************************************************************************
1550 Reply to a printwrite.
1551 ****************************************************************************/
1552 void smbsrv_reply_printwrite(struct smbsrv_request *req)
1554 union smb_write *io;
1557 REQ_CHECK_WCT(req, 1);
1558 REQ_TALLOC(io, union smb_write);
1560 io->splwrite.level = RAW_WRITE_SPLWRITE;
1562 if (req->in.data_size < 3) {
1563 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1567 io->splwrite.file.fnum= req_fnum(req, req->in.vwv, VWV(0));
1568 io->splwrite.in.count = SVAL(req->in.data, 1);
1569 io->splwrite.in.data = req->in.data + 3;
1571 /* make sure they gave us the data they promised */
1572 if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1573 smbsrv_send_error(req, NT_STATUS_FOOBAR);
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_write(req, io);
1587 /****************************************************************************
1589 ****************************************************************************/
1590 void smbsrv_reply_mkdir(struct smbsrv_request *req)
1592 union smb_mkdir *io;
1594 /* parse the request */
1595 REQ_CHECK_WCT(req, 0);
1596 REQ_TALLOC(io, union smb_mkdir);
1598 io->generic.level = RAW_MKDIR_MKDIR;
1599 req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1601 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1602 req->async_states->send_fn = reply_simple_send;
1605 req->async_states->status = ntvfs_mkdir(req, io);
1611 /****************************************************************************
1613 ****************************************************************************/
1614 void smbsrv_reply_rmdir(struct smbsrv_request *req)
1616 struct smb_rmdir *io;
1618 /* parse the request */
1619 REQ_CHECK_WCT(req, 0);
1620 REQ_TALLOC(io, struct smb_rmdir);
1622 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1624 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1625 req->async_states->send_fn = reply_simple_send;
1628 req->async_states->status = ntvfs_rmdir(req, io);
1634 /****************************************************************************
1636 ****************************************************************************/
1637 void smbsrv_reply_mv(struct smbsrv_request *req)
1639 union smb_rename *io;
1642 /* parse the request */
1643 REQ_CHECK_WCT(req, 1);
1644 REQ_TALLOC(io, union smb_rename);
1646 io->generic.level = RAW_RENAME_RENAME;
1647 io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1650 p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1651 p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1653 if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1654 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1658 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1659 req->async_states->send_fn = reply_simple_send;
1662 req->async_states->status = ntvfs_rename(req, io);
1668 /****************************************************************************
1669 Reply to an NT rename.
1670 ****************************************************************************/
1671 void smbsrv_reply_ntrename(struct smbsrv_request *req)
1673 union smb_rename *io;
1676 /* parse the request */
1677 REQ_CHECK_WCT(req, 4);
1678 REQ_TALLOC(io, union smb_rename);
1680 io->generic.level = RAW_RENAME_NTRENAME;
1681 io->ntrename.in.attrib = SVAL(req->in.vwv, VWV(0));
1682 io->ntrename.in.flags = SVAL(req->in.vwv, VWV(1));
1683 io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1686 p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1687 p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1689 if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1690 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1694 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1695 req->async_states->send_fn = reply_simple_send;
1698 req->async_states->status = ntvfs_rename(req, io);
1703 /****************************************************************************
1704 Reply to a file copy (async reply)
1705 ****************************************************************************/
1706 static void reply_copy_send(struct smbsrv_request *req)
1708 struct smb_copy *cp = req->async_states->private_data;
1712 /* build the reply */
1713 smbsrv_setup_reply(req, 1, 0);
1715 SSVAL(req->out.vwv, VWV(0), cp->out.count);
1717 smbsrv_send_reply(req);
1720 /****************************************************************************
1721 Reply to a file copy.
1722 ****************************************************************************/
1723 void smbsrv_reply_copy(struct smbsrv_request *req)
1725 struct smb_copy *cp;
1729 REQ_CHECK_WCT(req, 3);
1730 REQ_TALLOC(cp, struct smb_copy);
1732 cp->in.tid2 = SVAL(req->in.vwv, VWV(0));
1733 cp->in.ofun = SVAL(req->in.vwv, VWV(1));
1734 cp->in.flags = SVAL(req->in.vwv, VWV(2));
1737 p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1738 p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1740 if (!cp->in.path1 || !cp->in.path2) {
1741 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1745 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1746 req->async_states->send_fn = reply_copy_send;
1747 req->async_states->private_data = cp;
1750 req->async_states->status = ntvfs_copy(req, cp);
1755 /****************************************************************************
1756 Reply to a lockingX request (async send)
1757 ****************************************************************************/
1758 static void reply_lockingX_send(struct smbsrv_request *req)
1760 union smb_lock *lck = req->async_states->private_data;
1764 /* if it was an oplock break ack then we only send a reply if
1765 there was an error */
1766 if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1771 /* construct reply */
1772 smbsrv_setup_reply(req, 2, 0);
1774 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1775 SSVAL(req->out.vwv, VWV(1), 0);
1777 smbsrv_chain_reply(req);
1781 /****************************************************************************
1782 Reply to a lockingX request.
1783 ****************************************************************************/
1784 void smbsrv_reply_lockingX(struct smbsrv_request *req)
1786 union smb_lock *lck;
1787 uint_t total_locks, i;
1792 REQ_CHECK_WCT(req, 8);
1793 REQ_TALLOC(lck, union smb_lock);
1795 lck->lockx.level = RAW_LOCK_LOCKX;
1796 lck->lockx.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
1797 lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
1798 lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
1799 lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1800 lck->lockx.in.lock_cnt = SVAL(req->in.vwv, VWV(7));
1802 total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1804 /* there are two variants, one with 64 bit offsets and counts */
1805 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1811 /* make sure we got the promised data */
1812 if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1813 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1817 /* allocate the locks array */
1819 lck->lockx.in.locks = talloc_array(req, struct smb_lock_entry,
1821 if (lck->lockx.in.locks == NULL) {
1822 smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1829 /* construct the locks array */
1830 for (i=0;i<total_locks;i++) {
1831 uint32_t ofs_high=0, count_high=0;
1833 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1835 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1836 ofs_high = IVAL(p, 4);
1837 lck->lockx.in.locks[i].offset = IVAL(p, 8);
1838 count_high = IVAL(p, 12);
1839 lck->lockx.in.locks[i].count = IVAL(p, 16);
1841 lck->lockx.in.locks[i].offset = IVAL(p, 2);
1842 lck->lockx.in.locks[i].count = IVAL(p, 6);
1844 if (ofs_high != 0 || count_high != 0) {
1845 lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32;
1846 lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1851 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1852 req->async_states->send_fn = reply_lockingX_send;
1853 req->async_states->private_data = lck;
1856 req->async_states->status = ntvfs_lock(req, lck);
1861 /****************************************************************************
1862 Reply to a SMBreadbmpx (read block multiplex) request.
1863 ****************************************************************************/
1864 void smbsrv_reply_readbmpx(struct smbsrv_request *req)
1866 /* tell the client to not use a multiplexed read - its too broken to use */
1867 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1871 /****************************************************************************
1872 Reply to a SMBsetattrE.
1873 ****************************************************************************/
1874 void smbsrv_reply_setattrE(struct smbsrv_request *req)
1876 union smb_setfileinfo *info;
1879 REQ_CHECK_WCT(req, 7);
1880 REQ_TALLOC(info, union smb_setfileinfo);
1882 info->setattre.level = RAW_SFILEINFO_SETATTRE;
1883 info->setattre.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1884 info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1885 info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1886 info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1888 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1889 req->async_states->send_fn = reply_simple_send;
1892 req->async_states->status = ntvfs_setfileinfo(req, info);
1898 /****************************************************************************
1899 Reply to a SMBwritebmpx (write block multiplex primary) request.
1900 ****************************************************************************/
1901 void smbsrv_reply_writebmpx(struct smbsrv_request *req)
1903 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1907 /****************************************************************************
1908 Reply to a SMBwritebs (write block multiplex secondary) request.
1909 ****************************************************************************/
1910 void smbsrv_reply_writebs(struct smbsrv_request *req)
1912 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1917 /****************************************************************************
1918 Reply to a SMBgetattrE (async reply)
1919 ****************************************************************************/
1920 static void reply_getattrE_send(struct smbsrv_request *req)
1922 union smb_fileinfo *info = req->async_states->private_data;
1927 smbsrv_setup_reply(req, 11, 0);
1929 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1930 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1931 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1932 SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
1933 SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
1934 SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
1936 smbsrv_send_reply(req);
1939 /****************************************************************************
1940 Reply to a SMBgetattrE.
1941 ****************************************************************************/
1942 void smbsrv_reply_getattrE(struct smbsrv_request *req)
1944 union smb_fileinfo *info;
1947 REQ_CHECK_WCT(req, 1);
1948 REQ_TALLOC(info, union smb_fileinfo);
1950 info->getattr.level = RAW_FILEINFO_GETATTRE;
1951 info->getattr.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1953 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
1954 req->async_states->send_fn = reply_getattrE_send;
1955 req->async_states->private_data = info;
1958 req->async_states->status = ntvfs_qfileinfo(req, info);
1964 /****************************************************************************
1965 reply to an old style session setup command
1966 ****************************************************************************/
1967 static void reply_sesssetup_old(struct smbsrv_request *req)
1970 union smb_sesssetup sess;
1974 sess.old.level = RAW_SESSSETUP_OLD;
1977 sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1978 sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1979 sess.old.in.vc_num = SVAL(req->in.vwv, VWV(4));
1980 sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1981 passlen = SVAL(req->in.vwv, VWV(7));
1983 /* check the request isn't malformed */
1984 if (req_data_oob(req, req->in.data, passlen)) {
1985 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1990 if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1991 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1996 p += req_pull_string(req, &sess.old.in.user, p, -1, STR_TERMINATE);
1997 p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1998 p += req_pull_string(req, &sess.old.in.os, p, -1, STR_TERMINATE);
1999 p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
2001 /* call the generic handler */
2002 status = smbsrv_sesssetup_backend(req, &sess);
2004 if (!NT_STATUS_IS_OK(status)) {
2005 smbsrv_send_error(req, status);
2009 /* construct reply */
2010 smbsrv_setup_reply(req, 3, 0);
2012 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2013 SSVAL(req->out.vwv, VWV(1), 0);
2014 SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
2016 SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
2018 smbsrv_chain_reply(req);
2022 /****************************************************************************
2023 reply to an NT1 style session setup command
2024 ****************************************************************************/
2025 static void reply_sesssetup_nt1(struct smbsrv_request *req)
2028 union smb_sesssetup sess;
2030 uint16_t passlen1, passlen2;
2032 sess.nt1.level = RAW_SESSSETUP_NT1;
2035 sess.nt1.in.bufsize = SVAL(req->in.vwv, VWV(2));
2036 sess.nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2037 sess.nt1.in.vc_num = SVAL(req->in.vwv, VWV(4));
2038 sess.nt1.in.sesskey = IVAL(req->in.vwv, VWV(5));
2039 passlen1 = SVAL(req->in.vwv, VWV(7));
2040 passlen2 = SVAL(req->in.vwv, VWV(8));
2041 sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
2043 /* check the request isn't malformed */
2044 if (req_data_oob(req, req->in.data, passlen1) ||
2045 req_data_oob(req, req->in.data + passlen1, passlen2)) {
2046 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2051 if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
2052 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2056 if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
2057 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2062 p += req_pull_string(req, &sess.nt1.in.user, p, -1, STR_TERMINATE);
2063 p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
2064 p += req_pull_string(req, &sess.nt1.in.os, p, -1, STR_TERMINATE);
2065 p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
2067 /* call the generic handler */
2068 status = smbsrv_sesssetup_backend(req, &sess);
2070 if (!NT_STATUS_IS_OK(status)) {
2071 smbsrv_send_error(req, status);
2075 /* construct reply */
2076 smbsrv_setup_reply(req, 3, 0);
2078 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2079 SSVAL(req->out.vwv, VWV(1), 0);
2080 SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
2082 SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
2084 req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
2085 req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
2086 req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
2088 smbsrv_chain_reply(req);
2092 /****************************************************************************
2093 reply to an SPNEGO style session setup command
2094 ****************************************************************************/
2095 static void reply_sesssetup_spnego(struct smbsrv_request *req)
2098 union smb_sesssetup sess;
2102 sess.spnego.level = RAW_SESSSETUP_SPNEGO;
2105 sess.spnego.in.bufsize = SVAL(req->in.vwv, VWV(2));
2106 sess.spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3));
2107 sess.spnego.in.vc_num = SVAL(req->in.vwv, VWV(4));
2108 sess.spnego.in.sesskey = IVAL(req->in.vwv, VWV(5));
2109 blob_len = SVAL(req->in.vwv, VWV(7));
2110 sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
2113 if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
2114 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2119 p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE);
2120 p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE);
2121 p += req_pull_string(req, &sess.spnego.in.workgroup, p, -1, STR_TERMINATE);
2123 /* call the generic handler */
2124 status = smbsrv_sesssetup_backend(req, &sess);
2126 if (!NT_STATUS_IS_OK(status) &&
2127 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2128 smbsrv_send_error(req, status);
2132 /* construct reply */
2133 smbsrv_setup_reply(req, 4, sess.spnego.out.secblob.length);
2135 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2136 smbsrv_setup_error(req, status);
2139 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2140 SSVAL(req->out.vwv, VWV(1), 0);
2141 SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
2142 SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
2144 SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
2146 memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
2147 req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
2148 req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
2149 req_push_str(req, NULL, sess.spnego.out.workgroup, -1, STR_TERMINATE);
2151 smbsrv_chain_reply(req);
2155 /****************************************************************************
2156 reply to a session setup command
2157 ****************************************************************************/
2158 void smbsrv_reply_sesssetup(struct smbsrv_request *req)
2160 switch (req->in.wct) {
2162 /* a pre-NT1 call */
2163 reply_sesssetup_old(req);
2167 reply_sesssetup_nt1(req);
2171 reply_sesssetup_spnego(req);
2175 /* unsupported variant */
2176 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2179 /****************************************************************************
2180 Reply to a SMBulogoffX.
2181 ****************************************************************************/
2182 void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
2184 struct smbsrv_tcon *tcon;
2187 if (!req->session) {
2188 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
2192 /* in user level security we are supposed to close any files
2193 open by this user on all open tree connects */
2194 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
2196 status = ntvfs_logoff(req);
2198 if (!NT_STATUS_IS_OK(status)) {
2199 smbsrv_send_error(req, status);
2204 talloc_free(req->session);
2205 req->session = NULL; /* it is now invalid, don't use on
2206 any chained packets */
2208 smbsrv_setup_reply(req, 2, 0);
2210 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2211 SSVAL(req->out.vwv, VWV(1), 0);
2213 smbsrv_chain_reply(req);
2217 /****************************************************************************
2218 Reply to an SMBfindclose request
2219 ****************************************************************************/
2220 void smbsrv_reply_findclose(struct smbsrv_request *req)
2223 union smb_search_close io;
2225 io.findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2228 REQ_CHECK_WCT(req, 1);
2230 io.findclose.in.handle = SVAL(req->in.vwv, VWV(0));
2233 status = ntvfs_search_close(req, &io);
2235 if (!NT_STATUS_IS_OK(status)) {
2236 smbsrv_send_error(req, status);
2240 /* construct reply */
2241 smbsrv_setup_reply(req, 0, 0);
2243 smbsrv_send_reply(req);
2246 /****************************************************************************
2247 Reply to an SMBfindnclose request
2248 ****************************************************************************/
2249 void smbsrv_reply_findnclose(struct smbsrv_request *req)
2251 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2255 /****************************************************************************
2256 Reply to an SMBntcreateX request (async send)
2257 ****************************************************************************/
2258 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
2260 union smb_open *io = req->async_states->private_data;
2264 /* construct reply */
2265 smbsrv_setup_reply(req, 34, 0);
2267 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2268 SSVAL(req->out.vwv, VWV(1), 0);
2269 SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2271 /* the rest of the parameters are not aligned! */
2272 SSVAL(req->out.vwv, 5, io->ntcreatex.file.fnum);
2273 SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
2274 push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2275 push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2276 push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2277 push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2278 SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
2279 SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
2280 SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
2281 SSVAL(req->out.vwv, 63, io->ntcreatex.out.file_type);
2282 SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
2283 SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
2285 req->chained_fnum = io->ntcreatex.file.fnum;
2287 smbsrv_chain_reply(req);
2290 /****************************************************************************
2291 Reply to an SMBntcreateX request
2292 ****************************************************************************/
2293 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request *req)
2298 /* parse the request */
2299 REQ_CHECK_WCT(req, 24);
2300 REQ_TALLOC(io, union smb_open);
2302 io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2304 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2305 fname_len = SVAL(req->in.vwv, 5);
2306 io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
2307 io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
2308 io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
2309 io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
2310 io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
2311 io->ntcreatex.in.share_access = IVAL(req->in.vwv, 31);
2312 io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2313 io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
2314 io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
2315 io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
2316 io->ntcreatex.in.ea_list = NULL;
2317 io->ntcreatex.in.sec_desc = NULL;
2319 /* we need a neater way to handle this alignment */
2320 if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
2321 ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2325 req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2326 if (!io->ntcreatex.in.fname) {
2327 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2331 req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
2332 req->async_states->send_fn = reply_ntcreate_and_X_send;
2333 req->async_states->private_data = io;
2335 /* call the backend */
2336 req->async_states->status = ntvfs_open(req, io);
2342 /****************************************************************************
2343 Reply to an SMBntcancel request
2344 ****************************************************************************/
2345 void smbsrv_reply_ntcancel(struct smbsrv_request *req)
2347 /* NOTE: this request does not generate a reply */
2352 /****************************************************************************
2353 Reply to an SMBsends request
2354 ****************************************************************************/
2355 void smbsrv_reply_sends(struct smbsrv_request *req)
2357 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2360 /****************************************************************************
2361 Reply to an SMBsendstrt request
2362 ****************************************************************************/
2363 void smbsrv_reply_sendstrt(struct smbsrv_request *req)
2365 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2368 /****************************************************************************
2369 Reply to an SMBsendend request
2370 ****************************************************************************/
2371 void smbsrv_reply_sendend(struct smbsrv_request *req)
2373 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2376 /****************************************************************************
2377 Reply to an SMBsendtxt request
2378 ****************************************************************************/
2379 void smbsrv_reply_sendtxt(struct smbsrv_request *req)
2381 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2386 parse the called/calling names from session request
2388 static NTSTATUS parse_session_request(struct smbsrv_request *req)
2393 blob.data = req->in.buffer + 4;
2394 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2395 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2397 req->smb_conn->negotiate.called_name = talloc(req->smb_conn, struct nbt_name);
2398 req->smb_conn->negotiate.calling_name = talloc(req->smb_conn, struct nbt_name);
2399 if (req->smb_conn->negotiate.called_name == NULL ||
2400 req->smb_conn->negotiate.calling_name == NULL) {
2401 return NT_STATUS_NO_MEMORY;
2404 status = nbt_name_from_blob(req->smb_conn, &blob,
2405 req->smb_conn->negotiate.called_name);
2406 NT_STATUS_NOT_OK_RETURN(status);
2408 blob.data += blob.length;
2409 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2410 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2412 status = nbt_name_from_blob(req->smb_conn, &blob,
2413 req->smb_conn->negotiate.calling_name);
2414 NT_STATUS_NOT_OK_RETURN(status);
2416 req->smb_conn->negotiate.done_nbt_session = True;
2418 return NT_STATUS_OK;
2423 /****************************************************************************
2424 Reply to a special message - a SMB packet with non zero NBT message type
2425 ****************************************************************************/
2426 void smbsrv_reply_special(struct smbsrv_request *req)
2429 uint8_t *buf = talloc_zero_array(req, uint8_t, 4);
2431 msg_type = CVAL(req->in.buffer,0);
2436 case 0x81: /* session request */
2437 if (req->smb_conn->negotiate.done_nbt_session) {
2438 DEBUG(0,("Warning: ignoring secondary session request\n"));
2445 /* we don't check the status - samba always accepts session
2446 requests for any name */
2447 parse_session_request(req);
2449 req->out.buffer = buf;
2451 smbsrv_send_reply_nosign(req);
2454 case 0x89: /* session keepalive request
2455 (some old clients produce this?) */
2456 SCVAL(buf, 0, SMBkeepalive);
2458 req->out.buffer = buf;
2460 smbsrv_send_reply_nosign(req);
2464 /* session keepalive - swallow it */
2469 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));