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>
6 Copyright (C) Stefan Metzmacher 2006
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific SMB commands
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 /****************************************************************************
47 Reply to a tcon (async reply)
48 ****************************************************************************/
49 static void reply_tcon_send(struct ntvfs_request
*ntvfs
)
51 struct smbsrv_request
*req
;
54 SMBSRV_CHECK_ASYNC_STATUS(con
, union smb_tcon
);
57 smbsrv_setup_reply(req
, 2, 0);
59 SSVAL(req
->out
.vwv
, VWV(0), con
->tcon
.out
.max_xmit
);
60 SSVAL(req
->out
.vwv
, VWV(1), con
->tcon
.out
.tid
);
61 SSVAL(req
->out
.hdr
, HDR_TID
, req
->tcon
->tid
);
63 smbsrv_send_reply(req
);
66 /****************************************************************************
68 ****************************************************************************/
69 void smbsrv_reply_tcon(struct smbsrv_request
*req
)
76 SMBSRV_CHECK_WCT(req
, 0);
78 SMBSRV_TALLOC_IO_PTR(con
, union smb_tcon
);
80 con
->tcon
.level
= RAW_TCON_TCON
;
83 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &con
->tcon
.in
.service
, p
, STR_TERMINATE
);
84 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &con
->tcon
.in
.password
, p
, STR_TERMINATE
);
85 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &con
->tcon
.in
.dev
, p
, STR_TERMINATE
);
87 if (!con
->tcon
.in
.service
|| !con
->tcon
.in
.password
|| !con
->tcon
.in
.dev
) {
88 smbsrv_send_error(req
, NT_STATUS_INVALID_PARAMETER
);
92 /* Instantiate backend */
93 status
= smbsrv_tcon_backend(req
, con
);
94 if (!NT_STATUS_IS_OK(status
)) {
95 smbsrv_send_error(req
, status
);
99 SMBSRV_SETUP_NTVFS_REQUEST(reply_tcon_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
101 /* Invoke NTVFS connection hook */
102 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_connect(req
->ntvfs
, con
));
106 /****************************************************************************
107 Reply to a tcon and X (async reply)
108 ****************************************************************************/
109 static void reply_tcon_and_X_send(struct ntvfs_request
*ntvfs
)
111 struct smbsrv_request
*req
;
114 SMBSRV_CHECK_ASYNC_STATUS(con
, union smb_tcon
);
116 /* construct reply - two variants */
117 if (req
->smb_conn
->negotiate
.protocol
< PROTOCOL_NT1
) {
118 smbsrv_setup_reply(req
, 2, 0);
120 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
121 SSVAL(req
->out
.vwv
, VWV(1), 0);
123 req_push_str(req
, NULL
, con
->tconx
.out
.dev_type
, -1, STR_TERMINATE
|STR_ASCII
);
125 smbsrv_setup_reply(req
, 3, 0);
127 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
128 SSVAL(req
->out
.vwv
, VWV(1), 0);
129 SSVAL(req
->out
.vwv
, VWV(2), con
->tconx
.out
.options
);
131 req_push_str(req
, NULL
, con
->tconx
.out
.dev_type
, -1, STR_TERMINATE
|STR_ASCII
);
132 req_push_str(req
, NULL
, con
->tconx
.out
.fs_type
, -1, STR_TERMINATE
);
135 /* set the incoming and outgoing tid to the just created one */
136 SSVAL(req
->in
.hdr
, HDR_TID
, con
->tconx
.out
.tid
);
137 SSVAL(req
->out
.hdr
,HDR_TID
, con
->tconx
.out
.tid
);
139 smbsrv_chain_reply(req
);
142 /****************************************************************************
143 Reply to a tcon and X.
144 ****************************************************************************/
145 void smbsrv_reply_tcon_and_X(struct smbsrv_request
*req
)
152 SMBSRV_TALLOC_IO_PTR(con
, union smb_tcon
);
154 con
->tconx
.level
= RAW_TCON_TCONX
;
157 SMBSRV_CHECK_WCT(req
, 4);
159 con
->tconx
.in
.flags
= SVAL(req
->in
.vwv
, VWV(2));
160 passlen
= SVAL(req
->in
.vwv
, VWV(3));
164 if (!req_pull_blob(&req
->in
.bufinfo
, p
, passlen
, &con
->tconx
.in
.password
)) {
165 smbsrv_send_error(req
, NT_STATUS_ILL_FORMED_PASSWORD
);
170 p
+= req_pull_string(&req
->in
.bufinfo
, &con
->tconx
.in
.path
, p
, -1, STR_TERMINATE
);
171 p
+= req_pull_string(&req
->in
.bufinfo
, &con
->tconx
.in
.device
, p
, -1, STR_ASCII
);
173 if (!con
->tconx
.in
.path
|| !con
->tconx
.in
.device
) {
174 smbsrv_send_error(req
, NT_STATUS_BAD_DEVICE_TYPE
);
178 /* Instantiate backend */
179 status
= smbsrv_tcon_backend(req
, con
);
180 if (!NT_STATUS_IS_OK(status
)) {
181 smbsrv_send_error(req
, status
);
185 SMBSRV_SETUP_NTVFS_REQUEST(reply_tcon_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
187 /* Invoke NTVFS connection hook */
188 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_connect(req
->ntvfs
, con
));
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 ntvfs_request
*ntvfs
)
212 struct smbsrv_request
*req
;
215 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_ioctl
);
217 /* the +1 is for nicer alignment */
218 smbsrv_setup_reply(req
, 8, io
->ioctl
.out
.blob
.length
+1);
219 SSVAL(req
->out
.vwv
, VWV(1), io
->ioctl
.out
.blob
.length
);
220 SSVAL(req
->out
.vwv
, VWV(5), io
->ioctl
.out
.blob
.length
);
221 SSVAL(req
->out
.vwv
, VWV(6), PTR_DIFF(req
->out
.data
, req
->out
.hdr
) + 1);
223 memcpy(req
->out
.data
+1, io
->ioctl
.out
.blob
.data
, io
->ioctl
.out
.blob
.length
);
225 smbsrv_send_reply(req
);
228 /****************************************************************************
230 ****************************************************************************/
231 void smbsrv_reply_ioctl(struct smbsrv_request
*req
)
236 SMBSRV_CHECK_WCT(req
, 3);
237 SMBSRV_TALLOC_IO_PTR(io
, union smb_ioctl
);
238 SMBSRV_SETUP_NTVFS_REQUEST(reply_ioctl_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
240 io
->ioctl
.level
= RAW_IOCTL_IOCTL
;
241 io
->ioctl
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
242 io
->ioctl
.in
.request
= IVAL(req
->in
.vwv
, VWV(1));
244 SMBSRV_CHECK_FILE_HANDLE_ERROR(io
->ioctl
.in
.file
.ntvfs
,
245 NT_STATUS_DOS(ERRSRV
, ERRerror
));
246 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_ioctl(req
->ntvfs
, io
));
250 /****************************************************************************
252 ****************************************************************************/
253 void smbsrv_reply_chkpth(struct smbsrv_request
*req
)
255 union smb_chkpath
*io
;
257 SMBSRV_TALLOC_IO_PTR(io
, union smb_chkpath
);
258 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
260 req_pull_ascii4(&req
->in
.bufinfo
, &io
->chkpath
.in
.path
, req
->in
.data
, STR_TERMINATE
);
262 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_chkpath(req
->ntvfs
, io
));
265 /****************************************************************************
266 Reply to a getatr (async reply)
267 ****************************************************************************/
268 static void reply_getatr_send(struct ntvfs_request
*ntvfs
)
270 struct smbsrv_request
*req
;
271 union smb_fileinfo
*st
;
273 SMBSRV_CHECK_ASYNC_STATUS(st
, union smb_fileinfo
);
275 /* construct reply */
276 smbsrv_setup_reply(req
, 10, 0);
278 SSVAL(req
->out
.vwv
, VWV(0), st
->getattr
.out
.attrib
);
279 srv_push_dos_date3(req
->smb_conn
, req
->out
.vwv
, VWV(1), st
->getattr
.out
.write_time
);
280 SIVAL(req
->out
.vwv
, VWV(3), st
->getattr
.out
.size
);
282 SMBSRV_VWV_RESERVED(5, 5);
284 smbsrv_send_reply(req
);
288 /****************************************************************************
290 ****************************************************************************/
291 void smbsrv_reply_getatr(struct smbsrv_request
*req
)
293 union smb_fileinfo
*st
;
295 SMBSRV_TALLOC_IO_PTR(st
, union smb_fileinfo
);
296 SMBSRV_SETUP_NTVFS_REQUEST(reply_getatr_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
298 st
->getattr
.level
= RAW_FILEINFO_GETATTR
;
301 req_pull_ascii4(&req
->in
.bufinfo
, &st
->getattr
.in
.file
.path
, req
->in
.data
, STR_TERMINATE
);
302 if (!st
->getattr
.in
.file
.path
) {
303 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
307 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qpathinfo(req
->ntvfs
, st
));
311 /****************************************************************************
313 ****************************************************************************/
314 void smbsrv_reply_setatr(struct smbsrv_request
*req
)
316 union smb_setfileinfo
*st
;
319 SMBSRV_CHECK_WCT(req
, 8);
320 SMBSRV_TALLOC_IO_PTR(st
, union smb_setfileinfo
);
321 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
323 st
->setattr
.level
= RAW_SFILEINFO_SETATTR
;
324 st
->setattr
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
325 st
->setattr
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
327 req_pull_ascii4(&req
->in
.bufinfo
, &st
->setattr
.in
.file
.path
, req
->in
.data
, STR_TERMINATE
);
329 if (!st
->setattr
.in
.file
.path
) {
330 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
334 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setpathinfo(req
->ntvfs
, st
));
338 /****************************************************************************
339 Reply to a dskattr (async reply)
340 ****************************************************************************/
341 static void reply_dskattr_send(struct ntvfs_request
*ntvfs
)
343 struct smbsrv_request
*req
;
344 union smb_fsinfo
*fs
;
346 SMBSRV_CHECK_ASYNC_STATUS(fs
, union smb_fsinfo
);
348 /* construct reply */
349 smbsrv_setup_reply(req
, 5, 0);
351 SSVAL(req
->out
.vwv
, VWV(0), fs
->dskattr
.out
.units_total
);
352 SSVAL(req
->out
.vwv
, VWV(1), fs
->dskattr
.out
.blocks_per_unit
);
353 SSVAL(req
->out
.vwv
, VWV(2), fs
->dskattr
.out
.block_size
);
354 SSVAL(req
->out
.vwv
, VWV(3), fs
->dskattr
.out
.units_free
);
356 SMBSRV_VWV_RESERVED(4, 1);
358 smbsrv_send_reply(req
);
362 /****************************************************************************
364 ****************************************************************************/
365 void smbsrv_reply_dskattr(struct smbsrv_request
*req
)
367 union smb_fsinfo
*fs
;
369 SMBSRV_TALLOC_IO_PTR(fs
, union smb_fsinfo
);
370 SMBSRV_SETUP_NTVFS_REQUEST(reply_dskattr_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
372 fs
->dskattr
.level
= RAW_QFS_DSKATTR
;
374 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_fsinfo(req
->ntvfs
, fs
));
378 /****************************************************************************
379 Reply to an open (async reply)
380 ****************************************************************************/
381 static void reply_open_send(struct ntvfs_request
*ntvfs
)
383 struct smbsrv_request
*req
;
386 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
388 /* construct reply */
389 smbsrv_setup_reply(req
, 7, 0);
391 smbsrv_push_fnum(req
->out
.vwv
, VWV(0), oi
->openold
.out
.file
.ntvfs
);
392 SSVAL(req
->out
.vwv
, VWV(1), oi
->openold
.out
.attrib
);
393 srv_push_dos_date3(req
->smb_conn
, req
->out
.vwv
, VWV(2), oi
->openold
.out
.write_time
);
394 SIVAL(req
->out
.vwv
, VWV(4), oi
->openold
.out
.size
);
395 SSVAL(req
->out
.vwv
, VWV(6), oi
->openold
.out
.rmode
);
397 smbsrv_send_reply(req
);
400 /****************************************************************************
402 ****************************************************************************/
403 void smbsrv_reply_open(struct smbsrv_request
*req
)
408 SMBSRV_CHECK_WCT(req
, 2);
409 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
410 SMBSRV_SETUP_NTVFS_REQUEST(reply_open_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
412 oi
->openold
.level
= RAW_OPEN_OPEN
;
413 oi
->openold
.in
.open_mode
= SVAL(req
->in
.vwv
, VWV(0));
414 oi
->openold
.in
.search_attrs
= SVAL(req
->in
.vwv
, VWV(1));
416 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->openold
.in
.fname
, req
->in
.data
, STR_TERMINATE
);
418 if (!oi
->openold
.in
.fname
) {
419 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
423 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
427 /****************************************************************************
428 Reply to an open and X (async reply)
429 ****************************************************************************/
430 static void reply_open_and_X_send(struct ntvfs_request
*ntvfs
)
432 struct smbsrv_request
*req
;
435 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
437 /* build the reply */
438 if (oi
->openx
.in
.flags
& OPENX_FLAGS_EXTENDED_RETURN
) {
439 smbsrv_setup_reply(req
, 19, 0);
441 smbsrv_setup_reply(req
, 15, 0);
444 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
445 SSVAL(req
->out
.vwv
, VWV(1), 0);
446 smbsrv_push_fnum(req
->out
.vwv
, VWV(2), oi
->openx
.out
.file
.ntvfs
);
447 SSVAL(req
->out
.vwv
, VWV(3), oi
->openx
.out
.attrib
);
448 srv_push_dos_date3(req
->smb_conn
, req
->out
.vwv
, VWV(4), oi
->openx
.out
.write_time
);
449 SIVAL(req
->out
.vwv
, VWV(6), oi
->openx
.out
.size
);
450 SSVAL(req
->out
.vwv
, VWV(8), oi
->openx
.out
.access
);
451 SSVAL(req
->out
.vwv
, VWV(9), oi
->openx
.out
.ftype
);
452 SSVAL(req
->out
.vwv
, VWV(10),oi
->openx
.out
.devstate
);
453 SSVAL(req
->out
.vwv
, VWV(11),oi
->openx
.out
.action
);
454 SIVAL(req
->out
.vwv
, VWV(12),oi
->openx
.out
.unique_fid
);
455 SSVAL(req
->out
.vwv
, VWV(14),0); /* reserved */
456 if (oi
->openx
.in
.flags
& OPENX_FLAGS_EXTENDED_RETURN
) {
457 SIVAL(req
->out
.vwv
, VWV(15),oi
->openx
.out
.access_mask
);
458 SMBSRV_VWV_RESERVED(17, 2);
461 req
->chained_fnum
= SVAL(req
->out
.vwv
, VWV(2));
463 smbsrv_chain_reply(req
);
467 /****************************************************************************
468 Reply to an open and X.
469 ****************************************************************************/
470 void smbsrv_reply_open_and_X(struct smbsrv_request
*req
)
474 /* parse the request */
475 SMBSRV_CHECK_WCT(req
, 15);
476 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
477 SMBSRV_SETUP_NTVFS_REQUEST(reply_open_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
479 oi
->openx
.level
= RAW_OPEN_OPENX
;
480 oi
->openx
.in
.flags
= SVAL(req
->in
.vwv
, VWV(2));
481 oi
->openx
.in
.open_mode
= SVAL(req
->in
.vwv
, VWV(3));
482 oi
->openx
.in
.search_attrs
= SVAL(req
->in
.vwv
, VWV(4));
483 oi
->openx
.in
.file_attrs
= SVAL(req
->in
.vwv
, VWV(5));
484 oi
->openx
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(6));
485 oi
->openx
.in
.open_func
= SVAL(req
->in
.vwv
, VWV(8));
486 oi
->openx
.in
.size
= IVAL(req
->in
.vwv
, VWV(9));
487 oi
->openx
.in
.timeout
= IVAL(req
->in
.vwv
, VWV(11));
489 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->openx
.in
.fname
, req
->in
.data
, STR_TERMINATE
);
491 if (!oi
->openx
.in
.fname
) {
492 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
496 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
500 /****************************************************************************
501 Reply to a mknew or a create.
502 ****************************************************************************/
503 static void reply_mknew_send(struct ntvfs_request
*ntvfs
)
505 struct smbsrv_request
*req
;
508 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
510 /* build the reply */
511 smbsrv_setup_reply(req
, 1, 0);
513 smbsrv_push_fnum(req
->out
.vwv
, VWV(0), oi
->mknew
.out
.file
.ntvfs
);
515 smbsrv_send_reply(req
);
519 /****************************************************************************
520 Reply to a mknew or a create.
521 ****************************************************************************/
522 void smbsrv_reply_mknew(struct smbsrv_request
*req
)
526 /* parse the request */
527 SMBSRV_CHECK_WCT(req
, 3);
528 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
529 SMBSRV_SETUP_NTVFS_REQUEST(reply_mknew_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
531 if (CVAL(req
->in
.hdr
, HDR_COM
) == SMBmknew
) {
532 oi
->mknew
.level
= RAW_OPEN_MKNEW
;
534 oi
->mknew
.level
= RAW_OPEN_CREATE
;
536 oi
->mknew
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
537 oi
->mknew
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
539 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->mknew
.in
.fname
, req
->in
.data
, STR_TERMINATE
);
541 if (!oi
->mknew
.in
.fname
) {
542 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
546 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
549 /****************************************************************************
550 Reply to a create temporary file (async reply)
551 ****************************************************************************/
552 static void reply_ctemp_send(struct ntvfs_request
*ntvfs
)
554 struct smbsrv_request
*req
;
557 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
559 /* build the reply */
560 smbsrv_setup_reply(req
, 1, 0);
562 smbsrv_push_fnum(req
->out
.vwv
, VWV(0), oi
->ctemp
.out
.file
.ntvfs
);
564 /* the returned filename is relative to the directory */
565 req_push_str(req
, NULL
, oi
->ctemp
.out
.name
, -1, STR_TERMINATE
| STR_ASCII
);
567 smbsrv_send_reply(req
);
570 /****************************************************************************
571 Reply to a create temporary file.
572 ****************************************************************************/
573 void smbsrv_reply_ctemp(struct smbsrv_request
*req
)
577 /* parse the request */
578 SMBSRV_CHECK_WCT(req
, 3);
579 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
580 SMBSRV_SETUP_NTVFS_REQUEST(reply_ctemp_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
582 oi
->ctemp
.level
= RAW_OPEN_CTEMP
;
583 oi
->ctemp
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
584 oi
->ctemp
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
586 /* the filename is actually a directory name, the server provides a filename
588 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->ctemp
.in
.directory
, req
->in
.data
, STR_TERMINATE
);
590 if (!oi
->ctemp
.in
.directory
) {
591 smbsrv_send_error(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
595 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
599 /****************************************************************************
601 ****************************************************************************/
602 void smbsrv_reply_unlink(struct smbsrv_request
*req
)
604 union smb_unlink
*unl
;
606 /* parse the request */
607 SMBSRV_CHECK_WCT(req
, 1);
608 SMBSRV_TALLOC_IO_PTR(unl
, union smb_unlink
);
609 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
611 unl
->unlink
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
613 req_pull_ascii4(&req
->in
.bufinfo
, &unl
->unlink
.in
.pattern
, req
->in
.data
, STR_TERMINATE
);
615 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_unlink(req
->ntvfs
, unl
));
619 /****************************************************************************
620 Reply to a readbraw (core+ protocol).
621 this is a strange packet because it doesn't use a standard SMB header in the reply,
622 only the 4 byte NBT header
623 This command must be replied to synchronously
624 ****************************************************************************/
625 void smbsrv_reply_readbraw(struct smbsrv_request
*req
)
630 io
.readbraw
.level
= RAW_READ_READBRAW
;
632 /* there are two variants, one with 10 and one with 8 command words */
633 if (req
->in
.wct
< 8) {
637 io
.readbraw
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
638 io
.readbraw
.in
.offset
= IVAL(req
->in
.vwv
, VWV(1));
639 io
.readbraw
.in
.maxcnt
= SVAL(req
->in
.vwv
, VWV(3));
640 io
.readbraw
.in
.mincnt
= SVAL(req
->in
.vwv
, VWV(4));
641 io
.readbraw
.in
.timeout
= IVAL(req
->in
.vwv
, VWV(5));
643 if (!io
.readbraw
.in
.file
.ntvfs
) {
647 /* the 64 bit variant */
648 if (req
->in
.wct
== 10) {
649 uint32_t offset_high
= IVAL(req
->in
.vwv
, VWV(8));
650 io
.readbraw
.in
.offset
|= (((off_t
)offset_high
) << 32);
653 /* before calling the backend we setup the raw buffer. This
654 * saves a copy later */
655 req
->out
.size
= io
.readbraw
.in
.maxcnt
+ NBT_HDR_SIZE
;
656 req
->out
.buffer
= talloc_size(req
, req
->out
.size
);
657 if (req
->out
.buffer
== NULL
) {
660 SIVAL(req
->out
.buffer
, 0, 0); /* init NBT header */
662 /* tell the backend where to put the data */
663 io
.readbraw
.out
.data
= req
->out
.buffer
+ NBT_HDR_SIZE
;
665 /* prepare the ntvfs request */
666 req
->ntvfs
= ntvfs_request_create(req
->tcon
->ntvfs
, req
,
667 req
->session
->session_info
,
668 SVAL(req
->in
.hdr
,HDR_PID
),
675 /* call the backend */
676 status
= ntvfs_read(req
->ntvfs
, &io
);
677 if (!NT_STATUS_IS_OK(status
)) {
681 req
->out
.size
= io
.readbraw
.out
.nread
+ NBT_HDR_SIZE
;
683 smbsrv_send_reply_nosign(req
);
687 /* any failure in readbraw is equivalent to reading zero bytes */
689 req
->out
.buffer
= talloc_size(req
, req
->out
.size
);
690 SIVAL(req
->out
.buffer
, 0, 0); /* init NBT header */
692 smbsrv_send_reply_nosign(req
);
696 /****************************************************************************
697 Reply to a lockread (async reply)
698 ****************************************************************************/
699 static void reply_lockread_send(struct ntvfs_request
*ntvfs
)
701 struct smbsrv_request
*req
;
704 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_read
);
707 io
->lockread
.out
.nread
= MIN(io
->lockread
.out
.nread
,
708 req_max_data(req
) - 3);
709 req_grow_data(req
, 3 + io
->lockread
.out
.nread
);
711 /* construct reply */
712 SSVAL(req
->out
.vwv
, VWV(0), io
->lockread
.out
.nread
);
713 SMBSRV_VWV_RESERVED(1, 4);
715 SCVAL(req
->out
.data
, 0, SMB_DATA_BLOCK
);
716 SSVAL(req
->out
.data
, 1, io
->lockread
.out
.nread
);
718 smbsrv_send_reply(req
);
722 /****************************************************************************
723 Reply to a lockread (core+ protocol).
724 note that the lock is a write lock, not a read lock!
725 ****************************************************************************/
726 void smbsrv_reply_lockread(struct smbsrv_request
*req
)
731 SMBSRV_CHECK_WCT(req
, 5);
732 SMBSRV_TALLOC_IO_PTR(io
, union smb_read
);
733 SMBSRV_SETUP_NTVFS_REQUEST(reply_lockread_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
735 io
->lockread
.level
= RAW_READ_LOCKREAD
;
736 io
->lockread
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
737 io
->lockread
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
738 io
->lockread
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
739 io
->lockread
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(4));
741 /* setup the reply packet assuming the maximum possible read */
742 smbsrv_setup_reply(req
, 5, 3 + io
->lockread
.in
.count
);
744 /* tell the backend where to put the data */
745 io
->lockread
.out
.data
= req
->out
.data
+ 3;
747 SMBSRV_CHECK_FILE_HANDLE(io
->lockread
.in
.file
.ntvfs
);
748 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req
->ntvfs
, io
));
753 /****************************************************************************
754 Reply to a read (async reply)
755 ****************************************************************************/
756 static void reply_read_send(struct ntvfs_request
*ntvfs
)
758 struct smbsrv_request
*req
;
761 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_read
);
764 io
->read
.out
.nread
= MIN(io
->read
.out
.nread
,
765 req_max_data(req
) - 3);
766 req_grow_data(req
, 3 + io
->read
.out
.nread
);
768 /* construct reply */
769 SSVAL(req
->out
.vwv
, VWV(0), io
->read
.out
.nread
);
770 SMBSRV_VWV_RESERVED(1, 4);
772 SCVAL(req
->out
.data
, 0, SMB_DATA_BLOCK
);
773 SSVAL(req
->out
.data
, 1, io
->read
.out
.nread
);
775 smbsrv_send_reply(req
);
778 /****************************************************************************
780 ****************************************************************************/
781 void smbsrv_reply_read(struct smbsrv_request
*req
)
786 SMBSRV_CHECK_WCT(req
, 5);
787 SMBSRV_TALLOC_IO_PTR(io
, union smb_read
);
788 SMBSRV_SETUP_NTVFS_REQUEST(reply_read_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
790 io
->read
.level
= RAW_READ_READ
;
791 io
->read
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
792 io
->read
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
793 io
->read
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
794 io
->read
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(4));
796 /* setup the reply packet assuming the maximum possible read */
797 smbsrv_setup_reply(req
, 5, 3 + io
->read
.in
.count
);
799 /* tell the backend where to put the data */
800 io
->read
.out
.data
= req
->out
.data
+ 3;
802 SMBSRV_CHECK_FILE_HANDLE(io
->read
.in
.file
.ntvfs
);
803 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req
->ntvfs
, io
));
806 /****************************************************************************
807 Reply to a read and X (async reply)
808 ****************************************************************************/
809 static void reply_read_and_X_send(struct ntvfs_request
*ntvfs
)
811 struct smbsrv_request
*req
;
814 SMBSRV_CHECK_ASYNC_STATUS_ERR(io
, union smb_read
);
816 /* readx reply packets can be over-sized */
817 req
->control_flags
|= SMBSRV_REQ_CONTROL_LARGE
;
818 if (io
->readx
.in
.maxcnt
!= 0xFFFF &&
819 io
->readx
.in
.mincnt
!= 0xFFFF) {
820 req_grow_data(req
, 1 + io
->readx
.out
.nread
);
821 SCVAL(req
->out
.data
, 0, 0); /* padding */
823 req_grow_data(req
, io
->readx
.out
.nread
);
826 /* construct reply */
827 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
828 SSVAL(req
->out
.vwv
, VWV(1), 0);
829 SSVAL(req
->out
.vwv
, VWV(2), io
->readx
.out
.remaining
);
830 SSVAL(req
->out
.vwv
, VWV(3), io
->readx
.out
.compaction_mode
);
831 SMBSRV_VWV_RESERVED(4, 1);
832 SSVAL(req
->out
.vwv
, VWV(5), io
->readx
.out
.nread
);
833 SSVAL(req
->out
.vwv
, VWV(6), PTR_DIFF(io
->readx
.out
.data
, req
->out
.hdr
));
834 SSVAL(req
->out
.vwv
, VWV(7), (io
->readx
.out
.nread
>>16));
835 SMBSRV_VWV_RESERVED(8, 4);
837 if (!NT_STATUS_IS_OK(req
->ntvfs
->async_states
->status
)) {
838 smbsrv_setup_error(req
, req
->ntvfs
->async_states
->status
);
841 smbsrv_chain_reply(req
);
844 /****************************************************************************
845 Reply to a read and X.
846 ****************************************************************************/
847 void smbsrv_reply_read_and_X(struct smbsrv_request
*req
)
852 if (req
->in
.wct
!= 12) {
853 SMBSRV_CHECK_WCT(req
, 10);
856 SMBSRV_TALLOC_IO_PTR(io
, union smb_read
);
857 SMBSRV_SETUP_NTVFS_REQUEST(reply_read_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
859 io
->readx
.level
= RAW_READ_READX
;
860 io
->readx
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(2));
861 io
->readx
.in
.offset
= IVAL(req
->in
.vwv
, VWV(3));
862 io
->readx
.in
.maxcnt
= SVAL(req
->in
.vwv
, VWV(5));
863 io
->readx
.in
.mincnt
= SVAL(req
->in
.vwv
, VWV(6));
864 io
->readx
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(9));
865 if (req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) {
866 io
->readx
.in
.read_for_execute
= true;
868 io
->readx
.in
.read_for_execute
= false;
871 if (req
->smb_conn
->negotiate
.client_caps
& CAP_LARGE_READX
) {
872 uint32_t high_part
= IVAL(req
->in
.vwv
, VWV(7));
873 if (high_part
== 1) {
874 io
->readx
.in
.maxcnt
|= high_part
<< 16;
878 /* the 64 bit variant */
879 if (req
->in
.wct
== 12) {
880 uint32_t offset_high
= IVAL(req
->in
.vwv
, VWV(10));
881 io
->readx
.in
.offset
|= (((uint64_t)offset_high
) << 32);
884 /* setup the reply packet assuming the maximum possible read */
885 smbsrv_setup_reply(req
, 12, 1 + io
->readx
.in
.maxcnt
);
887 /* tell the backend where to put the data. Notice the pad byte. */
888 if (io
->readx
.in
.maxcnt
!= 0xFFFF &&
889 io
->readx
.in
.mincnt
!= 0xFFFF) {
890 io
->readx
.out
.data
= req
->out
.data
+ 1;
892 io
->readx
.out
.data
= req
->out
.data
;
895 SMBSRV_CHECK_FILE_HANDLE(io
->readx
.in
.file
.ntvfs
);
896 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_read(req
->ntvfs
, io
));
900 /****************************************************************************
901 Reply to a writebraw (core+ or LANMAN1.0 protocol).
902 ****************************************************************************/
903 void smbsrv_reply_writebraw(struct smbsrv_request
*req
)
905 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRuseSTD
));
909 /****************************************************************************
910 Reply to a writeunlock (async reply)
911 ****************************************************************************/
912 static void reply_writeunlock_send(struct ntvfs_request
*ntvfs
)
914 struct smbsrv_request
*req
;
917 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_write
);
919 /* construct reply */
920 smbsrv_setup_reply(req
, 1, 0);
922 SSVAL(req
->out
.vwv
, VWV(0), io
->writeunlock
.out
.nwritten
);
924 smbsrv_send_reply(req
);
927 /****************************************************************************
928 Reply to a writeunlock (core+).
929 ****************************************************************************/
930 void smbsrv_reply_writeunlock(struct smbsrv_request
*req
)
934 SMBSRV_CHECK_WCT(req
, 5);
935 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
936 SMBSRV_SETUP_NTVFS_REQUEST(reply_writeunlock_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
938 io
->writeunlock
.level
= RAW_WRITE_WRITEUNLOCK
;
939 io
->writeunlock
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
940 io
->writeunlock
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
941 io
->writeunlock
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
942 io
->writeunlock
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(4));
943 io
->writeunlock
.in
.data
= req
->in
.data
+ 3;
945 /* make sure they gave us the data they promised */
946 if (io
->writeunlock
.in
.count
+3 > req
->in
.data_size
) {
947 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
951 /* make sure the data block is big enough */
952 if (SVAL(req
->in
.data
, 1) < io
->writeunlock
.in
.count
) {
953 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
957 SMBSRV_CHECK_FILE_HANDLE(io
->writeunlock
.in
.file
.ntvfs
);
958 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
963 /****************************************************************************
964 Reply to a write (async reply)
965 ****************************************************************************/
966 static void reply_write_send(struct ntvfs_request
*ntvfs
)
968 struct smbsrv_request
*req
;
971 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_write
);
973 /* construct reply */
974 smbsrv_setup_reply(req
, 1, 0);
976 SSVAL(req
->out
.vwv
, VWV(0), io
->write
.out
.nwritten
);
978 smbsrv_send_reply(req
);
981 /****************************************************************************
983 ****************************************************************************/
984 void smbsrv_reply_write(struct smbsrv_request
*req
)
988 SMBSRV_CHECK_WCT(req
, 5);
989 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
990 SMBSRV_SETUP_NTVFS_REQUEST(reply_write_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
992 io
->write
.level
= RAW_WRITE_WRITE
;
993 io
->write
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
994 io
->write
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
995 io
->write
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
996 io
->write
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(4));
997 io
->write
.in
.data
= req
->in
.data
+ 3;
999 /* make sure they gave us the data they promised */
1000 if (req_data_oob(&req
->in
.bufinfo
, io
->write
.in
.data
, io
->write
.in
.count
)) {
1001 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1005 /* make sure the data block is big enough */
1006 if (SVAL(req
->in
.data
, 1) < io
->write
.in
.count
) {
1007 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1011 SMBSRV_CHECK_FILE_HANDLE(io
->write
.in
.file
.ntvfs
);
1012 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
1016 /****************************************************************************
1017 Reply to a write and X (async reply)
1018 ****************************************************************************/
1019 static void reply_write_and_X_send(struct ntvfs_request
*ntvfs
)
1021 struct smbsrv_request
*req
;
1022 union smb_write
*io
;
1024 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_write
);
1026 /* construct reply */
1027 smbsrv_setup_reply(req
, 6, 0);
1029 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1030 SSVAL(req
->out
.vwv
, VWV(1), 0);
1031 SSVAL(req
->out
.vwv
, VWV(2), io
->writex
.out
.nwritten
& 0xFFFF);
1032 SSVAL(req
->out
.vwv
, VWV(3), io
->writex
.out
.remaining
);
1033 SSVAL(req
->out
.vwv
, VWV(4), io
->writex
.out
.nwritten
>> 16);
1034 SMBSRV_VWV_RESERVED(5, 1);
1036 smbsrv_chain_reply(req
);
1039 /****************************************************************************
1040 Reply to a write and X.
1041 ****************************************************************************/
1042 void smbsrv_reply_write_and_X(struct smbsrv_request
*req
)
1044 union smb_write
*io
;
1046 if (req
->in
.wct
!= 14) {
1047 SMBSRV_CHECK_WCT(req
, 12);
1050 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
1051 SMBSRV_SETUP_NTVFS_REQUEST(reply_write_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1053 io
->writex
.level
= RAW_WRITE_WRITEX
;
1054 io
->writex
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(2));
1055 io
->writex
.in
.offset
= IVAL(req
->in
.vwv
, VWV(3));
1056 io
->writex
.in
.wmode
= SVAL(req
->in
.vwv
, VWV(7));
1057 io
->writex
.in
.remaining
= SVAL(req
->in
.vwv
, VWV(8));
1058 io
->writex
.in
.count
= SVAL(req
->in
.vwv
, VWV(10));
1059 io
->writex
.in
.data
= req
->in
.hdr
+ SVAL(req
->in
.vwv
, VWV(11));
1061 if (req
->in
.wct
== 14) {
1062 uint32_t offset_high
= IVAL(req
->in
.vwv
, VWV(12));
1063 uint16_t count_high
= SVAL(req
->in
.vwv
, VWV(9));
1064 io
->writex
.in
.offset
|= (((uint64_t)offset_high
) << 32);
1065 io
->writex
.in
.count
|= ((uint32_t)count_high
) << 16;
1068 /* make sure the data is in bounds */
1069 if (req_data_oob(&req
->in
.bufinfo
, io
->writex
.in
.data
, io
->writex
.in
.count
)) {
1070 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
1074 SMBSRV_CHECK_FILE_HANDLE(io
->writex
.in
.file
.ntvfs
);
1075 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
1079 /****************************************************************************
1080 Reply to a lseek (async reply)
1081 ****************************************************************************/
1082 static void reply_lseek_send(struct ntvfs_request
*ntvfs
)
1084 struct smbsrv_request
*req
;
1087 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_seek
);
1089 /* construct reply */
1090 smbsrv_setup_reply(req
, 2, 0);
1092 SIVALS(req
->out
.vwv
, VWV(0), io
->lseek
.out
.offset
);
1094 smbsrv_send_reply(req
);
1097 /****************************************************************************
1099 ****************************************************************************/
1100 void smbsrv_reply_lseek(struct smbsrv_request
*req
)
1104 SMBSRV_CHECK_WCT(req
, 4);
1105 SMBSRV_TALLOC_IO_PTR(io
, union smb_seek
);
1106 SMBSRV_SETUP_NTVFS_REQUEST(reply_lseek_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1108 io
->lseek
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1109 io
->lseek
.in
.mode
= SVAL(req
->in
.vwv
, VWV(1));
1110 io
->lseek
.in
.offset
= IVALS(req
->in
.vwv
, VWV(2));
1112 SMBSRV_CHECK_FILE_HANDLE(io
->lseek
.in
.file
.ntvfs
);
1113 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_seek(req
->ntvfs
, io
));
1116 /****************************************************************************
1118 ****************************************************************************/
1119 void smbsrv_reply_flush(struct smbsrv_request
*req
)
1121 union smb_flush
*io
;
1125 SMBSRV_CHECK_WCT(req
, 1);
1126 SMBSRV_TALLOC_IO_PTR(io
, union smb_flush
);
1127 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1129 fnum
= SVAL(req
->in
.vwv
, VWV(0));
1130 if (fnum
== 0xFFFF) {
1131 io
->flush_all
.level
= RAW_FLUSH_ALL
;
1133 io
->flush
.level
= RAW_FLUSH_FLUSH
;
1134 io
->flush
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1135 SMBSRV_CHECK_FILE_HANDLE(io
->flush
.in
.file
.ntvfs
);
1138 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_flush(req
->ntvfs
, io
));
1141 /****************************************************************************
1144 Note that this has to deal with closing a directory opened by NT SMB's.
1145 ****************************************************************************/
1146 void smbsrv_reply_close(struct smbsrv_request
*req
)
1148 union smb_close
*io
;
1151 SMBSRV_CHECK_WCT(req
, 3);
1152 SMBSRV_TALLOC_IO_PTR(io
, union smb_close
);
1153 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1155 io
->close
.level
= RAW_CLOSE_CLOSE
;
1156 io
->close
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1157 io
->close
.in
.write_time
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
1159 SMBSRV_CHECK_FILE_HANDLE(io
->close
.in
.file
.ntvfs
);
1160 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req
->ntvfs
, io
));
1164 /****************************************************************************
1165 Reply to a writeclose (async reply)
1166 ****************************************************************************/
1167 static void reply_writeclose_send(struct ntvfs_request
*ntvfs
)
1169 struct smbsrv_request
*req
;
1170 union smb_write
*io
;
1172 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_write
);
1174 /* construct reply */
1175 smbsrv_setup_reply(req
, 1, 0);
1177 SSVAL(req
->out
.vwv
, VWV(0), io
->write
.out
.nwritten
);
1179 smbsrv_send_reply(req
);
1182 /****************************************************************************
1183 Reply to a writeclose (Core+ protocol).
1184 ****************************************************************************/
1185 void smbsrv_reply_writeclose(struct smbsrv_request
*req
)
1187 union smb_write
*io
;
1189 /* this one is pretty weird - the wct can be 6 or 12 */
1190 if (req
->in
.wct
!= 12) {
1191 SMBSRV_CHECK_WCT(req
, 6);
1194 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
1195 SMBSRV_SETUP_NTVFS_REQUEST(reply_writeclose_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1197 io
->writeclose
.level
= RAW_WRITE_WRITECLOSE
;
1198 io
->writeclose
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1199 io
->writeclose
.in
.count
= SVAL(req
->in
.vwv
, VWV(1));
1200 io
->writeclose
.in
.offset
= IVAL(req
->in
.vwv
, VWV(2));
1201 io
->writeclose
.in
.mtime
= srv_pull_dos_date3(req
->smb_conn
, req
->in
.vwv
+ VWV(4));
1202 io
->writeclose
.in
.data
= req
->in
.data
+ 1;
1204 /* make sure they gave us the data they promised */
1205 if (req_data_oob(&req
->in
.bufinfo
, io
->writeclose
.in
.data
, io
->writeclose
.in
.count
)) {
1206 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1210 SMBSRV_CHECK_FILE_HANDLE(io
->writeclose
.in
.file
.ntvfs
);
1211 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
1214 /****************************************************************************
1216 ****************************************************************************/
1217 void smbsrv_reply_lock(struct smbsrv_request
*req
)
1219 union smb_lock
*lck
;
1222 SMBSRV_CHECK_WCT(req
, 5);
1223 SMBSRV_TALLOC_IO_PTR(lck
, union smb_lock
);
1224 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1226 lck
->lock
.level
= RAW_LOCK_LOCK
;
1227 lck
->lock
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1228 lck
->lock
.in
.count
= IVAL(req
->in
.vwv
, VWV(1));
1229 lck
->lock
.in
.offset
= IVAL(req
->in
.vwv
, VWV(3));
1231 SMBSRV_CHECK_FILE_HANDLE(lck
->lock
.in
.file
.ntvfs
);
1232 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req
->ntvfs
, lck
));
1236 /****************************************************************************
1238 ****************************************************************************/
1239 void smbsrv_reply_unlock(struct smbsrv_request
*req
)
1241 union smb_lock
*lck
;
1244 SMBSRV_CHECK_WCT(req
, 5);
1245 SMBSRV_TALLOC_IO_PTR(lck
, union smb_lock
);
1246 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1248 lck
->unlock
.level
= RAW_LOCK_UNLOCK
;
1249 lck
->unlock
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1250 lck
->unlock
.in
.count
= IVAL(req
->in
.vwv
, VWV(1));
1251 lck
->unlock
.in
.offset
= IVAL(req
->in
.vwv
, VWV(3));
1253 SMBSRV_CHECK_FILE_HANDLE(lck
->unlock
.in
.file
.ntvfs
);
1254 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req
->ntvfs
, lck
));
1258 /****************************************************************************
1260 ****************************************************************************/
1261 void smbsrv_reply_tdis(struct smbsrv_request
*req
)
1263 struct smbsrv_handle
*h
, *nh
;
1265 SMBSRV_CHECK_WCT(req
, 0);
1268 * TODO: cancel all pending requests on this tcon
1272 * close all handles on this tcon
1274 for (h
=req
->tcon
->handles
.list
; h
; h
=nh
) {
1279 /* finally destroy the tcon */
1280 talloc_free(req
->tcon
);
1283 smbsrv_setup_reply(req
, 0, 0);
1284 smbsrv_send_reply(req
);
1288 /****************************************************************************
1289 Reply to a echo. This is one of the few calls that is handled directly (the
1290 backends don't see it at all)
1291 ****************************************************************************/
1292 void smbsrv_reply_echo(struct smbsrv_request
*req
)
1297 SMBSRV_CHECK_WCT(req
, 1);
1299 count
= SVAL(req
->in
.vwv
, VWV(0));
1301 smbsrv_setup_reply(req
, 1, req
->in
.data_size
);
1303 memcpy(req
->out
.data
, req
->in
.data
, req
->in
.data_size
);
1305 for (i
=1; i
<= count
;i
++) {
1306 struct smbsrv_request
*this_req
;
1309 this_req
= smbsrv_setup_secondary_request(req
);
1314 SSVAL(this_req
->out
.vwv
, VWV(0), i
);
1315 smbsrv_send_reply(this_req
);
1321 /****************************************************************************
1322 Reply to a printopen (async reply)
1323 ****************************************************************************/
1324 static void reply_printopen_send(struct ntvfs_request
*ntvfs
)
1326 struct smbsrv_request
*req
;
1329 SMBSRV_CHECK_ASYNC_STATUS(oi
, union smb_open
);
1331 /* construct reply */
1332 smbsrv_setup_reply(req
, 1, 0);
1334 smbsrv_push_fnum(req
->out
.vwv
, VWV(0), oi
->openold
.out
.file
.ntvfs
);
1336 smbsrv_send_reply(req
);
1339 /****************************************************************************
1340 Reply to a printopen.
1341 ****************************************************************************/
1342 void smbsrv_reply_printopen(struct smbsrv_request
*req
)
1347 SMBSRV_CHECK_WCT(req
, 2);
1348 SMBSRV_TALLOC_IO_PTR(oi
, union smb_open
);
1349 SMBSRV_SETUP_NTVFS_REQUEST(reply_printopen_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1351 oi
->splopen
.level
= RAW_OPEN_SPLOPEN
;
1352 oi
->splopen
.in
.setup_length
= SVAL(req
->in
.vwv
, VWV(0));
1353 oi
->splopen
.in
.mode
= SVAL(req
->in
.vwv
, VWV(1));
1355 req_pull_ascii4(&req
->in
.bufinfo
, &oi
->splopen
.in
.ident
, req
->in
.data
, STR_TERMINATE
);
1357 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, oi
));
1360 /****************************************************************************
1361 Reply to a printclose.
1362 ****************************************************************************/
1363 void smbsrv_reply_printclose(struct smbsrv_request
*req
)
1365 union smb_close
*io
;
1368 SMBSRV_CHECK_WCT(req
, 3);
1369 SMBSRV_TALLOC_IO_PTR(io
, union smb_close
);
1370 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1372 io
->splclose
.level
= RAW_CLOSE_SPLCLOSE
;
1373 io
->splclose
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1375 SMBSRV_CHECK_FILE_HANDLE(io
->splclose
.in
.file
.ntvfs
);
1376 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_close(req
->ntvfs
, io
));
1379 /****************************************************************************
1380 Reply to a printqueue.
1381 ****************************************************************************/
1382 static void reply_printqueue_send(struct ntvfs_request
*ntvfs
)
1384 struct smbsrv_request
*req
;
1387 const unsigned int el_size
= 28;
1389 SMBSRV_CHECK_ASYNC_STATUS(lpq
,union smb_lpq
);
1391 /* construct reply */
1392 smbsrv_setup_reply(req
, 2, 0);
1394 /* truncate the returned list to fit in the negotiated buffer size */
1395 maxcount
= (req_max_data(req
) - 3) / el_size
;
1396 if (maxcount
< lpq
->retq
.out
.count
) {
1397 lpq
->retq
.out
.count
= maxcount
;
1400 /* setup enough space in the reply */
1401 req_grow_data(req
, 3 + el_size
*lpq
->retq
.out
.count
);
1403 /* and fill it in */
1404 SSVAL(req
->out
.vwv
, VWV(0), lpq
->retq
.out
.count
);
1405 SSVAL(req
->out
.vwv
, VWV(1), lpq
->retq
.out
.restart_idx
);
1407 SCVAL(req
->out
.data
, 0, SMB_DATA_BLOCK
);
1408 SSVAL(req
->out
.data
, 1, el_size
*lpq
->retq
.out
.count
);
1410 req
->out
.ptr
= req
->out
.data
+ 3;
1412 for (i
=0;i
<lpq
->retq
.out
.count
;i
++) {
1413 srv_push_dos_date2(req
->smb_conn
, req
->out
.ptr
, 0 , lpq
->retq
.out
.queue
[i
].time
);
1414 SCVAL(req
->out
.ptr
, 4, lpq
->retq
.out
.queue
[i
].status
);
1415 SSVAL(req
->out
.ptr
, 5, lpq
->retq
.out
.queue
[i
].job
);
1416 SIVAL(req
->out
.ptr
, 7, lpq
->retq
.out
.queue
[i
].size
);
1417 SCVAL(req
->out
.ptr
, 11, 0); /* reserved */
1418 req_push_str(req
, req
->out
.ptr
+12, lpq
->retq
.out
.queue
[i
].user
, 16, STR_ASCII
);
1419 req
->out
.ptr
+= el_size
;
1422 smbsrv_send_reply(req
);
1425 /****************************************************************************
1426 Reply to a printqueue.
1427 ****************************************************************************/
1428 void smbsrv_reply_printqueue(struct smbsrv_request
*req
)
1433 SMBSRV_CHECK_WCT(req
, 2);
1434 SMBSRV_TALLOC_IO_PTR(lpq
, union smb_lpq
);
1435 SMBSRV_SETUP_NTVFS_REQUEST(reply_printqueue_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1437 lpq
->retq
.level
= RAW_LPQ_RETQ
;
1438 lpq
->retq
.in
.maxcount
= SVAL(req
->in
.vwv
, VWV(0));
1439 lpq
->retq
.in
.startidx
= SVAL(req
->in
.vwv
, VWV(1));
1441 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lpq(req
->ntvfs
, lpq
));
1445 /****************************************************************************
1446 Reply to a printwrite.
1447 ****************************************************************************/
1448 void smbsrv_reply_printwrite(struct smbsrv_request
*req
)
1450 union smb_write
*io
;
1453 SMBSRV_CHECK_WCT(req
, 1);
1454 SMBSRV_TALLOC_IO_PTR(io
, union smb_write
);
1455 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1457 if (req
->in
.data_size
< 3) {
1458 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1462 io
->splwrite
.level
= RAW_WRITE_SPLWRITE
;
1463 io
->splwrite
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1464 io
->splwrite
.in
.count
= SVAL(req
->in
.data
, 1);
1465 io
->splwrite
.in
.data
= req
->in
.data
+ 3;
1467 /* make sure they gave us the data they promised */
1468 if (req_data_oob(&req
->in
.bufinfo
, io
->splwrite
.in
.data
, io
->splwrite
.in
.count
)) {
1469 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1473 SMBSRV_CHECK_FILE_HANDLE(io
->splwrite
.in
.file
.ntvfs
);
1474 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_write(req
->ntvfs
, io
));
1478 /****************************************************************************
1480 ****************************************************************************/
1481 void smbsrv_reply_mkdir(struct smbsrv_request
*req
)
1483 union smb_mkdir
*io
;
1485 /* parse the request */
1486 SMBSRV_CHECK_WCT(req
, 0);
1487 SMBSRV_TALLOC_IO_PTR(io
, union smb_mkdir
);
1488 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1490 io
->generic
.level
= RAW_MKDIR_MKDIR
;
1491 req_pull_ascii4(&req
->in
.bufinfo
, &io
->mkdir
.in
.path
, req
->in
.data
, STR_TERMINATE
);
1493 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_mkdir(req
->ntvfs
, io
));
1497 /****************************************************************************
1499 ****************************************************************************/
1500 void smbsrv_reply_rmdir(struct smbsrv_request
*req
)
1502 struct smb_rmdir
*io
;
1504 /* parse the request */
1505 SMBSRV_CHECK_WCT(req
, 0);
1506 SMBSRV_TALLOC_IO_PTR(io
, struct smb_rmdir
);
1507 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1509 req_pull_ascii4(&req
->in
.bufinfo
, &io
->in
.path
, req
->in
.data
, STR_TERMINATE
);
1511 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rmdir(req
->ntvfs
, io
));
1515 /****************************************************************************
1517 ****************************************************************************/
1518 void smbsrv_reply_mv(struct smbsrv_request
*req
)
1520 union smb_rename
*io
;
1523 /* parse the request */
1524 SMBSRV_CHECK_WCT(req
, 1);
1525 SMBSRV_TALLOC_IO_PTR(io
, union smb_rename
);
1526 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1528 io
->generic
.level
= RAW_RENAME_RENAME
;
1529 io
->rename
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
1532 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &io
->rename
.in
.pattern1
, p
, STR_TERMINATE
);
1533 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &io
->rename
.in
.pattern2
, p
, STR_TERMINATE
);
1535 if (!io
->rename
.in
.pattern1
|| !io
->rename
.in
.pattern2
) {
1536 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1540 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req
->ntvfs
, io
));
1544 /****************************************************************************
1545 Reply to an NT rename.
1546 ****************************************************************************/
1547 void smbsrv_reply_ntrename(struct smbsrv_request
*req
)
1549 union smb_rename
*io
;
1552 /* parse the request */
1553 SMBSRV_CHECK_WCT(req
, 4);
1554 SMBSRV_TALLOC_IO_PTR(io
, union smb_rename
);
1555 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1557 io
->generic
.level
= RAW_RENAME_NTRENAME
;
1558 io
->ntrename
.in
.attrib
= SVAL(req
->in
.vwv
, VWV(0));
1559 io
->ntrename
.in
.flags
= SVAL(req
->in
.vwv
, VWV(1));
1560 io
->ntrename
.in
.cluster_size
= IVAL(req
->in
.vwv
, VWV(2));
1563 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &io
->ntrename
.in
.old_name
, p
, STR_TERMINATE
);
1564 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &io
->ntrename
.in
.new_name
, p
, STR_TERMINATE
);
1566 if (!io
->ntrename
.in
.old_name
|| !io
->ntrename
.in
.new_name
) {
1567 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1571 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_rename(req
->ntvfs
, io
));
1574 /****************************************************************************
1575 Reply to a file copy (async reply)
1576 ****************************************************************************/
1577 static void reply_copy_send(struct ntvfs_request
*ntvfs
)
1579 struct smbsrv_request
*req
;
1580 struct smb_copy
*cp
;
1582 SMBSRV_CHECK_ASYNC_STATUS(cp
, struct smb_copy
);
1584 /* build the reply */
1585 smbsrv_setup_reply(req
, 1, 0);
1587 SSVAL(req
->out
.vwv
, VWV(0), cp
->out
.count
);
1589 smbsrv_send_reply(req
);
1592 /****************************************************************************
1593 Reply to a file copy.
1594 ****************************************************************************/
1595 void smbsrv_reply_copy(struct smbsrv_request
*req
)
1597 struct smb_copy
*cp
;
1601 SMBSRV_CHECK_WCT(req
, 3);
1602 SMBSRV_TALLOC_IO_PTR(cp
, struct smb_copy
);
1603 SMBSRV_SETUP_NTVFS_REQUEST(reply_copy_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1605 cp
->in
.tid2
= SVAL(req
->in
.vwv
, VWV(0));
1606 cp
->in
.ofun
= SVAL(req
->in
.vwv
, VWV(1));
1607 cp
->in
.flags
= SVAL(req
->in
.vwv
, VWV(2));
1610 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &cp
->in
.path1
, p
, STR_TERMINATE
);
1611 p
+= req_pull_ascii4(&req
->in
.bufinfo
, &cp
->in
.path2
, p
, STR_TERMINATE
);
1613 if (!cp
->in
.path1
|| !cp
->in
.path2
) {
1614 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1618 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_copy(req
->ntvfs
, cp
));
1621 /****************************************************************************
1622 Reply to a lockingX request (async send)
1623 ****************************************************************************/
1624 static void reply_lockingX_send(struct ntvfs_request
*ntvfs
)
1626 struct smbsrv_request
*req
;
1627 union smb_lock
*lck
;
1629 SMBSRV_CHECK_ASYNC_STATUS(lck
, union smb_lock
);
1631 /* if it was an oplock break ack then we only send a reply if
1632 there was an error */
1633 if (lck
->lockx
.in
.ulock_cnt
+ lck
->lockx
.in
.lock_cnt
== 0) {
1638 /* construct reply */
1639 smbsrv_setup_reply(req
, 2, 0);
1641 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1642 SSVAL(req
->out
.vwv
, VWV(1), 0);
1644 smbsrv_chain_reply(req
);
1648 /****************************************************************************
1649 Reply to a lockingX request.
1650 ****************************************************************************/
1651 void smbsrv_reply_lockingX(struct smbsrv_request
*req
)
1653 union smb_lock
*lck
;
1654 unsigned int total_locks
, i
;
1655 unsigned int lck_size
;
1659 SMBSRV_CHECK_WCT(req
, 8);
1660 SMBSRV_TALLOC_IO_PTR(lck
, union smb_lock
);
1661 SMBSRV_SETUP_NTVFS_REQUEST(reply_lockingX_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1663 lck
->lockx
.level
= RAW_LOCK_LOCKX
;
1664 lck
->lockx
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(2));
1665 lck
->lockx
.in
.mode
= SVAL(req
->in
.vwv
, VWV(3));
1666 lck
->lockx
.in
.timeout
= IVAL(req
->in
.vwv
, VWV(4));
1667 lck
->lockx
.in
.ulock_cnt
= SVAL(req
->in
.vwv
, VWV(6));
1668 lck
->lockx
.in
.lock_cnt
= SVAL(req
->in
.vwv
, VWV(7));
1670 total_locks
= lck
->lockx
.in
.ulock_cnt
+ lck
->lockx
.in
.lock_cnt
;
1672 /* there are two variants, one with 64 bit offsets and counts */
1673 if (lck
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
) {
1679 /* make sure we got the promised data */
1680 if (req_data_oob(&req
->in
.bufinfo
, req
->in
.data
, total_locks
* lck_size
)) {
1681 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1685 /* allocate the locks array */
1687 lck
->lockx
.in
.locks
= talloc_array(req
, struct smb_lock_entry
,
1689 if (lck
->lockx
.in
.locks
== NULL
) {
1690 smbsrv_send_error(req
, NT_STATUS_NO_MEMORY
);
1697 /* construct the locks array */
1698 for (i
=0;i
<total_locks
;i
++) {
1699 uint32_t ofs_high
=0, count_high
=0;
1701 lck
->lockx
.in
.locks
[i
].pid
= SVAL(p
, 0);
1703 if (lck
->lockx
.in
.mode
& LOCKING_ANDX_LARGE_FILES
) {
1704 ofs_high
= IVAL(p
, 4);
1705 lck
->lockx
.in
.locks
[i
].offset
= IVAL(p
, 8);
1706 count_high
= IVAL(p
, 12);
1707 lck
->lockx
.in
.locks
[i
].count
= IVAL(p
, 16);
1709 lck
->lockx
.in
.locks
[i
].offset
= IVAL(p
, 2);
1710 lck
->lockx
.in
.locks
[i
].count
= IVAL(p
, 6);
1712 if (ofs_high
!= 0 || count_high
!= 0) {
1713 lck
->lockx
.in
.locks
[i
].count
|= ((uint64_t)count_high
) << 32;
1714 lck
->lockx
.in
.locks
[i
].offset
|= ((uint64_t)ofs_high
) << 32;
1719 SMBSRV_CHECK_FILE_HANDLE(lck
->lockx
.in
.file
.ntvfs
);
1720 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_lock(req
->ntvfs
, lck
));
1723 /****************************************************************************
1724 Reply to a SMBreadbmpx (read block multiplex) request.
1725 ****************************************************************************/
1726 void smbsrv_reply_readbmpx(struct smbsrv_request
*req
)
1728 /* tell the client to not use a multiplexed read - its too broken to use */
1729 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRuseSTD
));
1733 /****************************************************************************
1734 Reply to a SMBsetattrE.
1735 ****************************************************************************/
1736 void smbsrv_reply_setattrE(struct smbsrv_request
*req
)
1738 union smb_setfileinfo
*info
;
1741 SMBSRV_CHECK_WCT(req
, 7);
1742 SMBSRV_TALLOC_IO_PTR(info
, union smb_setfileinfo
);
1743 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1745 info
->setattre
.level
= RAW_SFILEINFO_SETATTRE
;
1746 info
->setattre
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1747 info
->setattre
.in
.create_time
= srv_pull_dos_date2(req
->smb_conn
, req
->in
.vwv
+ VWV(1));
1748 info
->setattre
.in
.access_time
= srv_pull_dos_date2(req
->smb_conn
, req
->in
.vwv
+ VWV(3));
1749 info
->setattre
.in
.write_time
= srv_pull_dos_date2(req
->smb_conn
, req
->in
.vwv
+ VWV(5));
1751 SMBSRV_CHECK_FILE_HANDLE(info
->setattre
.in
.file
.ntvfs
);
1752 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_setfileinfo(req
->ntvfs
, info
));
1756 /****************************************************************************
1757 Reply to a SMBwritebmpx (write block multiplex primary) request.
1758 ****************************************************************************/
1759 void smbsrv_reply_writebmpx(struct smbsrv_request
*req
)
1761 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRuseSTD
));
1765 /****************************************************************************
1766 Reply to a SMBwritebs (write block multiplex secondary) request.
1767 ****************************************************************************/
1768 void smbsrv_reply_writebs(struct smbsrv_request
*req
)
1770 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRuseSTD
));
1775 /****************************************************************************
1776 Reply to a SMBgetattrE (async reply)
1777 ****************************************************************************/
1778 static void reply_getattrE_send(struct ntvfs_request
*ntvfs
)
1780 struct smbsrv_request
*req
;
1781 union smb_fileinfo
*info
;
1783 SMBSRV_CHECK_ASYNC_STATUS(info
, union smb_fileinfo
);
1786 smbsrv_setup_reply(req
, 11, 0);
1788 srv_push_dos_date2(req
->smb_conn
, req
->out
.vwv
, VWV(0), info
->getattre
.out
.create_time
);
1789 srv_push_dos_date2(req
->smb_conn
, req
->out
.vwv
, VWV(2), info
->getattre
.out
.access_time
);
1790 srv_push_dos_date2(req
->smb_conn
, req
->out
.vwv
, VWV(4), info
->getattre
.out
.write_time
);
1791 SIVAL(req
->out
.vwv
, VWV(6), info
->getattre
.out
.size
);
1792 SIVAL(req
->out
.vwv
, VWV(8), info
->getattre
.out
.alloc_size
);
1793 SSVAL(req
->out
.vwv
, VWV(10), info
->getattre
.out
.attrib
);
1795 smbsrv_send_reply(req
);
1798 /****************************************************************************
1799 Reply to a SMBgetattrE.
1800 ****************************************************************************/
1801 void smbsrv_reply_getattrE(struct smbsrv_request
*req
)
1803 union smb_fileinfo
*info
;
1806 SMBSRV_CHECK_WCT(req
, 1);
1807 SMBSRV_TALLOC_IO_PTR(info
, union smb_fileinfo
);
1808 SMBSRV_SETUP_NTVFS_REQUEST(reply_getattrE_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1810 info
->getattr
.level
= RAW_FILEINFO_GETATTRE
;
1811 info
->getattr
.in
.file
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, VWV(0));
1813 SMBSRV_CHECK_FILE_HANDLE(info
->getattr
.in
.file
.ntvfs
);
1814 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_qfileinfo(req
->ntvfs
, info
));
1817 void smbsrv_reply_sesssetup_send(struct smbsrv_request
*req
,
1818 union smb_sesssetup
*io
,
1821 switch (io
->old
.level
) {
1822 case RAW_SESSSETUP_OLD
:
1823 if (!NT_STATUS_IS_OK(status
)) {
1824 smbsrv_send_error(req
, status
);
1828 /* construct reply */
1829 smbsrv_setup_reply(req
, 3, 0);
1831 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1832 SSVAL(req
->out
.vwv
, VWV(1), 0);
1833 SSVAL(req
->out
.vwv
, VWV(2), io
->old
.out
.action
);
1835 SSVAL(req
->out
.hdr
, HDR_UID
, io
->old
.out
.vuid
);
1837 smbsrv_chain_reply(req
);
1840 case RAW_SESSSETUP_NT1
:
1841 if (!NT_STATUS_IS_OK(status
)) {
1842 smbsrv_send_error(req
, status
);
1846 /* construct reply */
1847 smbsrv_setup_reply(req
, 3, 0);
1849 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1850 SSVAL(req
->out
.vwv
, VWV(1), 0);
1851 SSVAL(req
->out
.vwv
, VWV(2), io
->nt1
.out
.action
);
1853 SSVAL(req
->out
.hdr
, HDR_UID
, io
->nt1
.out
.vuid
);
1855 req_push_str(req
, NULL
, io
->nt1
.out
.os
, -1, STR_TERMINATE
);
1856 req_push_str(req
, NULL
, io
->nt1
.out
.lanman
, -1, STR_TERMINATE
);
1857 req_push_str(req
, NULL
, io
->nt1
.out
.domain
, -1, STR_TERMINATE
);
1859 smbsrv_chain_reply(req
);
1862 case RAW_SESSSETUP_SPNEGO
:
1863 if (!NT_STATUS_IS_OK(status
) &&
1864 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1865 smbsrv_send_error(req
, status
);
1869 /* construct reply */
1870 smbsrv_setup_reply(req
, 4, io
->spnego
.out
.secblob
.length
);
1872 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
1873 smbsrv_setup_error(req
, status
);
1876 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
1877 SSVAL(req
->out
.vwv
, VWV(1), 0);
1878 SSVAL(req
->out
.vwv
, VWV(2), io
->spnego
.out
.action
);
1879 SSVAL(req
->out
.vwv
, VWV(3), io
->spnego
.out
.secblob
.length
);
1881 SSVAL(req
->out
.hdr
, HDR_UID
, io
->spnego
.out
.vuid
);
1883 memcpy(req
->out
.data
, io
->spnego
.out
.secblob
.data
, io
->spnego
.out
.secblob
.length
);
1884 req_push_str(req
, NULL
, io
->spnego
.out
.os
, -1, STR_TERMINATE
);
1885 req_push_str(req
, NULL
, io
->spnego
.out
.lanman
, -1, STR_TERMINATE
);
1886 req_push_str(req
, NULL
, io
->spnego
.out
.workgroup
, -1, STR_TERMINATE
);
1888 smbsrv_chain_reply(req
);
1891 case RAW_SESSSETUP_SMB2
:
1895 smbsrv_send_error(req
, NT_STATUS_INTERNAL_ERROR
);
1898 /****************************************************************************
1899 reply to an old style session setup command
1900 ****************************************************************************/
1901 static void reply_sesssetup_old(struct smbsrv_request
*req
)
1905 union smb_sesssetup
*io
;
1907 SMBSRV_TALLOC_IO_PTR(io
, union smb_sesssetup
);
1909 io
->old
.level
= RAW_SESSSETUP_OLD
;
1912 io
->old
.in
.bufsize
= SVAL(req
->in
.vwv
, VWV(2));
1913 io
->old
.in
.mpx_max
= SVAL(req
->in
.vwv
, VWV(3));
1914 io
->old
.in
.vc_num
= SVAL(req
->in
.vwv
, VWV(4));
1915 io
->old
.in
.sesskey
= IVAL(req
->in
.vwv
, VWV(5));
1916 passlen
= SVAL(req
->in
.vwv
, VWV(7));
1918 /* check the request isn't malformed */
1919 if (req_data_oob(&req
->in
.bufinfo
, req
->in
.data
, passlen
)) {
1920 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1925 if (!req_pull_blob(&req
->in
.bufinfo
, p
, passlen
, &io
->old
.in
.password
)) {
1926 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1931 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->old
.in
.user
, p
, -1, STR_TERMINATE
);
1932 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->old
.in
.domain
, p
, -1, STR_TERMINATE
);
1933 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->old
.in
.os
, p
, -1, STR_TERMINATE
);
1934 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->old
.in
.lanman
, p
, -1, STR_TERMINATE
);
1936 /* call the generic handler */
1937 smbsrv_sesssetup_backend(req
, io
);
1940 /****************************************************************************
1941 reply to an NT1 style session setup command
1942 ****************************************************************************/
1943 static void reply_sesssetup_nt1(struct smbsrv_request
*req
)
1946 uint16_t passlen1
, passlen2
;
1947 union smb_sesssetup
*io
;
1949 SMBSRV_TALLOC_IO_PTR(io
, union smb_sesssetup
);
1951 io
->nt1
.level
= RAW_SESSSETUP_NT1
;
1954 io
->nt1
.in
.bufsize
= SVAL(req
->in
.vwv
, VWV(2));
1955 io
->nt1
.in
.mpx_max
= SVAL(req
->in
.vwv
, VWV(3));
1956 io
->nt1
.in
.vc_num
= SVAL(req
->in
.vwv
, VWV(4));
1957 io
->nt1
.in
.sesskey
= IVAL(req
->in
.vwv
, VWV(5));
1958 passlen1
= SVAL(req
->in
.vwv
, VWV(7));
1959 passlen2
= SVAL(req
->in
.vwv
, VWV(8));
1960 io
->nt1
.in
.capabilities
= IVAL(req
->in
.vwv
, VWV(11));
1962 /* check the request isn't malformed */
1963 if (req_data_oob(&req
->in
.bufinfo
, req
->in
.data
, passlen1
) ||
1964 req_data_oob(&req
->in
.bufinfo
, req
->in
.data
+ passlen1
, passlen2
)) {
1965 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1970 if (!req_pull_blob(&req
->in
.bufinfo
, p
, passlen1
, &io
->nt1
.in
.password1
)) {
1971 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1975 if (!req_pull_blob(&req
->in
.bufinfo
, p
, passlen2
, &io
->nt1
.in
.password2
)) {
1976 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1981 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->nt1
.in
.user
, p
, -1, STR_TERMINATE
);
1982 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->nt1
.in
.domain
, p
, -1, STR_TERMINATE
);
1983 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->nt1
.in
.os
, p
, -1, STR_TERMINATE
);
1984 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->nt1
.in
.lanman
, p
, -1, STR_TERMINATE
);
1986 /* call the generic handler */
1987 smbsrv_sesssetup_backend(req
, io
);
1991 /****************************************************************************
1992 reply to an SPNEGO style session setup command
1993 ****************************************************************************/
1994 static void reply_sesssetup_spnego(struct smbsrv_request
*req
)
1998 union smb_sesssetup
*io
;
2000 SMBSRV_TALLOC_IO_PTR(io
, union smb_sesssetup
);
2002 io
->spnego
.level
= RAW_SESSSETUP_SPNEGO
;
2005 io
->spnego
.in
.bufsize
= SVAL(req
->in
.vwv
, VWV(2));
2006 io
->spnego
.in
.mpx_max
= SVAL(req
->in
.vwv
, VWV(3));
2007 io
->spnego
.in
.vc_num
= SVAL(req
->in
.vwv
, VWV(4));
2008 io
->spnego
.in
.sesskey
= IVAL(req
->in
.vwv
, VWV(5));
2009 blob_len
= SVAL(req
->in
.vwv
, VWV(7));
2010 io
->spnego
.in
.capabilities
= IVAL(req
->in
.vwv
, VWV(10));
2013 if (!req_pull_blob(&req
->in
.bufinfo
, p
, blob_len
, &io
->spnego
.in
.secblob
)) {
2014 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
2019 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->spnego
.in
.os
, p
, -1, STR_TERMINATE
);
2020 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->spnego
.in
.lanman
, p
, -1, STR_TERMINATE
);
2021 p
+= req_pull_string(&req
->in
.bufinfo
, &io
->spnego
.in
.workgroup
, p
, -1, STR_TERMINATE
);
2023 /* call the generic handler */
2024 smbsrv_sesssetup_backend(req
, io
);
2028 /****************************************************************************
2029 reply to a session setup command
2030 ****************************************************************************/
2031 void smbsrv_reply_sesssetup(struct smbsrv_request
*req
)
2033 switch (req
->in
.wct
) {
2035 /* a pre-NT1 call */
2036 reply_sesssetup_old(req
);
2040 reply_sesssetup_nt1(req
);
2044 reply_sesssetup_spnego(req
);
2048 /* unsupported variant */
2049 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
2052 /****************************************************************************
2053 Reply to a exit. This closes all files open by a smbpid
2054 ****************************************************************************/
2055 void smbsrv_reply_exit(struct smbsrv_request
*req
)
2057 struct smbsrv_handle_session_item
*i
, *ni
;
2058 struct smbsrv_handle
*h
;
2059 struct smbsrv_tcon
*tcon
;
2062 SMBSRV_CHECK_WCT(req
, 0);
2064 smbpid
= SVAL(req
->in
.hdr
,HDR_PID
);
2066 /* first destroy all handles, which have the same PID as the request */
2067 for (i
=req
->session
->handles
; i
; i
=ni
) {
2070 if (h
->smbpid
!= smbpid
) continue;
2076 * then let the ntvfs backends proxy the call if they want to,
2077 * but we didn't check the return value of the backends,
2078 * as for the SMB client the call succeed
2080 for (tcon
=req
->smb_conn
->smb_tcons
.list
;tcon
;tcon
=tcon
->next
) {
2082 SMBSRV_SETUP_NTVFS_REQUEST(NULL
,0);
2083 ntvfs_exit(req
->ntvfs
);
2084 talloc_free(req
->ntvfs
);
2089 smbsrv_setup_reply(req
, 0, 0);
2090 smbsrv_send_reply(req
);
2093 /****************************************************************************
2094 Reply to a SMBulogoffX.
2095 ****************************************************************************/
2096 void smbsrv_reply_ulogoffX(struct smbsrv_request
*req
)
2098 struct smbsrv_handle_session_item
*i
, *ni
;
2099 struct smbsrv_handle
*h
;
2100 struct smbsrv_tcon
*tcon
;
2102 SMBSRV_CHECK_WCT(req
, 2);
2105 * TODO: cancel all pending requests
2109 /* destroy all handles */
2110 for (i
=req
->session
->handles
; i
; i
=ni
) {
2117 * then let the ntvfs backends proxy the call if they want to,
2118 * but we didn't check the return value of the backends,
2119 * as for the SMB client the call succeed
2121 for (tcon
=req
->smb_conn
->smb_tcons
.list
;tcon
;tcon
=tcon
->next
) {
2123 SMBSRV_SETUP_NTVFS_REQUEST(NULL
,0);
2124 ntvfs_logoff(req
->ntvfs
);
2125 talloc_free(req
->ntvfs
);
2130 talloc_free(req
->session
);
2131 req
->session
= NULL
; /* it is now invalid, don't use on
2132 any chained packets */
2134 smbsrv_setup_reply(req
, 2, 0);
2136 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
2137 SSVAL(req
->out
.vwv
, VWV(1), 0);
2139 smbsrv_chain_reply(req
);
2142 /****************************************************************************
2143 Reply to an SMBfindclose request
2144 ****************************************************************************/
2145 void smbsrv_reply_findclose(struct smbsrv_request
*req
)
2147 union smb_search_close
*io
;
2150 SMBSRV_CHECK_WCT(req
, 1);
2151 SMBSRV_TALLOC_IO_PTR(io
, union smb_search_close
);
2152 SMBSRV_SETUP_NTVFS_REQUEST(reply_simple_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
2154 io
->findclose
.level
= RAW_FINDCLOSE_FINDCLOSE
;
2155 io
->findclose
.in
.handle
= SVAL(req
->in
.vwv
, VWV(0));
2157 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_search_close(req
->ntvfs
, io
));
2160 /****************************************************************************
2161 Reply to an SMBfindnclose request
2162 ****************************************************************************/
2163 void smbsrv_reply_findnclose(struct smbsrv_request
*req
)
2165 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
2169 /****************************************************************************
2170 Reply to an SMBntcreateX request (async send)
2171 ****************************************************************************/
2172 static void reply_ntcreate_and_X_send(struct ntvfs_request
*ntvfs
)
2174 struct smbsrv_request
*req
;
2177 SMBSRV_CHECK_ASYNC_STATUS(io
, union smb_open
);
2179 /* construct reply */
2180 smbsrv_setup_reply(req
, 34, 0);
2182 SSVAL(req
->out
.vwv
, VWV(0), SMB_CHAIN_NONE
);
2183 SSVAL(req
->out
.vwv
, VWV(1), 0);
2184 SCVAL(req
->out
.vwv
, VWV(2), io
->ntcreatex
.out
.oplock_level
);
2186 /* the rest of the parameters are not aligned! */
2187 smbsrv_push_fnum(req
->out
.vwv
, 5, io
->ntcreatex
.out
.file
.ntvfs
);
2188 SIVAL(req
->out
.vwv
, 7, io
->ntcreatex
.out
.create_action
);
2189 push_nttime(req
->out
.vwv
, 11, io
->ntcreatex
.out
.create_time
);
2190 push_nttime(req
->out
.vwv
, 19, io
->ntcreatex
.out
.access_time
);
2191 push_nttime(req
->out
.vwv
, 27, io
->ntcreatex
.out
.write_time
);
2192 push_nttime(req
->out
.vwv
, 35, io
->ntcreatex
.out
.change_time
);
2193 SIVAL(req
->out
.vwv
, 43, io
->ntcreatex
.out
.attrib
);
2194 SBVAL(req
->out
.vwv
, 47, io
->ntcreatex
.out
.alloc_size
);
2195 SBVAL(req
->out
.vwv
, 55, io
->ntcreatex
.out
.size
);
2196 SSVAL(req
->out
.vwv
, 63, io
->ntcreatex
.out
.file_type
);
2197 SSVAL(req
->out
.vwv
, 65, io
->ntcreatex
.out
.ipc_state
);
2198 SCVAL(req
->out
.vwv
, 67, io
->ntcreatex
.out
.is_directory
);
2200 req
->chained_fnum
= SVAL(req
->out
.vwv
, 5);
2202 smbsrv_chain_reply(req
);
2205 /****************************************************************************
2206 Reply to an SMBntcreateX request
2207 ****************************************************************************/
2208 void smbsrv_reply_ntcreate_and_X(struct smbsrv_request
*req
)
2213 /* parse the request */
2214 SMBSRV_CHECK_WCT(req
, 24);
2215 SMBSRV_TALLOC_IO_PTR(io
, union smb_open
);
2216 SMBSRV_SETUP_NTVFS_REQUEST(reply_ntcreate_and_X_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
2218 io
->ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
2220 /* notice that the word parameters are not word aligned, so we don't use VWV() */
2221 fname_len
= SVAL(req
->in
.vwv
, 5);
2222 io
->ntcreatex
.in
.flags
= IVAL(req
->in
.vwv
, 7);
2223 io
->ntcreatex
.in
.root_fid
.ntvfs
= smbsrv_pull_fnum(req
, req
->in
.vwv
, 11);
2224 io
->ntcreatex
.in
.access_mask
= IVAL(req
->in
.vwv
, 15);
2225 io
->ntcreatex
.in
.alloc_size
= BVAL(req
->in
.vwv
, 19);
2226 io
->ntcreatex
.in
.file_attr
= IVAL(req
->in
.vwv
, 27);
2227 io
->ntcreatex
.in
.share_access
= IVAL(req
->in
.vwv
, 31);
2228 io
->ntcreatex
.in
.open_disposition
= IVAL(req
->in
.vwv
, 35);
2229 io
->ntcreatex
.in
.create_options
= IVAL(req
->in
.vwv
, 39);
2230 io
->ntcreatex
.in
.impersonation
= IVAL(req
->in
.vwv
, 43);
2231 io
->ntcreatex
.in
.security_flags
= CVAL(req
->in
.vwv
, 47);
2232 io
->ntcreatex
.in
.ea_list
= NULL
;
2233 io
->ntcreatex
.in
.sec_desc
= NULL
;
2234 io
->ntcreatex
.in
.query_maximal_access
= false;
2235 io
->ntcreatex
.in
.private_flags
= 0;
2237 /* we need a neater way to handle this alignment */
2238 if ((req
->flags2
& FLAGS2_UNICODE_STRINGS
) &&
2239 ucs2_align(req
->in
.buffer
, req
->in
.data
, STR_TERMINATE
|STR_UNICODE
)) {
2243 req_pull_string(&req
->in
.bufinfo
, &io
->ntcreatex
.in
.fname
, req
->in
.data
, fname_len
, STR_TERMINATE
);
2244 if (!io
->ntcreatex
.in
.fname
) {
2245 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
2249 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_open(req
->ntvfs
, io
));
2253 /****************************************************************************
2254 Reply to an SMBntcancel request
2255 ****************************************************************************/
2256 void smbsrv_reply_ntcancel(struct smbsrv_request
*req
)
2258 struct smbsrv_request
*r
;
2259 uint16_t tid
= SVAL(req
->in
.hdr
,HDR_TID
);
2260 uint16_t uid
= SVAL(req
->in
.hdr
,HDR_UID
);
2261 uint16_t mid
= SVAL(req
->in
.hdr
,HDR_MID
);
2262 uint16_t pid
= SVAL(req
->in
.hdr
,HDR_PID
);
2264 for (r
= req
->smb_conn
->requests
; r
; r
= r
->next
) {
2265 if (tid
!= SVAL(r
->in
.hdr
,HDR_TID
)) continue;
2266 if (uid
!= SVAL(r
->in
.hdr
,HDR_UID
)) continue;
2267 if (mid
!= SVAL(r
->in
.hdr
,HDR_MID
)) continue;
2268 if (pid
!= SVAL(r
->in
.hdr
,HDR_PID
)) continue;
2270 SMBSRV_CHECK(ntvfs_cancel(r
->ntvfs
));
2272 /* NOTE: this request does not generate a reply */
2277 /* TODO: workout the correct error code,
2278 * until we know how the smb signing works
2279 * for ntcancel replies, don't send an error
2281 /*smbsrv_send_error(req, NT_STATUS_FOOBAR);*/
2286 parse the called/calling names from session request
2288 static NTSTATUS
parse_session_request(struct smbsrv_request
*req
)
2293 blob
.data
= req
->in
.buffer
+ 4;
2294 blob
.length
= ascii_len_n((const char *)blob
.data
, req
->in
.size
- PTR_DIFF(blob
.data
, req
->in
.buffer
));
2295 if (blob
.length
== 0) return NT_STATUS_BAD_NETWORK_NAME
;
2297 req
->smb_conn
->negotiate
.called_name
= talloc(req
->smb_conn
, struct nbt_name
);
2298 req
->smb_conn
->negotiate
.calling_name
= talloc(req
->smb_conn
, struct nbt_name
);
2299 if (req
->smb_conn
->negotiate
.called_name
== NULL
||
2300 req
->smb_conn
->negotiate
.calling_name
== NULL
) {
2301 return NT_STATUS_NO_MEMORY
;
2304 status
= nbt_name_from_blob(req
->smb_conn
, &blob
,
2305 req
->smb_conn
->negotiate
.called_name
);
2306 NT_STATUS_NOT_OK_RETURN(status
);
2308 blob
.data
+= blob
.length
;
2309 blob
.length
= ascii_len_n((const char *)blob
.data
, req
->in
.size
- PTR_DIFF(blob
.data
, req
->in
.buffer
));
2310 if (blob
.length
== 0) return NT_STATUS_BAD_NETWORK_NAME
;
2312 status
= nbt_name_from_blob(req
->smb_conn
, &blob
,
2313 req
->smb_conn
->negotiate
.calling_name
);
2314 NT_STATUS_NOT_OK_RETURN(status
);
2316 req
->smb_conn
->negotiate
.done_nbt_session
= true;
2318 return NT_STATUS_OK
;
2323 /****************************************************************************
2324 Reply to a special message - a SMB packet with non zero NBT message type
2325 ****************************************************************************/
2326 void smbsrv_reply_special(struct smbsrv_request
*req
)
2329 uint8_t *buf
= talloc_zero_array(req
, uint8_t, 4);
2331 msg_type
= CVAL(req
->in
.buffer
,0);
2336 case NBSSrequest
: /* session request */
2337 if (req
->smb_conn
->negotiate
.done_nbt_session
) {
2338 DEBUG(0,("Warning: ignoring secondary session request\n"));
2345 /* we don't check the status - samba always accepts session
2346 requests for any name */
2347 parse_session_request(req
);
2349 req
->out
.buffer
= buf
;
2351 smbsrv_send_reply_nosign(req
);
2354 case 0x89: /* session keepalive request
2355 (some old clients produce this?) */
2356 SCVAL(buf
, 0, NBSSkeepalive
);
2358 req
->out
.buffer
= buf
;
2360 smbsrv_send_reply_nosign(req
);
2364 /* session keepalive - swallow it */
2369 DEBUG(0,("Unexpected NBT session packet (%d)\n", msg_type
));