2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-2003
5 Copyright (C) James J Myers 2003 <myersjj@samba.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "smb_server/smb_server.h"
28 #include "ntvfs/ntvfs.h"
29 #include "librpc/gen_ndr/ndr_nbt.h"
32 /****************************************************************************
33 Reply to a simple request (async send)
34 ****************************************************************************/
35 static void reply_simple_send(struct ntvfs_request *ntvfs)
37 struct smbsrv_request *req;
39 SMBSRV_CHECK_ASYNC_STATUS_SIMPLE;
41 smbsrv_setup_reply(req, 0, 0);
42 smbsrv_send_reply(req);
46 /****************************************************************************
48 ****************************************************************************/
49 void smbsrv_reply_tcon(struct smbsrv_request *req)
56 SMBSRV_CHECK_WCT(req, 0);
58 con.tcon.level = RAW_TCON_TCON;
61 p += req_pull_ascii4(req, &con.tcon.in.service, p, STR_TERMINATE);
62 p += req_pull_ascii4(req, &con.tcon.in.password, p, STR_TERMINATE);
63 p += req_pull_ascii4(req, &con.tcon.in.dev, p, STR_TERMINATE);
65 if (!con.tcon.in.service || !con.tcon.in.password || !con.tcon.in.dev) {
66 smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
71 status = smbsrv_tcon_backend(req, &con);
73 if (!NT_STATUS_IS_OK(status)) {
74 smbsrv_send_error(req, status);
79 smbsrv_setup_reply(req, 2, 0);
81 SSVAL(req->out.vwv, VWV(0), con.tcon.out.max_xmit);
82 SSVAL(req->out.vwv, VWV(1), con.tcon.out.tid);
83 SSVAL(req->out.hdr, HDR_TID, req->tcon->tid);
85 smbsrv_send_reply(req);
89 /****************************************************************************
90 Reply to a tcon and X.
91 ****************************************************************************/
92 void smbsrv_reply_tcon_and_X(struct smbsrv_request *req)
99 con.tconx.level = RAW_TCON_TCONX;
102 SMBSRV_CHECK_WCT(req, 4);
104 con.tconx.in.flags = SVAL(req->in.vwv, VWV(2));
105 passlen = SVAL(req->in.vwv, VWV(3));
109 if (!req_pull_blob(req, p, passlen, &con.tconx.in.password)) {
110 smbsrv_send_error(req, NT_STATUS_ILL_FORMED_PASSWORD);
115 p += req_pull_string(req, &con.tconx.in.path, p, -1, STR_TERMINATE);
116 p += req_pull_string(req, &con.tconx.in.device, p, -1, STR_ASCII);
118 if (!con.tconx.in.path || !con.tconx.in.device) {
119 smbsrv_send_error(req, NT_STATUS_BAD_DEVICE_TYPE);
124 status = smbsrv_tcon_backend(req, &con);
126 if (!NT_STATUS_IS_OK(status)) {
127 smbsrv_send_error(req, status);
131 /* construct reply - two variants */
132 if (req->smb_conn->negotiate.protocol < PROTOCOL_NT1) {
133 smbsrv_setup_reply(req, 2, 0);
135 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
136 SSVAL(req->out.vwv, VWV(1), 0);
138 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
140 smbsrv_setup_reply(req, 3, 0);
142 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
143 SSVAL(req->out.vwv, VWV(1), 0);
144 SSVAL(req->out.vwv, VWV(2), con.tconx.out.options);
146 req_push_str(req, NULL, con.tconx.out.dev_type, -1, STR_TERMINATE|STR_ASCII);
147 req_push_str(req, NULL, con.tconx.out.fs_type, -1, STR_TERMINATE);
150 /* set the incoming and outgoing tid to the just created one */
151 SSVAL(req->in.hdr, HDR_TID, con.tconx.out.tid);
152 SSVAL(req->out.hdr,HDR_TID, con.tconx.out.tid);
154 smbsrv_chain_reply(req);
158 /****************************************************************************
159 Reply to an unknown request
160 ****************************************************************************/
161 void smbsrv_reply_unknown(struct smbsrv_request *req)
165 type = CVAL(req->in.hdr, HDR_COM);
167 DEBUG(0,("unknown command type %d (0x%X)\n", type, type));
169 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRunknownsmb));
173 /****************************************************************************
174 Reply to an ioctl (async reply)
175 ****************************************************************************/
176 static void reply_ioctl_send(struct ntvfs_request *ntvfs)
178 struct smbsrv_request *req;
181 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_ioctl);
183 /* the +1 is for nicer alignment */
184 smbsrv_setup_reply(req, 8, io->ioctl.out.blob.length+1);
185 SSVAL(req->out.vwv, VWV(1), io->ioctl.out.blob.length);
186 SSVAL(req->out.vwv, VWV(5), io->ioctl.out.blob.length);
187 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(req->out.data, req->out.hdr) + 1);
189 memcpy(req->out.data+1, io->ioctl.out.blob.data, io->ioctl.out.blob.length);
191 smbsrv_send_reply(req);
194 /****************************************************************************
196 ****************************************************************************/
197 void smbsrv_reply_ioctl(struct smbsrv_request *req)
202 SMBSRV_CHECK_WCT(req, 3);
203 SMBSRV_TALLOC_IO_PTR(io, union smb_ioctl);
204 SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
206 io->ioctl.level = RAW_IOCTL_IOCTL;
207 io->ioctl.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
208 io->ioctl.in.request = IVAL(req->in.vwv, VWV(1));
211 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req->ntvfs, io));
215 /****************************************************************************
217 ****************************************************************************/
218 void smbsrv_reply_chkpth(struct smbsrv_request *req)
220 union smb_chkpath *io;
222 SMBSRV_TALLOC_IO_PTR(io, union smb_chkpath);
223 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
225 req_pull_ascii4(req, &io->chkpath.in.path, req->in.data, STR_TERMINATE);
227 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_chkpath(req->ntvfs, io));
230 /****************************************************************************
231 Reply to a getatr (async reply)
232 ****************************************************************************/
233 static void reply_getatr_send(struct ntvfs_request *ntvfs)
235 struct smbsrv_request *req;
236 union smb_fileinfo *st;
238 SMBSRV_CHECK_ASYNC_STATUS(st, union smb_fileinfo);
240 /* construct reply */
241 smbsrv_setup_reply(req, 10, 0);
243 SSVAL(req->out.vwv, VWV(0), st->getattr.out.attrib);
244 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(1), st->getattr.out.write_time);
245 SIVAL(req->out.vwv, VWV(3), st->getattr.out.size);
247 SMBSRV_VWV_RESERVED(5, 5);
249 smbsrv_send_reply(req);
253 /****************************************************************************
255 ****************************************************************************/
256 void smbsrv_reply_getatr(struct smbsrv_request *req)
258 union smb_fileinfo *st;
260 SMBSRV_TALLOC_IO_PTR(st, union smb_fileinfo);
261 SMBSRV_SETUP_NTVFS_REQUEST(reply_getatr_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
263 st->getattr.level = RAW_FILEINFO_GETATTR;
266 req_pull_ascii4(req, &st->getattr.in.file.path, req->in.data, STR_TERMINATE);
267 if (!st->getattr.in.file.path) {
268 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
272 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qpathinfo(req->ntvfs, st));
276 /****************************************************************************
278 ****************************************************************************/
279 void smbsrv_reply_setatr(struct smbsrv_request *req)
281 union smb_setfileinfo *st;
284 SMBSRV_CHECK_WCT(req, 8);
285 SMBSRV_TALLOC_IO_PTR(st, union smb_setfileinfo);
286 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
288 st->setattr.level = RAW_SFILEINFO_SETATTR;
289 st->setattr.in.attrib = SVAL(req->in.vwv, VWV(0));
290 st->setattr.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
292 req_pull_ascii4(req, &st->setattr.in.file.path, req->in.data, STR_TERMINATE);
294 if (!st->setattr.in.file.path) {
295 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
299 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setpathinfo(req->ntvfs, st));
303 /****************************************************************************
304 Reply to a dskattr (async reply)
305 ****************************************************************************/
306 static void reply_dskattr_send(struct ntvfs_request *ntvfs)
308 struct smbsrv_request *req;
309 union smb_fsinfo *fs;
311 SMBSRV_CHECK_ASYNC_STATUS(fs, union smb_fsinfo);
313 /* construct reply */
314 smbsrv_setup_reply(req, 5, 0);
316 SSVAL(req->out.vwv, VWV(0), fs->dskattr.out.units_total);
317 SSVAL(req->out.vwv, VWV(1), fs->dskattr.out.blocks_per_unit);
318 SSVAL(req->out.vwv, VWV(2), fs->dskattr.out.block_size);
319 SSVAL(req->out.vwv, VWV(3), fs->dskattr.out.units_free);
321 SMBSRV_VWV_RESERVED(4, 1);
323 smbsrv_send_reply(req);
327 /****************************************************************************
329 ****************************************************************************/
330 void smbsrv_reply_dskattr(struct smbsrv_request *req)
332 union smb_fsinfo *fs;
334 SMBSRV_TALLOC_IO_PTR(fs, union smb_fsinfo);
335 SMBSRV_SETUP_NTVFS_REQUEST(reply_dskattr_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
337 fs->dskattr.level = RAW_QFS_DSKATTR;
339 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_fsinfo(req->ntvfs, fs));
343 /****************************************************************************
344 Reply to an open (async reply)
345 ****************************************************************************/
346 static void reply_open_send(struct ntvfs_request *ntvfs)
348 struct smbsrv_request *req;
351 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
353 /* construct reply */
354 smbsrv_setup_reply(req, 7, 0);
356 SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum);
357 SSVAL(req->out.vwv, VWV(1), oi->openold.out.attrib);
358 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(2), oi->openold.out.write_time);
359 SIVAL(req->out.vwv, VWV(4), oi->openold.out.size);
360 SSVAL(req->out.vwv, VWV(6), oi->openold.out.rmode);
362 smbsrv_send_reply(req);
365 /****************************************************************************
367 ****************************************************************************/
368 void smbsrv_reply_open(struct smbsrv_request *req)
373 SMBSRV_CHECK_WCT(req, 2);
374 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
375 SMBSRV_SETUP_NTVFS_REQUEST(reply_open_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
377 oi->openold.level = RAW_OPEN_OPEN;
378 oi->openold.in.open_mode = SVAL(req->in.vwv, VWV(0));
379 oi->openold.in.search_attrs = SVAL(req->in.vwv, VWV(1));
381 req_pull_ascii4(req, &oi->openold.in.fname, req->in.data, STR_TERMINATE);
383 if (!oi->openold.in.fname) {
384 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
388 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
392 /****************************************************************************
393 Reply to an open and X (async reply)
394 ****************************************************************************/
395 static void reply_open_and_X_send(struct ntvfs_request *ntvfs)
397 struct smbsrv_request *req;
400 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
402 /* build the reply */
403 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
404 smbsrv_setup_reply(req, 19, 0);
406 smbsrv_setup_reply(req, 15, 0);
409 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
410 SSVAL(req->out.vwv, VWV(1), 0);
411 SSVAL(req->out.vwv, VWV(2), oi->openx.out.file.fnum);
412 SSVAL(req->out.vwv, VWV(3), oi->openx.out.attrib);
413 srv_push_dos_date3(req->smb_conn, req->out.vwv, VWV(4), oi->openx.out.write_time);
414 SIVAL(req->out.vwv, VWV(6), oi->openx.out.size);
415 SSVAL(req->out.vwv, VWV(8), oi->openx.out.access);
416 SSVAL(req->out.vwv, VWV(9), oi->openx.out.ftype);
417 SSVAL(req->out.vwv, VWV(10),oi->openx.out.devstate);
418 SSVAL(req->out.vwv, VWV(11),oi->openx.out.action);
419 SIVAL(req->out.vwv, VWV(12),oi->openx.out.unique_fid);
420 SSVAL(req->out.vwv, VWV(14),0); /* reserved */
421 if (oi->openx.in.flags & OPENX_FLAGS_EXTENDED_RETURN) {
422 SIVAL(req->out.vwv, VWV(15),oi->openx.out.access_mask);
423 SMBSRV_VWV_RESERVED(17, 2);
426 req->chained_fnum = oi->openx.out.file.fnum;
428 smbsrv_chain_reply(req);
432 /****************************************************************************
433 Reply to an open and X.
434 ****************************************************************************/
435 void smbsrv_reply_open_and_X(struct smbsrv_request *req)
439 /* parse the request */
440 SMBSRV_CHECK_WCT(req, 15);
441 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
442 SMBSRV_SETUP_NTVFS_REQUEST(reply_open_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
444 oi->openx.level = RAW_OPEN_OPENX;
445 oi->openx.in.flags = SVAL(req->in.vwv, VWV(2));
446 oi->openx.in.open_mode = SVAL(req->in.vwv, VWV(3));
447 oi->openx.in.search_attrs = SVAL(req->in.vwv, VWV(4));
448 oi->openx.in.file_attrs = SVAL(req->in.vwv, VWV(5));
449 oi->openx.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(6));
450 oi->openx.in.open_func = SVAL(req->in.vwv, VWV(8));
451 oi->openx.in.size = IVAL(req->in.vwv, VWV(9));
452 oi->openx.in.timeout = IVAL(req->in.vwv, VWV(11));
454 req_pull_ascii4(req, &oi->openx.in.fname, req->in.data, STR_TERMINATE);
456 if (!oi->openx.in.fname) {
457 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
461 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
465 /****************************************************************************
466 Reply to a mknew or a create.
467 ****************************************************************************/
468 static void reply_mknew_send(struct ntvfs_request *ntvfs)
470 struct smbsrv_request *req;
473 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
475 /* build the reply */
476 smbsrv_setup_reply(req, 1, 0);
478 SSVAL(req->out.vwv, VWV(0), oi->mknew.out.file.fnum);
480 smbsrv_send_reply(req);
484 /****************************************************************************
485 Reply to a mknew or a create.
486 ****************************************************************************/
487 void smbsrv_reply_mknew(struct smbsrv_request *req)
491 /* parse the request */
492 SMBSRV_CHECK_WCT(req, 3);
493 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
494 SMBSRV_SETUP_NTVFS_REQUEST(reply_mknew_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
496 if (CVAL(req->in.hdr, HDR_COM) == SMBmknew) {
497 oi->mknew.level = RAW_OPEN_MKNEW;
499 oi->mknew.level = RAW_OPEN_CREATE;
501 oi->mknew.in.attrib = SVAL(req->in.vwv, VWV(0));
502 oi->mknew.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
504 req_pull_ascii4(req, &oi->mknew.in.fname, req->in.data, STR_TERMINATE);
506 if (!oi->mknew.in.fname) {
507 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
511 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
514 /****************************************************************************
515 Reply to a create temporary file (async reply)
516 ****************************************************************************/
517 static void reply_ctemp_send(struct ntvfs_request *ntvfs)
519 struct smbsrv_request *req;
522 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
524 /* build the reply */
525 smbsrv_setup_reply(req, 1, 0);
527 SSVAL(req->out.vwv, VWV(0), oi->ctemp.out.file.fnum);
529 /* the returned filename is relative to the directory */
530 req_push_str(req, NULL, oi->ctemp.out.name, -1, STR_TERMINATE | STR_ASCII);
532 smbsrv_send_reply(req);
535 /****************************************************************************
536 Reply to a create temporary file.
537 ****************************************************************************/
538 void smbsrv_reply_ctemp(struct smbsrv_request *req)
542 /* parse the request */
543 SMBSRV_CHECK_WCT(req, 3);
544 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
545 SMBSRV_SETUP_NTVFS_REQUEST(reply_ctemp_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
547 oi->ctemp.level = RAW_OPEN_CTEMP;
548 oi->ctemp.in.attrib = SVAL(req->in.vwv, VWV(0));
549 oi->ctemp.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
551 /* the filename is actually a directory name, the server provides a filename
553 req_pull_ascii4(req, &oi->ctemp.in.directory, req->in.data, STR_TERMINATE);
555 if (!oi->ctemp.in.directory) {
556 smbsrv_send_error(req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
560 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
564 /****************************************************************************
566 ****************************************************************************/
567 void smbsrv_reply_unlink(struct smbsrv_request *req)
569 union smb_unlink *unl;
571 /* parse the request */
572 SMBSRV_CHECK_WCT(req, 1);
573 SMBSRV_TALLOC_IO_PTR(unl, union smb_unlink);
574 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
576 unl->unlink.in.attrib = SVAL(req->in.vwv, VWV(0));
578 req_pull_ascii4(req, &unl->unlink.in.pattern, req->in.data, STR_TERMINATE);
580 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_unlink(req->ntvfs, unl));
584 /****************************************************************************
585 Reply to a readbraw (core+ protocol).
586 this is a strange packet because it doesn't use a standard SMB header in the reply,
587 only the 4 byte NBT header
588 This command must be replied to synchronously
589 ****************************************************************************/
590 void smbsrv_reply_readbraw(struct smbsrv_request *req)
595 io.readbraw.level = RAW_READ_READBRAW;
597 /* there are two variants, one with 10 and one with 8 command words */
598 if (req->in.wct < 8) {
602 io.readbraw.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
603 io.readbraw.in.offset = IVAL(req->in.vwv, VWV(1));
604 io.readbraw.in.maxcnt = SVAL(req->in.vwv, VWV(3));
605 io.readbraw.in.mincnt = SVAL(req->in.vwv, VWV(4));
606 io.readbraw.in.timeout = IVAL(req->in.vwv, VWV(5));
608 /* the 64 bit variant */
609 if (req->in.wct == 10) {
610 uint32_t offset_high = IVAL(req->in.vwv, VWV(8));
611 io.readbraw.in.offset |= (((off_t)offset_high) << 32);
614 /* before calling the backend we setup the raw buffer. This
615 * saves a copy later */
616 req->out.size = io.readbraw.in.maxcnt + NBT_HDR_SIZE;
617 req->out.buffer = talloc_size(req, req->out.size);
618 if (req->out.buffer == NULL) {
621 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
623 /* tell the backend where to put the data */
624 io.readbraw.out.data = req->out.buffer + NBT_HDR_SIZE;
626 /* prepare the ntvfs request */
627 req->ntvfs = ntvfs_request_create(req->tcon->ntvfs, req,
628 req->session->session_info,
629 SVAL(req->in.hdr,HDR_PID),
630 SVAL(req->in.hdr,HDR_MID),
637 /* call the backend */
638 status = ntvfs_read(req->ntvfs, &io);
639 if (!NT_STATUS_IS_OK(status)) {
643 req->out.size = io.readbraw.out.nread + NBT_HDR_SIZE;
645 smbsrv_send_reply_nosign(req);
649 /* any failure in readbraw is equivalent to reading zero bytes */
651 req->out.buffer = talloc_size(req, req->out.size);
652 SIVAL(req->out.buffer, 0, 0); /* init NBT header */
654 smbsrv_send_reply_nosign(req);
658 /****************************************************************************
659 Reply to a lockread (async reply)
660 ****************************************************************************/
661 static void reply_lockread_send(struct ntvfs_request *ntvfs)
663 struct smbsrv_request *req;
666 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
669 io->lockread.out.nread = MIN(io->lockread.out.nread,
670 req_max_data(req) - 3);
671 req_grow_data(req, 3 + io->lockread.out.nread);
673 /* construct reply */
674 SSVAL(req->out.vwv, VWV(0), io->lockread.out.nread);
675 SMBSRV_VWV_RESERVED(1, 4);
677 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
678 SSVAL(req->out.data, 1, io->lockread.out.nread);
680 smbsrv_send_reply(req);
684 /****************************************************************************
685 Reply to a lockread (core+ protocol).
686 note that the lock is a write lock, not a read lock!
687 ****************************************************************************/
688 void smbsrv_reply_lockread(struct smbsrv_request *req)
693 SMBSRV_CHECK_WCT(req, 5);
694 SMBSRV_TALLOC_IO_PTR(io, union smb_read);
695 SMBSRV_SETUP_NTVFS_REQUEST(reply_lockread_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
697 io->lockread.level = RAW_READ_LOCKREAD;
698 io->lockread.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
699 io->lockread.in.count = SVAL(req->in.vwv, VWV(1));
700 io->lockread.in.offset = IVAL(req->in.vwv, VWV(2));
701 io->lockread.in.remaining = SVAL(req->in.vwv, VWV(4));
703 /* setup the reply packet assuming the maximum possible read */
704 smbsrv_setup_reply(req, 5, 3 + io->lockread.in.count);
706 /* tell the backend where to put the data */
707 io->lockread.out.data = req->out.data + 3;
709 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
714 /****************************************************************************
715 Reply to a read (async reply)
716 ****************************************************************************/
717 static void reply_read_send(struct ntvfs_request *ntvfs)
719 struct smbsrv_request *req;
722 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
725 io->read.out.nread = MIN(io->read.out.nread,
726 req_max_data(req) - 3);
727 req_grow_data(req, 3 + io->read.out.nread);
729 /* construct reply */
730 SSVAL(req->out.vwv, VWV(0), io->read.out.nread);
731 SMBSRV_VWV_RESERVED(1, 4);
733 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
734 SSVAL(req->out.data, 1, io->read.out.nread);
736 smbsrv_send_reply(req);
739 /****************************************************************************
741 ****************************************************************************/
742 void smbsrv_reply_read(struct smbsrv_request *req)
747 SMBSRV_CHECK_WCT(req, 5);
748 SMBSRV_TALLOC_IO_PTR(io, union smb_read);
749 SMBSRV_SETUP_NTVFS_REQUEST(reply_read_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
751 io->read.level = RAW_READ_READ;
752 io->read.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
753 io->read.in.count = SVAL(req->in.vwv, VWV(1));
754 io->read.in.offset = IVAL(req->in.vwv, VWV(2));
755 io->read.in.remaining = SVAL(req->in.vwv, VWV(4));
757 /* setup the reply packet assuming the maximum possible read */
758 smbsrv_setup_reply(req, 5, 3 + io->read.in.count);
760 /* tell the backend where to put the data */
761 io->read.out.data = req->out.data + 3;
763 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
766 /****************************************************************************
767 Reply to a read and X (async reply)
768 ****************************************************************************/
769 static void reply_read_and_X_send(struct ntvfs_request *ntvfs)
771 struct smbsrv_request *req;
774 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_read);
776 /* readx reply packets can be over-sized */
777 req->control_flags |= SMBSRV_REQ_CONTROL_LARGE;
778 if (io->readx.in.maxcnt != 0xFFFF &&
779 io->readx.in.mincnt != 0xFFFF) {
780 req_grow_data(req, 1 + io->readx.out.nread);
781 SCVAL(req->out.data, 0, 0); /* padding */
783 req_grow_data(req, io->readx.out.nread);
786 /* construct reply */
787 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
788 SSVAL(req->out.vwv, VWV(1), 0);
789 SSVAL(req->out.vwv, VWV(2), io->readx.out.remaining);
790 SSVAL(req->out.vwv, VWV(3), io->readx.out.compaction_mode);
791 SMBSRV_VWV_RESERVED(4, 1);
792 SSVAL(req->out.vwv, VWV(5), io->readx.out.nread);
793 SSVAL(req->out.vwv, VWV(6), PTR_DIFF(io->readx.out.data, req->out.hdr));
794 SMBSRV_VWV_RESERVED(7, 5);
796 smbsrv_chain_reply(req);
799 /****************************************************************************
800 Reply to a read and X.
801 ****************************************************************************/
802 void smbsrv_reply_read_and_X(struct smbsrv_request *req)
807 if (req->in.wct != 12) {
808 SMBSRV_CHECK_WCT(req, 10);
811 SMBSRV_TALLOC_IO_PTR(io, union smb_read);
812 SMBSRV_SETUP_NTVFS_REQUEST(reply_read_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
814 io->readx.level = RAW_READ_READX;
815 io->readx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
816 io->readx.in.offset = IVAL(req->in.vwv, VWV(3));
817 io->readx.in.maxcnt = SVAL(req->in.vwv, VWV(5));
818 io->readx.in.mincnt = SVAL(req->in.vwv, VWV(6));
819 io->readx.in.remaining = SVAL(req->in.vwv, VWV(9));
820 if (req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) {
821 io->readx.in.read_for_execute = True;
823 io->readx.in.read_for_execute = False;
826 if (req->smb_conn->negotiate.client_caps & CAP_LARGE_READX) {
827 uint32_t high_part = IVAL(req->in.vwv, VWV(7));
828 if (high_part == 1) {
829 io->readx.in.maxcnt |= high_part << 16;
833 /* the 64 bit variant */
834 if (req->in.wct == 12) {
835 uint32_t offset_high = IVAL(req->in.vwv, VWV(10));
836 io->readx.in.offset |= (((uint64_t)offset_high) << 32);
839 /* setup the reply packet assuming the maximum possible read */
840 smbsrv_setup_reply(req, 12, 1 + io->readx.in.maxcnt);
842 /* tell the backend where to put the data. Notice the pad byte. */
843 if (io->readx.in.maxcnt != 0xFFFF &&
844 io->readx.in.mincnt != 0xFFFF) {
845 io->readx.out.data = req->out.data + 1;
847 io->readx.out.data = req->out.data;
850 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req->ntvfs, io));
854 /****************************************************************************
855 Reply to a writebraw (core+ or LANMAN1.0 protocol).
856 ****************************************************************************/
857 void smbsrv_reply_writebraw(struct smbsrv_request *req)
859 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
863 /****************************************************************************
864 Reply to a writeunlock (async reply)
865 ****************************************************************************/
866 static void reply_writeunlock_send(struct ntvfs_request *ntvfs)
868 struct smbsrv_request *req;
871 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
873 /* construct reply */
874 smbsrv_setup_reply(req, 1, 0);
876 SSVAL(req->out.vwv, VWV(0), io->writeunlock.out.nwritten);
878 smbsrv_send_reply(req);
881 /****************************************************************************
882 Reply to a writeunlock (core+).
883 ****************************************************************************/
884 void smbsrv_reply_writeunlock(struct smbsrv_request *req)
888 SMBSRV_CHECK_WCT(req, 5);
889 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
890 SMBSRV_SETUP_NTVFS_REQUEST(reply_writeunlock_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
892 io->writeunlock.level = RAW_WRITE_WRITEUNLOCK;
893 io->writeunlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
894 io->writeunlock.in.count = SVAL(req->in.vwv, VWV(1));
895 io->writeunlock.in.offset = IVAL(req->in.vwv, VWV(2));
896 io->writeunlock.in.remaining = SVAL(req->in.vwv, VWV(4));
897 io->writeunlock.in.data = req->in.data + 3;
899 /* make sure they gave us the data they promised */
900 if (io->writeunlock.in.count+3 > req->in.data_size) {
901 smbsrv_send_error(req, NT_STATUS_FOOBAR);
905 /* make sure the data block is big enough */
906 if (SVAL(req->in.data, 1) < io->writeunlock.in.count) {
907 smbsrv_send_error(req, NT_STATUS_FOOBAR);
911 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
916 /****************************************************************************
917 Reply to a write (async reply)
918 ****************************************************************************/
919 static void reply_write_send(struct ntvfs_request *ntvfs)
921 struct smbsrv_request *req;
924 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
926 /* construct reply */
927 smbsrv_setup_reply(req, 1, 0);
929 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
931 smbsrv_send_reply(req);
934 /****************************************************************************
936 ****************************************************************************/
937 void smbsrv_reply_write(struct smbsrv_request *req)
941 SMBSRV_CHECK_WCT(req, 5);
942 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
943 SMBSRV_SETUP_NTVFS_REQUEST(reply_write_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
945 io->write.level = RAW_WRITE_WRITE;
946 io->write.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
947 io->write.in.count = SVAL(req->in.vwv, VWV(1));
948 io->write.in.offset = IVAL(req->in.vwv, VWV(2));
949 io->write.in.remaining = SVAL(req->in.vwv, VWV(4));
950 io->write.in.data = req->in.data + 3;
952 /* make sure they gave us the data they promised */
953 if (req_data_oob(req, io->write.in.data, io->write.in.count)) {
954 smbsrv_send_error(req, NT_STATUS_FOOBAR);
958 /* make sure the data block is big enough */
959 if (SVAL(req->in.data, 1) < io->write.in.count) {
960 smbsrv_send_error(req, NT_STATUS_FOOBAR);
964 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
968 /****************************************************************************
969 Reply to a write and X (async reply)
970 ****************************************************************************/
971 static void reply_write_and_X_send(struct ntvfs_request *ntvfs)
973 struct smbsrv_request *req;
976 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
978 /* construct reply */
979 smbsrv_setup_reply(req, 6, 0);
981 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
982 SSVAL(req->out.vwv, VWV(1), 0);
983 SSVAL(req->out.vwv, VWV(2), io->writex.out.nwritten & 0xFFFF);
984 SSVAL(req->out.vwv, VWV(3), io->writex.out.remaining);
985 SSVAL(req->out.vwv, VWV(4), io->writex.out.nwritten >> 16);
986 SMBSRV_VWV_RESERVED(5, 1);
988 smbsrv_chain_reply(req);
991 /****************************************************************************
992 Reply to a write and X.
993 ****************************************************************************/
994 void smbsrv_reply_write_and_X(struct smbsrv_request *req)
998 if (req->in.wct != 14) {
999 SMBSRV_CHECK_WCT(req, 12);
1002 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1003 SMBSRV_SETUP_NTVFS_REQUEST(reply_write_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1005 io->writex.level = RAW_WRITE_WRITEX;
1006 io->writex.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
1007 io->writex.in.offset = IVAL(req->in.vwv, VWV(3));
1008 io->writex.in.wmode = SVAL(req->in.vwv, VWV(7));
1009 io->writex.in.remaining = SVAL(req->in.vwv, VWV(8));
1010 io->writex.in.count = SVAL(req->in.vwv, VWV(10));
1011 io->writex.in.data = req->in.hdr + SVAL(req->in.vwv, VWV(11));
1013 if (req->in.wct == 14) {
1014 uint32_t offset_high = IVAL(req->in.vwv, VWV(12));
1015 uint16_t count_high = SVAL(req->in.vwv, VWV(9));
1016 io->writex.in.offset |= (((uint64_t)offset_high) << 32);
1017 io->writex.in.count |= ((uint32_t)count_high) << 16;
1020 /* make sure the data is in bounds */
1021 if (req_data_oob(req, io->writex.in.data, io->writex.in.count)) {
1022 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1026 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1030 /****************************************************************************
1031 Reply to a lseek (async reply)
1032 ****************************************************************************/
1033 static void reply_lseek_send(struct ntvfs_request *ntvfs)
1035 struct smbsrv_request *req;
1038 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_seek);
1040 /* construct reply */
1041 smbsrv_setup_reply(req, 2, 0);
1043 SIVALS(req->out.vwv, VWV(0), io->lseek.out.offset);
1045 smbsrv_send_reply(req);
1048 /****************************************************************************
1050 ****************************************************************************/
1051 void smbsrv_reply_lseek(struct smbsrv_request *req)
1055 SMBSRV_CHECK_WCT(req, 4);
1056 SMBSRV_TALLOC_IO_PTR(io, union smb_seek);
1057 SMBSRV_SETUP_NTVFS_REQUEST(reply_lseek_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1059 io->lseek.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1060 io->lseek.in.mode = SVAL(req->in.vwv, VWV(1));
1061 io->lseek.in.offset = IVALS(req->in.vwv, VWV(2));
1063 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_seek(req->ntvfs, io));
1066 /****************************************************************************
1068 ****************************************************************************/
1069 void smbsrv_reply_flush(struct smbsrv_request *req)
1071 union smb_flush *io;
1074 SMBSRV_CHECK_WCT(req, 1);
1075 SMBSRV_TALLOC_IO_PTR(io, union smb_flush);
1076 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1078 io->flush.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1080 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_flush(req->ntvfs, io));
1084 /****************************************************************************
1085 Reply to a exit. This closes all files open by a smbpid
1086 ****************************************************************************/
1087 void smbsrv_reply_exit(struct smbsrv_request *req)
1090 struct smbsrv_tcon *tcon;
1091 SMBSRV_CHECK_WCT(req, 0);
1093 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
1095 SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
1096 status = ntvfs_exit(req->ntvfs);
1097 talloc_free(req->ntvfs);
1100 if (!NT_STATUS_IS_OK(status)) {
1101 smbsrv_send_error(req, status);
1106 smbsrv_setup_reply(req, 0, 0);
1107 smbsrv_send_reply(req);
1111 /****************************************************************************
1114 Note that this has to deal with closing a directory opened by NT SMB's.
1115 ****************************************************************************/
1116 void smbsrv_reply_close(struct smbsrv_request *req)
1118 union smb_close *io;
1121 SMBSRV_CHECK_WCT(req, 3);
1122 SMBSRV_TALLOC_IO_PTR(io, union smb_close);
1123 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1125 io->close.level = RAW_CLOSE_CLOSE;
1126 io->close.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1127 io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
1129 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
1133 /****************************************************************************
1134 Reply to a writeclose (async reply)
1135 ****************************************************************************/
1136 static void reply_writeclose_send(struct ntvfs_request *ntvfs)
1138 struct smbsrv_request *req;
1139 union smb_write *io;
1141 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_write);
1143 /* construct reply */
1144 smbsrv_setup_reply(req, 1, 0);
1146 SSVAL(req->out.vwv, VWV(0), io->write.out.nwritten);
1148 smbsrv_send_reply(req);
1151 /****************************************************************************
1152 Reply to a writeclose (Core+ protocol).
1153 ****************************************************************************/
1154 void smbsrv_reply_writeclose(struct smbsrv_request *req)
1156 union smb_write *io;
1158 /* this one is pretty weird - the wct can be 6 or 12 */
1159 if (req->in.wct != 12) {
1160 SMBSRV_CHECK_WCT(req, 6);
1163 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1164 SMBSRV_SETUP_NTVFS_REQUEST(reply_writeclose_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1166 io->writeclose.level = RAW_WRITE_WRITECLOSE;
1167 io->writeclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1168 io->writeclose.in.count = SVAL(req->in.vwv, VWV(1));
1169 io->writeclose.in.offset = IVAL(req->in.vwv, VWV(2));
1170 io->writeclose.in.mtime = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(4));
1171 io->writeclose.in.data = req->in.data + 1;
1173 /* make sure they gave us the data they promised */
1174 if (req_data_oob(req, io->writeclose.in.data, io->writeclose.in.count)) {
1175 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1179 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1182 /****************************************************************************
1184 ****************************************************************************/
1185 void smbsrv_reply_lock(struct smbsrv_request *req)
1187 union smb_lock *lck;
1190 SMBSRV_CHECK_WCT(req, 5);
1191 SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1192 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1194 lck->lock.level = RAW_LOCK_LOCK;
1195 lck->lock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1196 lck->lock.in.count = IVAL(req->in.vwv, VWV(1));
1197 lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
1199 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1203 /****************************************************************************
1205 ****************************************************************************/
1206 void smbsrv_reply_unlock(struct smbsrv_request *req)
1208 union smb_lock *lck;
1211 SMBSRV_CHECK_WCT(req, 5);
1212 SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1213 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1215 lck->unlock.level = RAW_LOCK_UNLOCK;
1216 lck->unlock.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1217 lck->unlock.in.count = IVAL(req->in.vwv, VWV(1));
1218 lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
1220 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1224 /****************************************************************************
1226 ****************************************************************************/
1227 void smbsrv_reply_tdis(struct smbsrv_request *req)
1229 SMBSRV_CHECK_WCT(req, 0);
1231 talloc_free(req->tcon);
1234 /* construct reply */
1235 smbsrv_setup_reply(req, 0, 0);
1237 smbsrv_send_reply(req);
1241 /****************************************************************************
1242 Reply to a echo. This is one of the few calls that is handled directly (the
1243 backends don't see it at all)
1244 ****************************************************************************/
1245 void smbsrv_reply_echo(struct smbsrv_request *req)
1250 SMBSRV_CHECK_WCT(req, 0);
1252 count = SVAL(req->in.vwv, VWV(0));
1254 smbsrv_setup_reply(req, 1, req->in.data_size);
1256 memcpy(req->out.data, req->in.data, req->in.data_size);
1258 for (i=1; i <= count;i++) {
1259 struct smbsrv_request *this_req;
1262 this_req = smbsrv_setup_secondary_request(req);
1267 SSVAL(this_req->out.vwv, VWV(0), i);
1268 smbsrv_send_reply(this_req);
1274 /****************************************************************************
1275 Reply to a printopen (async reply)
1276 ****************************************************************************/
1277 static void reply_printopen_send(struct ntvfs_request *ntvfs)
1279 struct smbsrv_request *req;
1282 SMBSRV_CHECK_ASYNC_STATUS(oi, union smb_open);
1284 /* construct reply */
1285 smbsrv_setup_reply(req, 1, 0);
1287 SSVAL(req->out.vwv, VWV(0), oi->openold.out.file.fnum);
1289 smbsrv_send_reply(req);
1292 /****************************************************************************
1293 Reply to a printopen.
1294 ****************************************************************************/
1295 void smbsrv_reply_printopen(struct smbsrv_request *req)
1300 SMBSRV_CHECK_WCT(req, 2);
1301 SMBSRV_TALLOC_IO_PTR(oi, union smb_open);
1302 SMBSRV_SETUP_NTVFS_REQUEST(reply_printopen_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1304 oi->splopen.level = RAW_OPEN_SPLOPEN;
1305 oi->splopen.in.setup_length = SVAL(req->in.vwv, VWV(0));
1306 oi->splopen.in.mode = SVAL(req->in.vwv, VWV(1));
1308 req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
1310 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, oi));
1313 /****************************************************************************
1314 Reply to a printclose.
1315 ****************************************************************************/
1316 void smbsrv_reply_printclose(struct smbsrv_request *req)
1318 union smb_close *io;
1321 SMBSRV_CHECK_WCT(req, 3);
1322 SMBSRV_TALLOC_IO_PTR(io, union smb_close);
1323 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1325 io->splclose.level = RAW_CLOSE_SPLCLOSE;
1326 io->splclose.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1328 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req->ntvfs, io));
1331 /****************************************************************************
1332 Reply to a printqueue.
1333 ****************************************************************************/
1334 static void reply_printqueue_send(struct ntvfs_request *ntvfs)
1336 struct smbsrv_request *req;
1339 const uint_t el_size = 28;
1341 SMBSRV_CHECK_ASYNC_STATUS(lpq,union smb_lpq);
1343 /* construct reply */
1344 smbsrv_setup_reply(req, 2, 0);
1346 /* truncate the returned list to fit in the negotiated buffer size */
1347 maxcount = (req_max_data(req) - 3) / el_size;
1348 if (maxcount < lpq->retq.out.count) {
1349 lpq->retq.out.count = maxcount;
1352 /* setup enough space in the reply */
1353 req_grow_data(req, 3 + el_size*lpq->retq.out.count);
1355 /* and fill it in */
1356 SSVAL(req->out.vwv, VWV(0), lpq->retq.out.count);
1357 SSVAL(req->out.vwv, VWV(1), lpq->retq.out.restart_idx);
1359 SCVAL(req->out.data, 0, SMB_DATA_BLOCK);
1360 SSVAL(req->out.data, 1, el_size*lpq->retq.out.count);
1362 req->out.ptr = req->out.data + 3;
1364 for (i=0;i<lpq->retq.out.count;i++) {
1365 srv_push_dos_date2(req->smb_conn, req->out.ptr, 0 , lpq->retq.out.queue[i].time);
1366 SCVAL(req->out.ptr, 4, lpq->retq.out.queue[i].status);
1367 SSVAL(req->out.ptr, 5, lpq->retq.out.queue[i].job);
1368 SIVAL(req->out.ptr, 7, lpq->retq.out.queue[i].size);
1369 SCVAL(req->out.ptr, 11, 0); /* reserved */
1370 req_push_str(req, req->out.ptr+12, lpq->retq.out.queue[i].user, 16, STR_ASCII);
1371 req->out.ptr += el_size;
1374 smbsrv_send_reply(req);
1377 /****************************************************************************
1378 Reply to a printqueue.
1379 ****************************************************************************/
1380 void smbsrv_reply_printqueue(struct smbsrv_request *req)
1385 SMBSRV_CHECK_WCT(req, 2);
1386 SMBSRV_TALLOC_IO_PTR(lpq, union smb_lpq);
1387 SMBSRV_SETUP_NTVFS_REQUEST(reply_printqueue_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1389 lpq->retq.level = RAW_LPQ_RETQ;
1390 lpq->retq.in.maxcount = SVAL(req->in.vwv, VWV(0));
1391 lpq->retq.in.startidx = SVAL(req->in.vwv, VWV(1));
1393 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lpq(req->ntvfs, lpq));
1397 /****************************************************************************
1398 Reply to a printwrite.
1399 ****************************************************************************/
1400 void smbsrv_reply_printwrite(struct smbsrv_request *req)
1402 union smb_write *io;
1405 SMBSRV_CHECK_WCT(req, 1);
1406 SMBSRV_TALLOC_IO_PTR(io, union smb_write);
1407 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1409 io->splwrite.level = RAW_WRITE_SPLWRITE;
1411 if (req->in.data_size < 3) {
1412 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1416 io->splwrite.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1417 io->splwrite.in.count = SVAL(req->in.data, 1);
1418 io->splwrite.in.data = req->in.data + 3;
1420 /* make sure they gave us the data they promised */
1421 if (req_data_oob(req, io->splwrite.in.data, io->splwrite.in.count)) {
1422 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1426 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req->ntvfs, io));
1430 /****************************************************************************
1432 ****************************************************************************/
1433 void smbsrv_reply_mkdir(struct smbsrv_request *req)
1435 union smb_mkdir *io;
1437 /* parse the request */
1438 SMBSRV_CHECK_WCT(req, 0);
1439 SMBSRV_TALLOC_IO_PTR(io, union smb_mkdir);
1440 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1442 io->generic.level = RAW_MKDIR_MKDIR;
1443 req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
1445 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_mkdir(req->ntvfs, io));
1449 /****************************************************************************
1451 ****************************************************************************/
1452 void smbsrv_reply_rmdir(struct smbsrv_request *req)
1454 struct smb_rmdir *io;
1456 /* parse the request */
1457 SMBSRV_CHECK_WCT(req, 0);
1458 SMBSRV_TALLOC_IO_PTR(io, struct smb_rmdir);
1459 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1461 req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
1463 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rmdir(req->ntvfs, io));
1467 /****************************************************************************
1469 ****************************************************************************/
1470 void smbsrv_reply_mv(struct smbsrv_request *req)
1472 union smb_rename *io;
1475 /* parse the request */
1476 SMBSRV_CHECK_WCT(req, 1);
1477 SMBSRV_TALLOC_IO_PTR(io, union smb_rename);
1478 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1480 io->generic.level = RAW_RENAME_RENAME;
1481 io->rename.in.attrib = SVAL(req->in.vwv, VWV(0));
1484 p += req_pull_ascii4(req, &io->rename.in.pattern1, p, STR_TERMINATE);
1485 p += req_pull_ascii4(req, &io->rename.in.pattern2, p, STR_TERMINATE);
1487 if (!io->rename.in.pattern1 || !io->rename.in.pattern2) {
1488 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1492 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req->ntvfs, io));
1496 /****************************************************************************
1497 Reply to an NT rename.
1498 ****************************************************************************/
1499 void smbsrv_reply_ntrename(struct smbsrv_request *req)
1501 union smb_rename *io;
1504 /* parse the request */
1505 SMBSRV_CHECK_WCT(req, 4);
1506 SMBSRV_TALLOC_IO_PTR(io, union smb_rename);
1507 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1509 io->generic.level = RAW_RENAME_NTRENAME;
1510 io->ntrename.in.attrib = SVAL(req->in.vwv, VWV(0));
1511 io->ntrename.in.flags = SVAL(req->in.vwv, VWV(1));
1512 io->ntrename.in.cluster_size = IVAL(req->in.vwv, VWV(2));
1515 p += req_pull_ascii4(req, &io->ntrename.in.old_name, p, STR_TERMINATE);
1516 p += req_pull_ascii4(req, &io->ntrename.in.new_name, p, STR_TERMINATE);
1518 if (!io->ntrename.in.old_name || !io->ntrename.in.new_name) {
1519 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1523 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req->ntvfs, io));
1526 /****************************************************************************
1527 Reply to a file copy (async reply)
1528 ****************************************************************************/
1529 static void reply_copy_send(struct ntvfs_request *ntvfs)
1531 struct smbsrv_request *req;
1532 struct smb_copy *cp;
1534 SMBSRV_CHECK_ASYNC_STATUS(cp, struct smb_copy);
1536 /* build the reply */
1537 smbsrv_setup_reply(req, 1, 0);
1539 SSVAL(req->out.vwv, VWV(0), cp->out.count);
1541 smbsrv_send_reply(req);
1544 /****************************************************************************
1545 Reply to a file copy.
1546 ****************************************************************************/
1547 void smbsrv_reply_copy(struct smbsrv_request *req)
1549 struct smb_copy *cp;
1553 SMBSRV_CHECK_WCT(req, 3);
1554 SMBSRV_TALLOC_IO_PTR(cp, struct smb_copy);
1555 SMBSRV_SETUP_NTVFS_REQUEST(reply_copy_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1557 cp->in.tid2 = SVAL(req->in.vwv, VWV(0));
1558 cp->in.ofun = SVAL(req->in.vwv, VWV(1));
1559 cp->in.flags = SVAL(req->in.vwv, VWV(2));
1562 p += req_pull_ascii4(req, &cp->in.path1, p, STR_TERMINATE);
1563 p += req_pull_ascii4(req, &cp->in.path2, p, STR_TERMINATE);
1565 if (!cp->in.path1 || !cp->in.path2) {
1566 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1570 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_copy(req->ntvfs, cp));
1573 /****************************************************************************
1574 Reply to a lockingX request (async send)
1575 ****************************************************************************/
1576 static void reply_lockingX_send(struct ntvfs_request *ntvfs)
1578 struct smbsrv_request *req;
1579 union smb_lock *lck;
1581 SMBSRV_CHECK_ASYNC_STATUS(lck, union smb_lock);
1583 /* if it was an oplock break ack then we only send a reply if
1584 there was an error */
1585 if (lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt == 0) {
1590 /* construct reply */
1591 smbsrv_setup_reply(req, 2, 0);
1593 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1594 SSVAL(req->out.vwv, VWV(1), 0);
1596 smbsrv_chain_reply(req);
1600 /****************************************************************************
1601 Reply to a lockingX request.
1602 ****************************************************************************/
1603 void smbsrv_reply_lockingX(struct smbsrv_request *req)
1605 union smb_lock *lck;
1606 uint_t total_locks, i;
1611 SMBSRV_CHECK_WCT(req, 8);
1612 SMBSRV_TALLOC_IO_PTR(lck, union smb_lock);
1613 SMBSRV_SETUP_NTVFS_REQUEST(reply_lockingX_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1615 lck->lockx.level = RAW_LOCK_LOCKX;
1616 lck->lockx.in.file.fnum = req_fnum(req, req->in.vwv, VWV(2));
1617 lck->lockx.in.mode = SVAL(req->in.vwv, VWV(3));
1618 lck->lockx.in.timeout = IVAL(req->in.vwv, VWV(4));
1619 lck->lockx.in.ulock_cnt = SVAL(req->in.vwv, VWV(6));
1620 lck->lockx.in.lock_cnt = SVAL(req->in.vwv, VWV(7));
1622 total_locks = lck->lockx.in.ulock_cnt + lck->lockx.in.lock_cnt;
1624 /* there are two variants, one with 64 bit offsets and counts */
1625 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1631 /* make sure we got the promised data */
1632 if (req_data_oob(req, req->in.data, total_locks * lck_size)) {
1633 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1637 /* allocate the locks array */
1639 lck->lockx.in.locks = talloc_array(req, struct smb_lock_entry,
1641 if (lck->lockx.in.locks == NULL) {
1642 smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
1649 /* construct the locks array */
1650 for (i=0;i<total_locks;i++) {
1651 uint32_t ofs_high=0, count_high=0;
1653 lck->lockx.in.locks[i].pid = SVAL(p, 0);
1655 if (lck->lockx.in.mode & LOCKING_ANDX_LARGE_FILES) {
1656 ofs_high = IVAL(p, 4);
1657 lck->lockx.in.locks[i].offset = IVAL(p, 8);
1658 count_high = IVAL(p, 12);
1659 lck->lockx.in.locks[i].count = IVAL(p, 16);
1661 lck->lockx.in.locks[i].offset = IVAL(p, 2);
1662 lck->lockx.in.locks[i].count = IVAL(p, 6);
1664 if (ofs_high != 0 || count_high != 0) {
1665 lck->lockx.in.locks[i].count |= ((uint64_t)count_high) << 32;
1666 lck->lockx.in.locks[i].offset |= ((uint64_t)ofs_high) << 32;
1671 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, lck));
1674 /****************************************************************************
1675 Reply to a SMBreadbmpx (read block multiplex) request.
1676 ****************************************************************************/
1677 void smbsrv_reply_readbmpx(struct smbsrv_request *req)
1679 /* tell the client to not use a multiplexed read - its too broken to use */
1680 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1684 /****************************************************************************
1685 Reply to a SMBsetattrE.
1686 ****************************************************************************/
1687 void smbsrv_reply_setattrE(struct smbsrv_request *req)
1689 union smb_setfileinfo *info;
1692 SMBSRV_CHECK_WCT(req, 7);
1693 SMBSRV_TALLOC_IO_PTR(info, union smb_setfileinfo);
1694 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1696 info->setattre.level = RAW_SFILEINFO_SETATTRE;
1697 info->setattre.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1698 info->setattre.in.create_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(1));
1699 info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
1700 info->setattre.in.write_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
1702 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setfileinfo(req->ntvfs, info));
1706 /****************************************************************************
1707 Reply to a SMBwritebmpx (write block multiplex primary) request.
1708 ****************************************************************************/
1709 void smbsrv_reply_writebmpx(struct smbsrv_request *req)
1711 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1715 /****************************************************************************
1716 Reply to a SMBwritebs (write block multiplex secondary) request.
1717 ****************************************************************************/
1718 void smbsrv_reply_writebs(struct smbsrv_request *req)
1720 smbsrv_send_error(req, NT_STATUS_DOS(ERRSRV, ERRuseSTD));
1725 /****************************************************************************
1726 Reply to a SMBgetattrE (async reply)
1727 ****************************************************************************/
1728 static void reply_getattrE_send(struct ntvfs_request *ntvfs)
1730 struct smbsrv_request *req;
1731 union smb_fileinfo *info;
1733 SMBSRV_CHECK_ASYNC_STATUS(info, union smb_fileinfo);
1736 smbsrv_setup_reply(req, 11, 0);
1738 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(0), info->getattre.out.create_time);
1739 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(2), info->getattre.out.access_time);
1740 srv_push_dos_date2(req->smb_conn, req->out.vwv, VWV(4), info->getattre.out.write_time);
1741 SIVAL(req->out.vwv, VWV(6), info->getattre.out.size);
1742 SIVAL(req->out.vwv, VWV(8), info->getattre.out.alloc_size);
1743 SSVAL(req->out.vwv, VWV(10), info->getattre.out.attrib);
1745 smbsrv_send_reply(req);
1748 /****************************************************************************
1749 Reply to a SMBgetattrE.
1750 ****************************************************************************/
1751 void smbsrv_reply_getattrE(struct smbsrv_request *req)
1753 union smb_fileinfo *info;
1756 SMBSRV_CHECK_WCT(req, 1);
1757 SMBSRV_TALLOC_IO_PTR(info, union smb_fileinfo);
1758 SMBSRV_SETUP_NTVFS_REQUEST(reply_getattrE_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
1760 info->getattr.level = RAW_FILEINFO_GETATTRE;
1761 info->getattr.in.file.fnum = req_fnum(req, req->in.vwv, VWV(0));
1763 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qfileinfo(req->ntvfs, info));
1767 /****************************************************************************
1768 reply to an old style session setup command
1769 ****************************************************************************/
1770 static void reply_sesssetup_old(struct smbsrv_request *req)
1773 union smb_sesssetup sess;
1777 sess.old.level = RAW_SESSSETUP_OLD;
1780 sess.old.in.bufsize = SVAL(req->in.vwv, VWV(2));
1781 sess.old.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1782 sess.old.in.vc_num = SVAL(req->in.vwv, VWV(4));
1783 sess.old.in.sesskey = IVAL(req->in.vwv, VWV(5));
1784 passlen = SVAL(req->in.vwv, VWV(7));
1786 /* check the request isn't malformed */
1787 if (req_data_oob(req, req->in.data, passlen)) {
1788 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1793 if (!req_pull_blob(req, p, passlen, &sess.old.in.password)) {
1794 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1799 p += req_pull_string(req, &sess.old.in.user, p, -1, STR_TERMINATE);
1800 p += req_pull_string(req, &sess.old.in.domain, p, -1, STR_TERMINATE);
1801 p += req_pull_string(req, &sess.old.in.os, p, -1, STR_TERMINATE);
1802 p += req_pull_string(req, &sess.old.in.lanman, p, -1, STR_TERMINATE);
1804 /* call the generic handler */
1805 status = smbsrv_sesssetup_backend(req, &sess);
1807 if (!NT_STATUS_IS_OK(status)) {
1808 smbsrv_send_error(req, status);
1812 /* construct reply */
1813 smbsrv_setup_reply(req, 3, 0);
1815 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1816 SSVAL(req->out.vwv, VWV(1), 0);
1817 SSVAL(req->out.vwv, VWV(2), sess.old.out.action);
1819 SSVAL(req->out.hdr, HDR_UID, sess.old.out.vuid);
1821 smbsrv_chain_reply(req);
1825 /****************************************************************************
1826 reply to an NT1 style session setup command
1827 ****************************************************************************/
1828 static void reply_sesssetup_nt1(struct smbsrv_request *req)
1831 union smb_sesssetup sess;
1833 uint16_t passlen1, passlen2;
1835 sess.nt1.level = RAW_SESSSETUP_NT1;
1838 sess.nt1.in.bufsize = SVAL(req->in.vwv, VWV(2));
1839 sess.nt1.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1840 sess.nt1.in.vc_num = SVAL(req->in.vwv, VWV(4));
1841 sess.nt1.in.sesskey = IVAL(req->in.vwv, VWV(5));
1842 passlen1 = SVAL(req->in.vwv, VWV(7));
1843 passlen2 = SVAL(req->in.vwv, VWV(8));
1844 sess.nt1.in.capabilities = IVAL(req->in.vwv, VWV(11));
1846 /* check the request isn't malformed */
1847 if (req_data_oob(req, req->in.data, passlen1) ||
1848 req_data_oob(req, req->in.data + passlen1, passlen2)) {
1849 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1854 if (!req_pull_blob(req, p, passlen1, &sess.nt1.in.password1)) {
1855 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1859 if (!req_pull_blob(req, p, passlen2, &sess.nt1.in.password2)) {
1860 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1865 p += req_pull_string(req, &sess.nt1.in.user, p, -1, STR_TERMINATE);
1866 p += req_pull_string(req, &sess.nt1.in.domain, p, -1, STR_TERMINATE);
1867 p += req_pull_string(req, &sess.nt1.in.os, p, -1, STR_TERMINATE);
1868 p += req_pull_string(req, &sess.nt1.in.lanman, p, -1, STR_TERMINATE);
1870 /* call the generic handler */
1871 status = smbsrv_sesssetup_backend(req, &sess);
1873 if (!NT_STATUS_IS_OK(status)) {
1874 smbsrv_send_error(req, status);
1878 /* construct reply */
1879 smbsrv_setup_reply(req, 3, 0);
1881 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1882 SSVAL(req->out.vwv, VWV(1), 0);
1883 SSVAL(req->out.vwv, VWV(2), sess.nt1.out.action);
1885 SSVAL(req->out.hdr, HDR_UID, sess.nt1.out.vuid);
1887 req_push_str(req, NULL, sess.nt1.out.os, -1, STR_TERMINATE);
1888 req_push_str(req, NULL, sess.nt1.out.lanman, -1, STR_TERMINATE);
1889 req_push_str(req, NULL, sess.nt1.out.domain, -1, STR_TERMINATE);
1891 smbsrv_chain_reply(req);
1895 /****************************************************************************
1896 reply to an SPNEGO style session setup command
1897 ****************************************************************************/
1898 static void reply_sesssetup_spnego(struct smbsrv_request *req)
1901 union smb_sesssetup sess;
1905 sess.spnego.level = RAW_SESSSETUP_SPNEGO;
1908 sess.spnego.in.bufsize = SVAL(req->in.vwv, VWV(2));
1909 sess.spnego.in.mpx_max = SVAL(req->in.vwv, VWV(3));
1910 sess.spnego.in.vc_num = SVAL(req->in.vwv, VWV(4));
1911 sess.spnego.in.sesskey = IVAL(req->in.vwv, VWV(5));
1912 blob_len = SVAL(req->in.vwv, VWV(7));
1913 sess.spnego.in.capabilities = IVAL(req->in.vwv, VWV(10));
1916 if (!req_pull_blob(req, p, blob_len, &sess.spnego.in.secblob)) {
1917 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1922 p += req_pull_string(req, &sess.spnego.in.os, p, -1, STR_TERMINATE);
1923 p += req_pull_string(req, &sess.spnego.in.lanman, p, -1, STR_TERMINATE);
1924 p += req_pull_string(req, &sess.spnego.in.workgroup, p, -1, STR_TERMINATE);
1926 /* call the generic handler */
1927 status = smbsrv_sesssetup_backend(req, &sess);
1929 if (!NT_STATUS_IS_OK(status) &&
1930 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1931 smbsrv_send_error(req, status);
1935 /* construct reply */
1936 smbsrv_setup_reply(req, 4, sess.spnego.out.secblob.length);
1938 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1939 smbsrv_setup_error(req, status);
1942 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
1943 SSVAL(req->out.vwv, VWV(1), 0);
1944 SSVAL(req->out.vwv, VWV(2), sess.spnego.out.action);
1945 SSVAL(req->out.vwv, VWV(3), sess.spnego.out.secblob.length);
1947 SSVAL(req->out.hdr, HDR_UID, sess.spnego.out.vuid);
1949 memcpy(req->out.data, sess.spnego.out.secblob.data, sess.spnego.out.secblob.length);
1950 req_push_str(req, NULL, sess.spnego.out.os, -1, STR_TERMINATE);
1951 req_push_str(req, NULL, sess.spnego.out.lanman, -1, STR_TERMINATE);
1952 req_push_str(req, NULL, sess.spnego.out.workgroup, -1, STR_TERMINATE);
1954 smbsrv_chain_reply(req);
1958 /****************************************************************************
1959 reply to a session setup command
1960 ****************************************************************************/
1961 void smbsrv_reply_sesssetup(struct smbsrv_request *req)
1963 switch (req->in.wct) {
1965 /* a pre-NT1 call */
1966 reply_sesssetup_old(req);
1970 reply_sesssetup_nt1(req);
1974 reply_sesssetup_spnego(req);
1978 /* unsupported variant */
1979 smbsrv_send_error(req, NT_STATUS_FOOBAR);
1982 /****************************************************************************
1983 Reply to a SMBulogoffX.
1984 ****************************************************************************/
1985 void smbsrv_reply_ulogoffX(struct smbsrv_request *req)
1987 struct smbsrv_tcon *tcon;
1990 /* in user level security we are supposed to close any files
1991 open by this user on all open tree connects */
1992 for (tcon=req->smb_conn->smb_tcons.list;tcon;tcon=tcon->next) {
1994 SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
1995 status = ntvfs_logoff(req->ntvfs);
1996 talloc_free(req->ntvfs);
1999 if (!NT_STATUS_IS_OK(status)) {
2000 smbsrv_send_error(req, status);
2005 talloc_free(req->session);
2006 req->session = NULL; /* it is now invalid, don't use on
2007 any chained packets */
2009 smbsrv_setup_reply(req, 2, 0);
2011 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2012 SSVAL(req->out.vwv, VWV(1), 0);
2014 smbsrv_chain_reply(req);
2017 /****************************************************************************
2018 Reply to an SMBfindclose request
2019 ****************************************************************************/
2020 void smbsrv_reply_findclose(struct smbsrv_request *req)
2022 union smb_search_close *io;
2025 SMBSRV_CHECK_WCT(req, 1);
2026 SMBSRV_TALLOC_IO_PTR(io, union smb_search_close);
2027 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
2029 io->findclose.level = RAW_FINDCLOSE_FINDCLOSE;
2030 io->findclose.in.handle = SVAL(req->in.vwv, VWV(0));
2032 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_close(req->ntvfs, io));
2035 /****************************************************************************
2036 Reply to an SMBfindnclose request
2037 ****************************************************************************/
2038 void smbsrv_reply_findnclose(struct smbsrv_request *req)
2040 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2044 /****************************************************************************
2045 Reply to an SMBntcreateX request (async send)
2046 ****************************************************************************/
2047 static void reply_ntcreate_and_X_send(struct ntvfs_request *ntvfs)
2049 struct smbsrv_request *req;
2052 SMBSRV_CHECK_ASYNC_STATUS(io, union smb_open);
2054 /* construct reply */
2055 smbsrv_setup_reply(req, 34, 0);
2057 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
2058 SSVAL(req->out.vwv, VWV(1), 0);
2059 SCVAL(req->out.vwv, VWV(2), io->ntcreatex.out.oplock_level);
2061 /* the rest of the parameters are not aligned! */
2062 SSVAL(req->out.vwv, 5, io->ntcreatex.out.file.fnum);
2063 SIVAL(req->out.vwv, 7, io->ntcreatex.out.create_action);
2064 push_nttime(req->out.vwv, 11, io->ntcreatex.out.create_time);
2065 push_nttime(req->out.vwv, 19, io->ntcreatex.out.access_time);
2066 push_nttime(req->out.vwv, 27, io->ntcreatex.out.write_time);
2067 push_nttime(req->out.vwv, 35, io->ntcreatex.out.change_time);
2068 SIVAL(req->out.vwv, 43, io->ntcreatex.out.attrib);
2069 SBVAL(req->out.vwv, 47, io->ntcreatex.out.alloc_size);
2070 SBVAL(req->out.vwv, 55, io->ntcreatex.out.size);
2071 SSVAL(req->out.vwv, 63, io->ntcreatex.out.file_type);
2072 SSVAL(req->out.vwv, 65, io->ntcreatex.out.ipc_state);
2073 SCVAL(req->out.vwv, 67, io->ntcreatex.out.is_directory);
2075 req->chained_fnum = io->ntcreatex.out.file.fnum;
2077 smbsrv_chain_reply(req);
2080 /****************************************************************************
2081 Reply to an SMBntcreateX request
2082 ****************************************************************************/
2083 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request *req)
2088 /* parse the request */
2089 SMBSRV_CHECK_WCT(req, 24);
2090 SMBSRV_TALLOC_IO_PTR(io, union smb_open);
2091 SMBSRV_SETUP_NTVFS_REQUEST(reply_ntcreate_and_X_send, NTVFS_ASYNC_STATE_MAY_ASYNC);
2093 io->ntcreatex.level = RAW_OPEN_NTCREATEX;
2095 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2096 fname_len = SVAL(req->in.vwv, 5);
2097 io->ntcreatex.in.flags = IVAL(req->in.vwv, 7);
2098 io->ntcreatex.in.root_fid = IVAL(req->in.vwv, 11);
2099 io->ntcreatex.in.access_mask = IVAL(req->in.vwv, 15);
2100 io->ntcreatex.in.alloc_size = BVAL(req->in.vwv, 19);
2101 io->ntcreatex.in.file_attr = IVAL(req->in.vwv, 27);
2102 io->ntcreatex.in.share_access = IVAL(req->in.vwv, 31);
2103 io->ntcreatex.in.open_disposition = IVAL(req->in.vwv, 35);
2104 io->ntcreatex.in.create_options = IVAL(req->in.vwv, 39);
2105 io->ntcreatex.in.impersonation = IVAL(req->in.vwv, 43);
2106 io->ntcreatex.in.security_flags = CVAL(req->in.vwv, 47);
2107 io->ntcreatex.in.ea_list = NULL;
2108 io->ntcreatex.in.sec_desc = NULL;
2110 /* we need a neater way to handle this alignment */
2111 if ((req->flags2 & FLAGS2_UNICODE_STRINGS) &&
2112 ucs2_align(req->in.buffer, req->in.data, STR_TERMINATE|STR_UNICODE)) {
2116 req_pull_string(req, &io->ntcreatex.in.fname, req->in.data, fname_len, STR_TERMINATE);
2117 if (!io->ntcreatex.in.fname) {
2118 smbsrv_send_error(req, NT_STATUS_FOOBAR);
2122 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req->ntvfs, io));
2126 /****************************************************************************
2127 Reply to an SMBntcancel request
2128 ****************************************************************************/
2129 void smbsrv_reply_ntcancel(struct smbsrv_request *req)
2131 /* NOTE: this request does not generate a reply */
2132 SMBSRV_SETUP_NTVFS_REQUEST(NULL,0);
2133 ntvfs_cancel(req->ntvfs);
2138 parse the called/calling names from session request
2140 static NTSTATUS parse_session_request(struct smbsrv_request *req)
2145 blob.data = req->in.buffer + 4;
2146 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2147 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2149 req->smb_conn->negotiate.called_name = talloc(req->smb_conn, struct nbt_name);
2150 req->smb_conn->negotiate.calling_name = talloc(req->smb_conn, struct nbt_name);
2151 if (req->smb_conn->negotiate.called_name == NULL ||
2152 req->smb_conn->negotiate.calling_name == NULL) {
2153 return NT_STATUS_NO_MEMORY;
2156 status = nbt_name_from_blob(req->smb_conn, &blob,
2157 req->smb_conn->negotiate.called_name);
2158 NT_STATUS_NOT_OK_RETURN(status);
2160 blob.data += blob.length;
2161 blob.length = ascii_len_n((const char *)blob.data, req->in.size - PTR_DIFF(blob.data, req->in.buffer));
2162 if (blob.length == 0) return NT_STATUS_BAD_NETWORK_NAME;
2164 status = nbt_name_from_blob(req->smb_conn, &blob,
2165 req->smb_conn->negotiate.calling_name);
2166 NT_STATUS_NOT_OK_RETURN(status);
2168 req->smb_conn->negotiate.done_nbt_session = True;
2170 return NT_STATUS_OK;
2175 /****************************************************************************
2176 Reply to a special message - a SMB packet with non zero NBT message type
2177 ****************************************************************************/
2178 void smbsrv_reply_special(struct smbsrv_request *req)
2181 uint8_t *buf = talloc_zero_array(req, uint8_t, 4);
2183 msg_type = CVAL(req->in.buffer,0);
2188 case 0x81: /* session request */
2189 if (req->smb_conn->negotiate.done_nbt_session) {
2190 DEBUG(0,("Warning: ignoring secondary session request\n"));
2197 /* we don't check the status - samba always accepts session
2198 requests for any name */
2199 parse_session_request(req);
2201 req->out.buffer = buf;
2203 smbsrv_send_reply_nosign(req);
2206 case 0x89: /* session keepalive request
2207 (some old clients produce this?) */
2208 SCVAL(buf, 0, SMBkeepalive);
2210 req->out.buffer = buf;
2212 smbsrv_send_reply_nosign(req);
2216 /* session keepalive - swallow it */
2221 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type));