2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 This file handles the parsing of transact2 requests
25 #include "dlinklist.h"
26 #include "smb_server/smb_server.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "ntvfs/ntvfs.h"
29 #include "libcli/raw/libcliraw.h"
31 #define TRANS2_CHECK_ASYNC_STATUS_SIMPLE do { \
32 if (!NT_STATUS_IS_OK(req->ntvfs->async_states->status)) { \
33 trans2_setup_reply(trans, 0, 0, 0);\
34 return req->ntvfs->async_states->status; \
37 #define TRANS2_CHECK_ASYNC_STATUS(ptr, type) do { \
38 TRANS2_CHECK_ASYNC_STATUS_SIMPLE; \
39 ptr = talloc_get_type(op->op_info, type); \
41 #define TRANS2_CHECK(cmd) do { \
44 NT_STATUS_NOT_OK_RETURN(_status); \
48 hold the state of a nttrans op while in progress. Needed to allow for async backend
52 struct smbsrv_request
*req
;
53 struct smb_trans2
*trans
;
55 NTSTATUS (*send_fn
)(struct trans_op
*);
59 #define CHECK_MIN_BLOB_SIZE(blob, size) do { \
60 if ((blob)->length < (size)) { \
61 return NT_STATUS_INFO_LENGTH_MISMATCH; \
64 /* grow the data size of a trans2 reply */
65 static NTSTATUS
trans2_grow_data(TALLOC_CTX
*mem_ctx
,
69 if (new_size
> blob
->length
) {
70 blob
->data
= talloc_realloc(mem_ctx
, blob
->data
, uint8_t, new_size
);
71 NT_STATUS_HAVE_NO_MEMORY(blob
->data
);
73 blob
->length
= new_size
;
77 /* grow the data, zero filling any new bytes */
78 static NTSTATUS
trans2_grow_data_fill(TALLOC_CTX
*mem_ctx
,
82 uint32_t old_size
= blob
->length
;
83 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, new_size
));
84 if (new_size
> old_size
) {
85 memset(blob
->data
+ old_size
, 0, new_size
- old_size
);
91 /* setup a trans2 reply, given the data and params sizes */
92 static NTSTATUS
trans2_setup_reply(struct smb_trans2
*trans
,
93 uint16_t param_size
, uint16_t data_size
,
96 trans
->out
.setup_count
= setup_count
;
97 if (setup_count
> 0) {
98 trans
->out
.setup
= talloc_zero_array(trans
, uint16_t, setup_count
);
99 NT_STATUS_HAVE_NO_MEMORY(trans
->out
.setup
);
101 trans
->out
.params
= data_blob_talloc(trans
, NULL
, param_size
);
102 if (param_size
> 0) NT_STATUS_HAVE_NO_MEMORY(trans
->out
.params
.data
);
104 trans
->out
.data
= data_blob_talloc(trans
, NULL
, data_size
);
105 if (data_size
> 0) NT_STATUS_HAVE_NO_MEMORY(trans
->out
.data
.data
);
112 pull a string from a blob in a trans2 request
114 static size_t trans2_pull_blob_string(struct smbsrv_request
*req
,
115 const DATA_BLOB
*blob
,
120 /* we use STR_NO_RANGE_CHECK because the params are allocated
121 separately in a DATA_BLOB, so we need to do our own range
123 if (offset
>= blob
->length
) {
128 return req_pull_string(req
, str
,
130 blob
->length
- offset
,
131 STR_NO_RANGE_CHECK
| flags
);
135 push a string into the data section of a trans2 request
136 return the number of bytes consumed in the output
138 static size_t trans2_push_data_string(struct smbsrv_request
*req
,
143 const struct smb_wire_string
*str
,
147 int alignment
= 0, ret
= 0, pkt_len
;
149 /* we use STR_NO_RANGE_CHECK because the params are allocated
150 separately in a DATA_BLOB, so we need to do our own range
152 if (!str
->s
|| offset
>= blob
->length
) {
153 if (flags
& STR_LEN8BIT
) {
154 SCVAL(blob
->data
, len_offset
, 0);
156 SIVAL(blob
->data
, len_offset
, 0);
161 flags
|= STR_NO_RANGE_CHECK
;
163 if (dest_len
== -1 || (dest_len
> blob
->length
- offset
)) {
164 dest_len
= blob
->length
- offset
;
167 if (!(flags
& (STR_ASCII
|STR_UNICODE
))) {
168 flags
|= (req
->flags2
& FLAGS2_UNICODE_STRINGS
) ? STR_UNICODE
: STR_ASCII
;
171 if ((offset
&1) && (flags
& STR_UNICODE
) && !(flags
& STR_NOALIGN
)) {
174 SCVAL(blob
->data
+ offset
, 0, 0);
175 ret
= push_string(blob
->data
+ offset
+ 1, str
->s
, dest_len
-1, flags
);
178 ret
= push_string(blob
->data
+ offset
, str
->s
, dest_len
, flags
);
181 /* sometimes the string needs to be terminated, but the length
182 on the wire must not include the termination! */
185 if ((flags
& STR_LEN_NOTERM
) && (flags
& STR_TERMINATE
)) {
186 if ((flags
& STR_UNICODE
) && ret
>= 2) {
189 if ((flags
& STR_ASCII
) && ret
>= 1) {
194 if (flags
& STR_LEN8BIT
) {
195 SCVAL(blob
->data
, len_offset
, pkt_len
);
197 SIVAL(blob
->data
, len_offset
, pkt_len
);
200 return ret
+ alignment
;
204 append a string to the data section of a trans2 reply
205 len_offset points to the place in the packet where the length field
208 static NTSTATUS
trans2_append_data_string(struct smbsrv_request
*req
,
211 const struct smb_wire_string
*str
,
217 const int max_bytes_per_char
= 3;
219 offset
= blob
->length
;
220 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, offset
+ (2+strlen_m(str
->s
))*max_bytes_per_char
));
221 ret
= trans2_push_data_string(req
, mem_ctx
, blob
, len_offset
, offset
, str
, -1, flags
);
223 return NT_STATUS_FOOBAR
;
225 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, offset
+ ret
));
230 align the end of the data section of a trans reply on an even boundary
232 static NTSTATUS
trans2_align_data(struct smb_trans2
*trans
)
234 if (trans
->out
.data
.length
& 1) {
235 TRANS2_CHECK(trans2_grow_data_fill(trans
, &trans
->out
.data
, trans
->out
.data
.length
+1));
242 trans2 qfsinfo implementation send
244 static NTSTATUS
trans2_qfsinfo_send(struct trans_op
*op
)
246 struct smbsrv_request
*req
= op
->req
;
247 struct smb_trans2
*trans
= op
->trans
;
248 union smb_fsinfo
*fsinfo
;
253 TRANS2_CHECK_ASYNC_STATUS(fsinfo
, union smb_fsinfo
);
255 switch (fsinfo
->generic
.level
) {
256 case SMB_QFS_ALLOCATION
:
257 trans2_setup_reply(trans
, 0, 18, 0);
259 SIVAL(trans
->out
.data
.data
, 0, fsinfo
->allocation
.out
.fs_id
);
260 SIVAL(trans
->out
.data
.data
, 4, fsinfo
->allocation
.out
.sectors_per_unit
);
261 SIVAL(trans
->out
.data
.data
, 8, fsinfo
->allocation
.out
.total_alloc_units
);
262 SIVAL(trans
->out
.data
.data
, 12, fsinfo
->allocation
.out
.avail_alloc_units
);
263 SSVAL(trans
->out
.data
.data
, 16, fsinfo
->allocation
.out
.bytes_per_sector
);
268 trans2_setup_reply(trans
, 0, 5, 0);
270 SIVAL(trans
->out
.data
.data
, 0, fsinfo
->volume
.out
.serial_number
);
271 /* w2k3 implements this incorrectly for unicode - it
272 * leaves the last byte off the string */
273 trans2_append_data_string(req
, trans
, &trans
->out
.data
,
274 &fsinfo
->volume
.out
.volume_name
,
275 4, STR_LEN8BIT
|STR_NOALIGN
);
279 case SMB_QFS_VOLUME_INFO
:
280 case SMB_QFS_VOLUME_INFORMATION
:
281 trans2_setup_reply(trans
, 0, 18, 0);
283 push_nttime(trans
->out
.data
.data
, 0, fsinfo
->volume_info
.out
.create_time
);
284 SIVAL(trans
->out
.data
.data
, 8, fsinfo
->volume_info
.out
.serial_number
);
285 SSVAL(trans
->out
.data
.data
, 16, 0); /* padding */
286 trans2_append_data_string(req
, trans
, &trans
->out
.data
,
287 &fsinfo
->volume_info
.out
.volume_name
,
292 case SMB_QFS_SIZE_INFO
:
293 case SMB_QFS_SIZE_INFORMATION
:
294 trans2_setup_reply(trans
, 0, 24, 0);
296 SBVAL(trans
->out
.data
.data
, 0, fsinfo
->size_info
.out
.total_alloc_units
);
297 SBVAL(trans
->out
.data
.data
, 8, fsinfo
->size_info
.out
.avail_alloc_units
);
298 SIVAL(trans
->out
.data
.data
, 16, fsinfo
->size_info
.out
.sectors_per_unit
);
299 SIVAL(trans
->out
.data
.data
, 20, fsinfo
->size_info
.out
.bytes_per_sector
);
303 case SMB_QFS_DEVICE_INFO
:
304 case SMB_QFS_DEVICE_INFORMATION
:
305 trans2_setup_reply(trans
, 0, 8, 0);
306 SIVAL(trans
->out
.data
.data
, 0, fsinfo
->device_info
.out
.device_type
);
307 SIVAL(trans
->out
.data
.data
, 4, fsinfo
->device_info
.out
.characteristics
);
311 case SMB_QFS_ATTRIBUTE_INFO
:
312 case SMB_QFS_ATTRIBUTE_INFORMATION
:
313 trans2_setup_reply(trans
, 0, 12, 0);
315 SIVAL(trans
->out
.data
.data
, 0, fsinfo
->attribute_info
.out
.fs_attr
);
316 SIVAL(trans
->out
.data
.data
, 4, fsinfo
->attribute_info
.out
.max_file_component_length
);
317 /* this must not be null terminated or win98 gets
318 confused! also note that w2k3 returns this as
319 unicode even when ascii is negotiated */
320 trans2_append_data_string(req
, trans
, &trans
->out
.data
,
321 &fsinfo
->attribute_info
.out
.fs_type
,
326 case SMB_QFS_QUOTA_INFORMATION
:
327 trans2_setup_reply(trans
, 0, 48, 0);
329 SBVAL(trans
->out
.data
.data
, 0, fsinfo
->quota_information
.out
.unknown
[0]);
330 SBVAL(trans
->out
.data
.data
, 8, fsinfo
->quota_information
.out
.unknown
[1]);
331 SBVAL(trans
->out
.data
.data
, 16, fsinfo
->quota_information
.out
.unknown
[2]);
332 SBVAL(trans
->out
.data
.data
, 24, fsinfo
->quota_information
.out
.quota_soft
);
333 SBVAL(trans
->out
.data
.data
, 32, fsinfo
->quota_information
.out
.quota_hard
);
334 SBVAL(trans
->out
.data
.data
, 40, fsinfo
->quota_information
.out
.quota_flags
);
339 case SMB_QFS_FULL_SIZE_INFORMATION
:
340 trans2_setup_reply(trans
, 0, 32, 0);
342 SBVAL(trans
->out
.data
.data
, 0, fsinfo
->full_size_information
.out
.total_alloc_units
);
343 SBVAL(trans
->out
.data
.data
, 8, fsinfo
->full_size_information
.out
.call_avail_alloc_units
);
344 SBVAL(trans
->out
.data
.data
, 16, fsinfo
->full_size_information
.out
.actual_avail_alloc_units
);
345 SIVAL(trans
->out
.data
.data
, 24, fsinfo
->full_size_information
.out
.sectors_per_unit
);
346 SIVAL(trans
->out
.data
.data
, 28, fsinfo
->full_size_information
.out
.bytes_per_sector
);
350 case SMB_QFS_OBJECTID_INFORMATION
:
351 trans2_setup_reply(trans
, 0, 64, 0);
353 status
= ndr_push_struct_blob(&guid_blob
, req
,
354 &fsinfo
->objectid_information
.out
.guid
,
355 (ndr_push_flags_fn_t
)ndr_push_GUID
);
356 if (!NT_STATUS_IS_OK(status
)) {
360 memcpy(trans
->out
.data
.data
, guid_blob
.data
, guid_blob
.length
);
363 SBVAL(trans
->out
.data
.data
, 16 + 8*i
, fsinfo
->objectid_information
.out
.unknown
[i
]);
368 return NT_STATUS_INVALID_LEVEL
;
372 trans2 qfsinfo implementation
374 static NTSTATUS
trans2_qfsinfo(struct smbsrv_request
*req
, struct trans_op
*op
)
376 struct smb_trans2
*trans
= op
->trans
;
377 union smb_fsinfo
*fsinfo
;
380 /* make sure we got enough parameters */
381 if (trans
->in
.params
.length
!= 2) {
382 return NT_STATUS_FOOBAR
;
385 fsinfo
= talloc(op
, union smb_fsinfo
);
386 NT_STATUS_HAVE_NO_MEMORY(fsinfo
);
388 op
->op_info
= fsinfo
;
389 op
->send_fn
= trans2_qfsinfo_send
;
391 level
= SVAL(trans
->in
.params
.data
, 0);
394 case SMB_QFS_ALLOCATION
:
395 fsinfo
->allocation
.level
= RAW_QFS_ALLOCATION
;
396 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
399 fsinfo
->volume
.level
= RAW_QFS_VOLUME
;
400 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
402 case SMB_QFS_VOLUME_INFO
:
403 case SMB_QFS_VOLUME_INFORMATION
:
404 fsinfo
->volume_info
.level
= RAW_QFS_VOLUME_INFO
;
405 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
407 case SMB_QFS_SIZE_INFO
:
408 case SMB_QFS_SIZE_INFORMATION
:
409 fsinfo
->size_info
.level
= RAW_QFS_SIZE_INFO
;
410 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
412 case SMB_QFS_DEVICE_INFO
:
413 case SMB_QFS_DEVICE_INFORMATION
:
414 fsinfo
->device_info
.level
= RAW_QFS_DEVICE_INFO
;
415 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
417 case SMB_QFS_ATTRIBUTE_INFO
:
418 case SMB_QFS_ATTRIBUTE_INFORMATION
:
419 fsinfo
->attribute_info
.level
= RAW_QFS_ATTRIBUTE_INFO
;
420 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
422 case SMB_QFS_QUOTA_INFORMATION
:
423 fsinfo
->quota_information
.level
= RAW_QFS_QUOTA_INFORMATION
;
424 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
426 case SMB_QFS_FULL_SIZE_INFORMATION
:
427 fsinfo
->full_size_information
.level
= RAW_QFS_FULL_SIZE_INFORMATION
;
428 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
430 case SMB_QFS_OBJECTID_INFORMATION
:
431 fsinfo
->objectid_information
.level
= RAW_QFS_OBJECTID_INFORMATION
;
432 return ntvfs_fsinfo(req
->ntvfs
, fsinfo
);
435 return NT_STATUS_INVALID_LEVEL
;
440 trans2 open implementation send
442 static NTSTATUS
trans2_open_send(struct trans_op
*op
)
444 struct smbsrv_request
*req
= op
->req
;
445 struct smb_trans2
*trans
= op
->trans
;
448 TRANS2_CHECK_ASYNC_STATUS(io
, union smb_open
);
450 trans2_setup_reply(trans
, 30, 0, 0);
452 smbsrv_push_fnum(trans
->out
.params
.data
, VWV(0), io
->t2open
.out
.file
.ntvfs
);
453 SSVAL(trans
->out
.params
.data
, VWV(1), io
->t2open
.out
.attrib
);
454 srv_push_dos_date3(req
->smb_conn
, trans
->out
.params
.data
,
455 VWV(2), io
->t2open
.out
.write_time
);
456 SIVAL(trans
->out
.params
.data
, VWV(4), io
->t2open
.out
.size
);
457 SSVAL(trans
->out
.params
.data
, VWV(6), io
->t2open
.out
.access
);
458 SSVAL(trans
->out
.params
.data
, VWV(7), io
->t2open
.out
.ftype
);
459 SSVAL(trans
->out
.params
.data
, VWV(8), io
->t2open
.out
.devstate
);
460 SSVAL(trans
->out
.params
.data
, VWV(9), io
->t2open
.out
.action
);
461 SIVAL(trans
->out
.params
.data
, VWV(10), 0); /* reserved */
462 SSVAL(trans
->out
.params
.data
, VWV(12), 0); /* EaErrorOffset */
463 SIVAL(trans
->out
.params
.data
, VWV(13), 0); /* EaLength */
469 trans2 open implementation
471 static NTSTATUS
trans2_open(struct smbsrv_request
*req
, struct trans_op
*op
)
473 struct smb_trans2
*trans
= op
->trans
;
477 /* make sure we got enough parameters */
478 if (trans
->in
.params
.length
< 29) {
479 return NT_STATUS_FOOBAR
;
482 io
= talloc(op
, union smb_open
);
483 NT_STATUS_HAVE_NO_MEMORY(io
);
485 io
->t2open
.level
= RAW_OPEN_T2OPEN
;
486 io
->t2open
.in
.flags
= SVAL(trans
->in
.params
.data
, VWV(0));
487 io
->t2open
.in
.open_mode
= SVAL(trans
->in
.params
.data
, VWV(1));
488 io
->t2open
.in
.search_attrs
= SVAL(trans
->in
.params
.data
, VWV(2));
489 io
->t2open
.in
.file_attrs
= SVAL(trans
->in
.params
.data
, VWV(3));
490 io
->t2open
.in
.write_time
= srv_pull_dos_date(req
->smb_conn
,
491 trans
->in
.params
.data
+ VWV(4));;
492 io
->t2open
.in
.open_func
= SVAL(trans
->in
.params
.data
, VWV(6));
493 io
->t2open
.in
.size
= IVAL(trans
->in
.params
.data
, VWV(7));
494 io
->t2open
.in
.timeout
= IVAL(trans
->in
.params
.data
, VWV(9));
495 io
->t2open
.in
.num_eas
= 0;
496 io
->t2open
.in
.eas
= NULL
;
498 trans2_pull_blob_string(req
, &trans
->in
.params
, 28, &io
->t2open
.in
.fname
, 0);
500 status
= ea_pull_list(&trans
->in
.data
, io
, &io
->t2open
.in
.num_eas
, &io
->t2open
.in
.eas
);
501 NT_STATUS_NOT_OK_RETURN(status
);
504 op
->send_fn
= trans2_open_send
;
506 return ntvfs_open(req
->ntvfs
, io
);
513 static NTSTATUS
trans2_simple_send(struct trans_op
*op
)
515 struct smbsrv_request
*req
= op
->req
;
516 struct smb_trans2
*trans
= op
->trans
;
518 TRANS2_CHECK_ASYNC_STATUS_SIMPLE
;
520 trans2_setup_reply(trans
, 2, 0, 0);
522 SSVAL(trans
->out
.params
.data
, VWV(0), 0);
528 trans2 mkdir implementation
530 static NTSTATUS
trans2_mkdir(struct smbsrv_request
*req
, struct trans_op
*op
)
532 struct smb_trans2
*trans
= op
->trans
;
536 /* make sure we got enough parameters */
537 if (trans
->in
.params
.length
< 5) {
538 return NT_STATUS_FOOBAR
;
541 io
= talloc(op
, union smb_mkdir
);
542 NT_STATUS_HAVE_NO_MEMORY(io
);
544 io
->t2mkdir
.level
= RAW_MKDIR_T2MKDIR
;
545 trans2_pull_blob_string(req
, &trans
->in
.params
, 4, &io
->t2mkdir
.in
.path
, 0);
547 status
= ea_pull_list(&trans
->in
.data
, io
,
548 &io
->t2mkdir
.in
.num_eas
,
549 &io
->t2mkdir
.in
.eas
);
550 NT_STATUS_NOT_OK_RETURN(status
);
553 op
->send_fn
= trans2_simple_send
;
555 return ntvfs_mkdir(req
->ntvfs
, io
);
558 static NTSTATUS
trans2_push_fileinfo(struct smbsrv_request
*req
,
559 union smb_fileinfo
*st
,
566 switch (st
->generic
.level
) {
567 case RAW_FILEINFO_GENERIC
:
568 case RAW_FILEINFO_GETATTR
:
569 case RAW_FILEINFO_GETATTRE
:
570 case RAW_FILEINFO_SEC_DESC
:
571 /* handled elsewhere */
572 return NT_STATUS_INVALID_LEVEL
;
574 case RAW_FILEINFO_BASIC_INFO
:
575 case RAW_FILEINFO_BASIC_INFORMATION
:
576 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 40));
578 push_nttime(blob
->data
, 0, st
->basic_info
.out
.create_time
);
579 push_nttime(blob
->data
, 8, st
->basic_info
.out
.access_time
);
580 push_nttime(blob
->data
, 16, st
->basic_info
.out
.write_time
);
581 push_nttime(blob
->data
, 24, st
->basic_info
.out
.change_time
);
582 SIVAL(blob
->data
, 32, st
->basic_info
.out
.attrib
);
583 SIVAL(blob
->data
, 36, 0); /* padding */
586 case RAW_FILEINFO_STANDARD
:
587 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 22));
589 srv_push_dos_date2(req
->smb_conn
, blob
->data
, 0, st
->standard
.out
.create_time
);
590 srv_push_dos_date2(req
->smb_conn
, blob
->data
, 4, st
->standard
.out
.access_time
);
591 srv_push_dos_date2(req
->smb_conn
, blob
->data
, 8, st
->standard
.out
.write_time
);
592 SIVAL(blob
->data
, 12, st
->standard
.out
.size
);
593 SIVAL(blob
->data
, 16, st
->standard
.out
.alloc_size
);
594 SSVAL(blob
->data
, 20, st
->standard
.out
.attrib
);
597 case RAW_FILEINFO_EA_SIZE
:
598 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 26));
600 srv_push_dos_date2(req
->smb_conn
, blob
->data
, 0, st
->ea_size
.out
.create_time
);
601 srv_push_dos_date2(req
->smb_conn
, blob
->data
, 4, st
->ea_size
.out
.access_time
);
602 srv_push_dos_date2(req
->smb_conn
, blob
->data
, 8, st
->ea_size
.out
.write_time
);
603 SIVAL(blob
->data
, 12, st
->ea_size
.out
.size
);
604 SIVAL(blob
->data
, 16, st
->ea_size
.out
.alloc_size
);
605 SSVAL(blob
->data
, 20, st
->ea_size
.out
.attrib
);
606 SIVAL(blob
->data
, 22, st
->ea_size
.out
.ea_size
);
609 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION
:
610 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 56));
612 push_nttime(blob
->data
, 0, st
->network_open_information
.out
.create_time
);
613 push_nttime(blob
->data
, 8, st
->network_open_information
.out
.access_time
);
614 push_nttime(blob
->data
, 16, st
->network_open_information
.out
.write_time
);
615 push_nttime(blob
->data
, 24, st
->network_open_information
.out
.change_time
);
616 SBVAL(blob
->data
, 32, st
->network_open_information
.out
.alloc_size
);
617 SBVAL(blob
->data
, 40, st
->network_open_information
.out
.size
);
618 SIVAL(blob
->data
, 48, st
->network_open_information
.out
.attrib
);
619 SIVAL(blob
->data
, 52, 0); /* padding */
622 case RAW_FILEINFO_STANDARD_INFO
:
623 case RAW_FILEINFO_STANDARD_INFORMATION
:
624 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 24));
626 SBVAL(blob
->data
, 0, st
->standard_info
.out
.alloc_size
);
627 SBVAL(blob
->data
, 8, st
->standard_info
.out
.size
);
628 SIVAL(blob
->data
, 16, st
->standard_info
.out
.nlink
);
629 SCVAL(blob
->data
, 20, st
->standard_info
.out
.delete_pending
);
630 SCVAL(blob
->data
, 21, st
->standard_info
.out
.directory
);
631 SSVAL(blob
->data
, 22, 0); /* padding */
634 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION
:
635 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 8));
637 SIVAL(blob
->data
, 0, st
->attribute_tag_information
.out
.attrib
);
638 SIVAL(blob
->data
, 4, st
->attribute_tag_information
.out
.reparse_tag
);
641 case RAW_FILEINFO_EA_INFO
:
642 case RAW_FILEINFO_EA_INFORMATION
:
643 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 4));
645 SIVAL(blob
->data
, 0, st
->ea_info
.out
.ea_size
);
648 case RAW_FILEINFO_MODE_INFORMATION
:
649 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 4));
651 SIVAL(blob
->data
, 0, st
->mode_information
.out
.mode
);
654 case RAW_FILEINFO_ALIGNMENT_INFORMATION
:
655 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 4));
658 st
->alignment_information
.out
.alignment_requirement
);
661 case RAW_FILEINFO_EA_LIST
:
662 list_size
= ea_list_size(st
->ea_list
.out
.num_eas
,
663 st
->ea_list
.out
.eas
);
664 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, list_size
));
666 ea_put_list(blob
->data
,
667 st
->ea_list
.out
.num_eas
, st
->ea_list
.out
.eas
);
670 case RAW_FILEINFO_ALL_EAS
:
671 list_size
= ea_list_size(st
->all_eas
.out
.num_eas
,
672 st
->all_eas
.out
.eas
);
673 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, list_size
));
675 ea_put_list(blob
->data
,
676 st
->all_eas
.out
.num_eas
, st
->all_eas
.out
.eas
);
679 case RAW_FILEINFO_ACCESS_INFORMATION
:
680 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 4));
682 SIVAL(blob
->data
, 0, st
->access_information
.out
.access_flags
);
685 case RAW_FILEINFO_POSITION_INFORMATION
:
686 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 8));
688 SBVAL(blob
->data
, 0, st
->position_information
.out
.position
);
691 case RAW_FILEINFO_COMPRESSION_INFO
:
692 case RAW_FILEINFO_COMPRESSION_INFORMATION
:
693 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 16));
695 SBVAL(blob
->data
, 0, st
->compression_info
.out
.compressed_size
);
696 SSVAL(blob
->data
, 8, st
->compression_info
.out
.format
);
697 SCVAL(blob
->data
, 10, st
->compression_info
.out
.unit_shift
);
698 SCVAL(blob
->data
, 11, st
->compression_info
.out
.chunk_shift
);
699 SCVAL(blob
->data
, 12, st
->compression_info
.out
.cluster_shift
);
700 SSVAL(blob
->data
, 13, 0); /* 3 bytes padding */
701 SCVAL(blob
->data
, 15, 0);
704 case RAW_FILEINFO_IS_NAME_VALID
:
707 case RAW_FILEINFO_INTERNAL_INFORMATION
:
708 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 8));
710 SBVAL(blob
->data
, 0, st
->internal_information
.out
.file_id
);
713 case RAW_FILEINFO_ALL_INFO
:
714 case RAW_FILEINFO_ALL_INFORMATION
:
715 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 72));
717 push_nttime(blob
->data
, 0, st
->all_info
.out
.create_time
);
718 push_nttime(blob
->data
, 8, st
->all_info
.out
.access_time
);
719 push_nttime(blob
->data
, 16, st
->all_info
.out
.write_time
);
720 push_nttime(blob
->data
, 24, st
->all_info
.out
.change_time
);
721 SIVAL(blob
->data
, 32, st
->all_info
.out
.attrib
);
722 SIVAL(blob
->data
, 36, 0);
723 SBVAL(blob
->data
, 40, st
->all_info
.out
.alloc_size
);
724 SBVAL(blob
->data
, 48, st
->all_info
.out
.size
);
725 SIVAL(blob
->data
, 56, st
->all_info
.out
.nlink
);
726 SCVAL(blob
->data
, 60, st
->all_info
.out
.delete_pending
);
727 SCVAL(blob
->data
, 61, st
->all_info
.out
.directory
);
728 SSVAL(blob
->data
, 62, 0); /* padding */
729 SIVAL(blob
->data
, 64, st
->all_info
.out
.ea_size
);
730 TRANS2_CHECK(trans2_append_data_string(req
, mem_ctx
, blob
,
731 &st
->all_info
.out
.fname
,
735 case RAW_FILEINFO_NAME_INFO
:
736 case RAW_FILEINFO_NAME_INFORMATION
:
737 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 4));
739 TRANS2_CHECK(trans2_append_data_string(req
, mem_ctx
, blob
,
740 &st
->name_info
.out
.fname
,
744 case RAW_FILEINFO_ALT_NAME_INFO
:
745 case RAW_FILEINFO_ALT_NAME_INFORMATION
:
746 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, 4));
748 TRANS2_CHECK(trans2_append_data_string(req
, mem_ctx
, blob
,
749 &st
->alt_name_info
.out
.fname
,
753 case RAW_FILEINFO_STREAM_INFO
:
754 case RAW_FILEINFO_STREAM_INFORMATION
:
755 for (i
=0;i
<st
->stream_info
.out
.num_streams
;i
++) {
756 uint32_t data_size
= blob
->length
;
759 TRANS2_CHECK(trans2_grow_data(mem_ctx
, blob
, data_size
+ 24));
760 data
= blob
->data
+ data_size
;
761 SBVAL(data
, 8, st
->stream_info
.out
.streams
[i
].size
);
762 SBVAL(data
, 16, st
->stream_info
.out
.streams
[i
].alloc_size
);
763 TRANS2_CHECK(trans2_append_data_string(req
, mem_ctx
, blob
,
764 &st
->stream_info
.out
.streams
[i
].stream_name
,
765 data_size
+ 4, STR_UNICODE
));
766 if (i
== st
->stream_info
.out
.num_streams
- 1) {
767 SIVAL(blob
->data
, data_size
, 0);
769 TRANS2_CHECK(trans2_grow_data_fill(mem_ctx
, blob
, (blob
->length
+7)&~7));
770 SIVAL(blob
->data
, data_size
,
771 blob
->length
- data_size
);
776 case RAW_FILEINFO_UNIX_BASIC
:
777 case RAW_FILEINFO_UNIX_LINK
:
778 return NT_STATUS_INVALID_LEVEL
;
780 case RAW_FILEINFO_SMB2_ALL_EAS
:
781 case RAW_FILEINFO_SMB2_ALL_INFORMATION
:
782 return NT_STATUS_INVALID_LEVEL
;
785 return NT_STATUS_INVALID_LEVEL
;
789 fill in the reply from a qpathinfo or qfileinfo call
791 static NTSTATUS
trans2_fileinfo_send(struct trans_op
*op
)
793 struct smbsrv_request
*req
= op
->req
;
794 struct smb_trans2
*trans
= op
->trans
;
795 union smb_fileinfo
*st
;
797 TRANS2_CHECK_ASYNC_STATUS(st
, union smb_fileinfo
);
799 TRANS2_CHECK(trans2_setup_reply(trans
, 2, 0, 0));
800 SSVAL(trans
->out
.params
.data
, 0, 0);
802 TRANS2_CHECK(trans2_push_fileinfo(req
, st
, trans
, &trans
->out
.data
));
808 trans2 qpathinfo implementation
810 static NTSTATUS
trans2_qpathinfo(struct smbsrv_request
*req
, struct trans_op
*op
)
812 struct smb_trans2
*trans
= op
->trans
;
813 union smb_fileinfo
*st
;
817 /* make sure we got enough parameters */
818 if (trans
->in
.params
.length
< 2) {
819 return NT_STATUS_FOOBAR
;
822 st
= talloc(op
, union smb_fileinfo
);
823 NT_STATUS_HAVE_NO_MEMORY(st
);
825 level
= SVAL(trans
->in
.params
.data
, 0);
827 trans2_pull_blob_string(req
, &trans
->in
.params
, 6, &st
->generic
.in
.file
.path
, 0);
828 if (st
->generic
.in
.file
.path
== NULL
) {
829 return NT_STATUS_FOOBAR
;
832 /* work out the backend level - we make it 1-1 in the header */
833 st
->generic
.level
= (enum smb_fileinfo_level
)level
;
834 if (st
->generic
.level
>= RAW_FILEINFO_GENERIC
) {
835 return NT_STATUS_INVALID_LEVEL
;
838 if (st
->generic
.level
== RAW_FILEINFO_EA_LIST
) {
839 status
= ea_pull_name_list(&trans
->in
.data
, req
,
840 &st
->ea_list
.in
.num_names
,
841 &st
->ea_list
.in
.ea_names
);
842 NT_STATUS_NOT_OK_RETURN(status
);
846 op
->send_fn
= trans2_fileinfo_send
;
848 return ntvfs_qpathinfo(req
->ntvfs
, st
);
853 trans2 qpathinfo implementation
855 static NTSTATUS
trans2_qfileinfo(struct smbsrv_request
*req
, struct trans_op
*op
)
857 struct smb_trans2
*trans
= op
->trans
;
858 union smb_fileinfo
*st
;
861 struct ntvfs_handle
*h
;
863 /* make sure we got enough parameters */
864 if (trans
->in
.params
.length
< 4) {
865 return NT_STATUS_FOOBAR
;
868 st
= talloc(op
, union smb_fileinfo
);
869 NT_STATUS_HAVE_NO_MEMORY(st
);
871 h
= smbsrv_pull_fnum(req
, trans
->in
.params
.data
, 0);
872 level
= SVAL(trans
->in
.params
.data
, 2);
874 st
->generic
.in
.file
.ntvfs
= h
;
875 /* work out the backend level - we make it 1-1 in the header */
876 st
->generic
.level
= (enum smb_fileinfo_level
)level
;
877 if (st
->generic
.level
>= RAW_FILEINFO_GENERIC
) {
878 return NT_STATUS_INVALID_LEVEL
;
881 if (st
->generic
.level
== RAW_FILEINFO_EA_LIST
) {
882 status
= ea_pull_name_list(&trans
->in
.data
, req
,
883 &st
->ea_list
.in
.num_names
,
884 &st
->ea_list
.in
.ea_names
);
885 NT_STATUS_NOT_OK_RETURN(status
);
889 op
->send_fn
= trans2_fileinfo_send
;
891 SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st
->generic
.in
.file
.ntvfs
);
892 return ntvfs_qfileinfo(req
->ntvfs
, st
);
897 parse a trans2 setfileinfo/setpathinfo data blob
899 static NTSTATUS
trans2_parse_sfileinfo(struct smbsrv_request
*req
,
900 union smb_setfileinfo
*st
,
901 const DATA_BLOB
*blob
)
905 switch (st
->generic
.level
) {
906 case RAW_SFILEINFO_GENERIC
:
907 case RAW_SFILEINFO_SETATTR
:
908 case RAW_SFILEINFO_SETATTRE
:
909 case RAW_SFILEINFO_SEC_DESC
:
910 /* handled elsewhere */
911 return NT_STATUS_INVALID_LEVEL
;
913 case RAW_SFILEINFO_STANDARD
:
914 CHECK_MIN_BLOB_SIZE(blob
, 12);
915 st
->standard
.in
.create_time
= srv_pull_dos_date2(req
->smb_conn
, blob
->data
+ 0);
916 st
->standard
.in
.access_time
= srv_pull_dos_date2(req
->smb_conn
, blob
->data
+ 4);
917 st
->standard
.in
.write_time
= srv_pull_dos_date2(req
->smb_conn
, blob
->data
+ 8);
920 case RAW_SFILEINFO_EA_SET
:
921 return ea_pull_list(blob
, req
,
922 &st
->ea_set
.in
.num_eas
,
925 case SMB_SFILEINFO_BASIC_INFO
:
926 case SMB_SFILEINFO_BASIC_INFORMATION
:
927 CHECK_MIN_BLOB_SIZE(blob
, 36);
928 st
->basic_info
.in
.create_time
= pull_nttime(blob
->data
, 0);
929 st
->basic_info
.in
.access_time
= pull_nttime(blob
->data
, 8);
930 st
->basic_info
.in
.write_time
= pull_nttime(blob
->data
, 16);
931 st
->basic_info
.in
.change_time
= pull_nttime(blob
->data
, 24);
932 st
->basic_info
.in
.attrib
= IVAL(blob
->data
, 32);
935 case SMB_SFILEINFO_DISPOSITION_INFO
:
936 case SMB_SFILEINFO_DISPOSITION_INFORMATION
:
937 CHECK_MIN_BLOB_SIZE(blob
, 1);
938 st
->disposition_info
.in
.delete_on_close
= CVAL(blob
->data
, 0);
941 case SMB_SFILEINFO_ALLOCATION_INFO
:
942 case SMB_SFILEINFO_ALLOCATION_INFORMATION
:
943 CHECK_MIN_BLOB_SIZE(blob
, 8);
944 st
->allocation_info
.in
.alloc_size
= BVAL(blob
->data
, 0);
947 case RAW_SFILEINFO_END_OF_FILE_INFO
:
948 case RAW_SFILEINFO_END_OF_FILE_INFORMATION
:
949 CHECK_MIN_BLOB_SIZE(blob
, 8);
950 st
->end_of_file_info
.in
.size
= BVAL(blob
->data
, 0);
953 case RAW_SFILEINFO_RENAME_INFORMATION
: {
956 CHECK_MIN_BLOB_SIZE(blob
, 12);
957 st
->rename_information
.in
.overwrite
= CVAL(blob
->data
, 0);
958 st
->rename_information
.in
.root_fid
= IVAL(blob
->data
, 4);
959 len
= IVAL(blob
->data
, 8);
960 blob2
.data
= blob
->data
+12;
961 blob2
.length
= MIN(blob
->length
, len
);
962 trans2_pull_blob_string(req
, &blob2
, 0,
963 &st
->rename_information
.in
.new_name
, STR_UNICODE
);
967 case RAW_SFILEINFO_POSITION_INFORMATION
:
968 CHECK_MIN_BLOB_SIZE(blob
, 8);
969 st
->position_information
.in
.position
= BVAL(blob
->data
, 0);
972 case RAW_SFILEINFO_MODE_INFORMATION
:
973 CHECK_MIN_BLOB_SIZE(blob
, 4);
974 st
->mode_information
.in
.mode
= IVAL(blob
->data
, 0);
977 case RAW_SFILEINFO_UNIX_BASIC
:
978 case RAW_SFILEINFO_UNIX_LINK
:
979 case RAW_SFILEINFO_UNIX_HLINK
:
980 case RAW_SFILEINFO_1023
:
981 case RAW_SFILEINFO_1025
:
982 case RAW_SFILEINFO_1029
:
983 case RAW_SFILEINFO_1032
:
984 case RAW_SFILEINFO_1039
:
985 case RAW_SFILEINFO_1040
:
986 return NT_STATUS_INVALID_LEVEL
;
989 return NT_STATUS_INVALID_LEVEL
;
993 trans2 setfileinfo implementation
995 static NTSTATUS
trans2_setfileinfo(struct smbsrv_request
*req
, struct trans_op
*op
)
997 struct smb_trans2
*trans
= op
->trans
;
998 union smb_setfileinfo
*st
;
1001 struct ntvfs_handle
*h
;
1003 /* make sure we got enough parameters */
1004 if (trans
->in
.params
.length
< 4) {
1005 return NT_STATUS_FOOBAR
;
1008 st
= talloc(op
, union smb_setfileinfo
);
1009 NT_STATUS_HAVE_NO_MEMORY(st
);
1011 h
= smbsrv_pull_fnum(req
, trans
->in
.params
.data
, 0);
1012 level
= SVAL(trans
->in
.params
.data
, 2);
1014 st
->generic
.in
.file
.ntvfs
= h
;
1015 /* work out the backend level - we make it 1-1 in the header */
1016 st
->generic
.level
= (enum smb_setfileinfo_level
)level
;
1017 if (st
->generic
.level
>= RAW_SFILEINFO_GENERIC
) {
1018 return NT_STATUS_INVALID_LEVEL
;
1021 status
= trans2_parse_sfileinfo(req
, st
, &trans
->in
.data
);
1022 NT_STATUS_NOT_OK_RETURN(status
);
1025 op
->send_fn
= trans2_simple_send
;
1027 SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(st
->generic
.in
.file
.ntvfs
);
1028 return ntvfs_setfileinfo(req
->ntvfs
, st
);
1032 trans2 setpathinfo implementation
1034 static NTSTATUS
trans2_setpathinfo(struct smbsrv_request
*req
, struct trans_op
*op
)
1036 struct smb_trans2
*trans
= op
->trans
;
1037 union smb_setfileinfo
*st
;
1041 /* make sure we got enough parameters */
1042 if (trans
->in
.params
.length
< 4) {
1043 return NT_STATUS_FOOBAR
;
1046 st
= talloc(op
, union smb_setfileinfo
);
1047 NT_STATUS_HAVE_NO_MEMORY(st
);
1049 level
= SVAL(trans
->in
.params
.data
, 0);
1051 trans2_pull_blob_string(req
, &trans
->in
.params
, 6, &st
->generic
.in
.file
.path
, 0);
1052 if (st
->generic
.in
.file
.path
== NULL
) {
1053 return NT_STATUS_FOOBAR
;
1056 /* work out the backend level - we make it 1-1 in the header */
1057 st
->generic
.level
= (enum smb_setfileinfo_level
)level
;
1058 if (st
->generic
.level
>= RAW_SFILEINFO_GENERIC
) {
1059 return NT_STATUS_INVALID_LEVEL
;
1062 status
= trans2_parse_sfileinfo(req
, st
, &trans
->in
.data
);
1063 NT_STATUS_NOT_OK_RETURN(status
);
1066 op
->send_fn
= trans2_simple_send
;
1068 return ntvfs_setpathinfo(req
->ntvfs
, st
);
1072 /* a structure to encapsulate the state information about an in-progress ffirst/fnext operation */
1074 struct trans_op
*op
;
1076 enum smb_search_level level
;
1077 uint16_t last_entry_offset
;
1082 fill a single entry in a trans2 find reply
1084 static BOOL
find_fill_info(struct find_state
*state
,
1085 union smb_search_data
*file
)
1087 struct smbsrv_request
*req
= state
->op
->req
;
1088 struct smb_trans2
*trans
= state
->op
->trans
;
1090 uint_t ofs
= trans
->out
.data
.length
;
1093 switch (state
->level
) {
1094 case RAW_SEARCH_SEARCH
:
1095 case RAW_SEARCH_FFIRST
:
1096 case RAW_SEARCH_FUNIQUE
:
1097 case RAW_SEARCH_GENERIC
:
1098 case RAW_SEARCH_SMB2
:
1099 /* handled elsewhere */
1102 case RAW_SEARCH_STANDARD
:
1103 if (state
->flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
) {
1104 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 27);
1105 SIVAL(trans
->out
.data
.data
, ofs
, file
->standard
.resume_key
);
1108 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 23);
1110 data
= trans
->out
.data
.data
+ ofs
;
1111 srv_push_dos_date2(req
->smb_conn
, data
, 0, file
->standard
.create_time
);
1112 srv_push_dos_date2(req
->smb_conn
, data
, 4, file
->standard
.access_time
);
1113 srv_push_dos_date2(req
->smb_conn
, data
, 8, file
->standard
.write_time
);
1114 SIVAL(data
, 12, file
->standard
.size
);
1115 SIVAL(data
, 16, file
->standard
.alloc_size
);
1116 SSVAL(data
, 20, file
->standard
.attrib
);
1117 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->standard
.name
,
1118 ofs
+ 22, STR_LEN8BIT
| STR_TERMINATE
| STR_LEN_NOTERM
);
1121 case RAW_SEARCH_EA_SIZE
:
1122 if (state
->flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
) {
1123 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 31);
1124 SIVAL(trans
->out
.data
.data
, ofs
, file
->ea_size
.resume_key
);
1127 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 27);
1129 data
= trans
->out
.data
.data
+ ofs
;
1130 srv_push_dos_date2(req
->smb_conn
, data
, 0, file
->ea_size
.create_time
);
1131 srv_push_dos_date2(req
->smb_conn
, data
, 4, file
->ea_size
.access_time
);
1132 srv_push_dos_date2(req
->smb_conn
, data
, 8, file
->ea_size
.write_time
);
1133 SIVAL(data
, 12, file
->ea_size
.size
);
1134 SIVAL(data
, 16, file
->ea_size
.alloc_size
);
1135 SSVAL(data
, 20, file
->ea_size
.attrib
);
1136 SIVAL(data
, 22, file
->ea_size
.ea_size
);
1137 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->ea_size
.name
,
1138 ofs
+ 26, STR_LEN8BIT
| STR_NOALIGN
);
1139 trans2_grow_data(trans
, &trans
->out
.data
, trans
->out
.data
.length
+ 1);
1140 trans
->out
.data
.data
[trans
->out
.data
.length
-1] = 0;
1143 case RAW_SEARCH_EA_LIST
:
1144 ea_size
= ea_list_size(file
->ea_list
.eas
.num_eas
, file
->ea_list
.eas
.eas
);
1145 if (state
->flags
& FLAG_TRANS2_FIND_REQUIRE_RESUME
) {
1146 if (!NT_STATUS_IS_OK(trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 27 + ea_size
))) {
1149 SIVAL(trans
->out
.data
.data
, ofs
, file
->ea_list
.resume_key
);
1152 if (!NT_STATUS_IS_OK(trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 23 + ea_size
))) {
1156 data
= trans
->out
.data
.data
+ ofs
;
1157 srv_push_dos_date2(req
->smb_conn
, data
, 0, file
->ea_list
.create_time
);
1158 srv_push_dos_date2(req
->smb_conn
, data
, 4, file
->ea_list
.access_time
);
1159 srv_push_dos_date2(req
->smb_conn
, data
, 8, file
->ea_list
.write_time
);
1160 SIVAL(data
, 12, file
->ea_list
.size
);
1161 SIVAL(data
, 16, file
->ea_list
.alloc_size
);
1162 SSVAL(data
, 20, file
->ea_list
.attrib
);
1163 ea_put_list(data
+22, file
->ea_list
.eas
.num_eas
, file
->ea_list
.eas
.eas
);
1164 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->ea_list
.name
,
1165 ofs
+ 22 + ea_size
, STR_LEN8BIT
| STR_NOALIGN
);
1166 trans2_grow_data(trans
, &trans
->out
.data
, trans
->out
.data
.length
+ 1);
1167 trans
->out
.data
.data
[trans
->out
.data
.length
-1] = 0;
1170 case RAW_SEARCH_DIRECTORY_INFO
:
1171 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 64);
1172 data
= trans
->out
.data
.data
+ ofs
;
1173 SIVAL(data
, 4, file
->directory_info
.file_index
);
1174 push_nttime(data
, 8, file
->directory_info
.create_time
);
1175 push_nttime(data
, 16, file
->directory_info
.access_time
);
1176 push_nttime(data
, 24, file
->directory_info
.write_time
);
1177 push_nttime(data
, 32, file
->directory_info
.change_time
);
1178 SBVAL(data
, 40, file
->directory_info
.size
);
1179 SBVAL(data
, 48, file
->directory_info
.alloc_size
);
1180 SIVAL(data
, 56, file
->directory_info
.attrib
);
1181 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->directory_info
.name
,
1182 ofs
+ 60, STR_TERMINATE_ASCII
);
1183 data
= trans
->out
.data
.data
+ ofs
;
1184 SIVAL(data
, 0, trans
->out
.data
.length
- ofs
);
1187 case RAW_SEARCH_FULL_DIRECTORY_INFO
:
1188 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 68);
1189 data
= trans
->out
.data
.data
+ ofs
;
1190 SIVAL(data
, 4, file
->full_directory_info
.file_index
);
1191 push_nttime(data
, 8, file
->full_directory_info
.create_time
);
1192 push_nttime(data
, 16, file
->full_directory_info
.access_time
);
1193 push_nttime(data
, 24, file
->full_directory_info
.write_time
);
1194 push_nttime(data
, 32, file
->full_directory_info
.change_time
);
1195 SBVAL(data
, 40, file
->full_directory_info
.size
);
1196 SBVAL(data
, 48, file
->full_directory_info
.alloc_size
);
1197 SIVAL(data
, 56, file
->full_directory_info
.attrib
);
1198 SIVAL(data
, 64, file
->full_directory_info
.ea_size
);
1199 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->full_directory_info
.name
,
1200 ofs
+ 60, STR_TERMINATE_ASCII
);
1201 data
= trans
->out
.data
.data
+ ofs
;
1202 SIVAL(data
, 0, trans
->out
.data
.length
- ofs
);
1205 case RAW_SEARCH_NAME_INFO
:
1206 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 12);
1207 data
= trans
->out
.data
.data
+ ofs
;
1208 SIVAL(data
, 4, file
->name_info
.file_index
);
1209 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->name_info
.name
,
1210 ofs
+ 8, STR_TERMINATE_ASCII
);
1211 data
= trans
->out
.data
.data
+ ofs
;
1212 SIVAL(data
, 0, trans
->out
.data
.length
- ofs
);
1215 case RAW_SEARCH_BOTH_DIRECTORY_INFO
:
1216 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 94);
1217 data
= trans
->out
.data
.data
+ ofs
;
1218 SIVAL(data
, 4, file
->both_directory_info
.file_index
);
1219 push_nttime(data
, 8, file
->both_directory_info
.create_time
);
1220 push_nttime(data
, 16, file
->both_directory_info
.access_time
);
1221 push_nttime(data
, 24, file
->both_directory_info
.write_time
);
1222 push_nttime(data
, 32, file
->both_directory_info
.change_time
);
1223 SBVAL(data
, 40, file
->both_directory_info
.size
);
1224 SBVAL(data
, 48, file
->both_directory_info
.alloc_size
);
1225 SIVAL(data
, 56, file
->both_directory_info
.attrib
);
1226 SIVAL(data
, 64, file
->both_directory_info
.ea_size
);
1227 SCVAL(data
, 69, 0); /* reserved */
1228 memset(data
+70,0,24);
1229 trans2_push_data_string(req
, trans
, &trans
->out
.data
,
1231 &file
->both_directory_info
.short_name
,
1232 24, STR_UNICODE
| STR_LEN8BIT
);
1233 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->both_directory_info
.name
,
1234 ofs
+ 60, STR_TERMINATE_ASCII
);
1235 trans2_align_data(trans
);
1236 data
= trans
->out
.data
.data
+ ofs
;
1237 SIVAL(data
, 0, trans
->out
.data
.length
- ofs
);
1240 case RAW_SEARCH_ID_FULL_DIRECTORY_INFO
:
1241 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 80);
1242 data
= trans
->out
.data
.data
+ ofs
;
1243 SIVAL(data
, 4, file
->id_full_directory_info
.file_index
);
1244 push_nttime(data
, 8, file
->id_full_directory_info
.create_time
);
1245 push_nttime(data
, 16, file
->id_full_directory_info
.access_time
);
1246 push_nttime(data
, 24, file
->id_full_directory_info
.write_time
);
1247 push_nttime(data
, 32, file
->id_full_directory_info
.change_time
);
1248 SBVAL(data
, 40, file
->id_full_directory_info
.size
);
1249 SBVAL(data
, 48, file
->id_full_directory_info
.alloc_size
);
1250 SIVAL(data
, 56, file
->id_full_directory_info
.attrib
);
1251 SIVAL(data
, 64, file
->id_full_directory_info
.ea_size
);
1252 SIVAL(data
, 68, 0); /* padding */
1253 SBVAL(data
, 72, file
->id_full_directory_info
.file_id
);
1254 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->id_full_directory_info
.name
,
1255 ofs
+ 60, STR_TERMINATE_ASCII
);
1256 data
= trans
->out
.data
.data
+ ofs
;
1257 SIVAL(data
, 0, trans
->out
.data
.length
- ofs
);
1260 case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO
:
1261 trans2_grow_data(trans
, &trans
->out
.data
, ofs
+ 104);
1262 data
= trans
->out
.data
.data
+ ofs
;
1263 SIVAL(data
, 4, file
->id_both_directory_info
.file_index
);
1264 push_nttime(data
, 8, file
->id_both_directory_info
.create_time
);
1265 push_nttime(data
, 16, file
->id_both_directory_info
.access_time
);
1266 push_nttime(data
, 24, file
->id_both_directory_info
.write_time
);
1267 push_nttime(data
, 32, file
->id_both_directory_info
.change_time
);
1268 SBVAL(data
, 40, file
->id_both_directory_info
.size
);
1269 SBVAL(data
, 48, file
->id_both_directory_info
.alloc_size
);
1270 SIVAL(data
, 56, file
->id_both_directory_info
.attrib
);
1271 SIVAL(data
, 64, file
->id_both_directory_info
.ea_size
);
1272 SCVAL(data
, 69, 0); /* reserved */
1273 memset(data
+70,0,26);
1274 trans2_push_data_string(req
, trans
, &trans
->out
.data
,
1276 &file
->id_both_directory_info
.short_name
,
1277 24, STR_UNICODE
| STR_LEN8BIT
);
1278 SBVAL(data
, 96, file
->id_both_directory_info
.file_id
);
1279 trans2_append_data_string(req
, trans
, &trans
->out
.data
, &file
->id_both_directory_info
.name
,
1280 ofs
+ 60, STR_TERMINATE_ASCII
);
1281 data
= trans
->out
.data
.data
+ ofs
;
1282 SIVAL(data
, 0, trans
->out
.data
.length
- ofs
);
1289 /* callback function for trans2 findfirst/findnext */
1290 static BOOL
find_callback(void *private, union smb_search_data
*file
)
1292 struct find_state
*state
= talloc_get_type(private, struct find_state
);
1293 struct smb_trans2
*trans
= state
->op
->trans
;
1296 old_length
= trans
->out
.data
.length
;
1298 if (!find_fill_info(state
, file
) ||
1299 trans
->out
.data
.length
> trans
->in
.max_data
) {
1300 /* restore the old length and tell the backend to stop */
1301 trans2_grow_data(trans
, &trans
->out
.data
, old_length
);
1305 state
->last_entry_offset
= old_length
;
1310 trans2 findfirst send
1312 static NTSTATUS
trans2_findfirst_send(struct trans_op
*op
)
1314 struct smbsrv_request
*req
= op
->req
;
1315 struct smb_trans2
*trans
= op
->trans
;
1316 union smb_search_first
*search
;
1317 struct find_state
*state
;
1320 TRANS2_CHECK_ASYNC_STATUS(state
, struct find_state
);
1321 search
= talloc_get_type(state
->search
, union smb_search_first
);
1323 /* fill in the findfirst reply header */
1324 param
= trans
->out
.params
.data
;
1325 SSVAL(param
, VWV(0), search
->t2ffirst
.out
.handle
);
1326 SSVAL(param
, VWV(1), search
->t2ffirst
.out
.count
);
1327 SSVAL(param
, VWV(2), search
->t2ffirst
.out
.end_of_search
);
1328 SSVAL(param
, VWV(3), 0);
1329 SSVAL(param
, VWV(4), state
->last_entry_offset
);
1331 return NT_STATUS_OK
;
1336 trans2 findfirst implementation
1338 static NTSTATUS
trans2_findfirst(struct smbsrv_request
*req
, struct trans_op
*op
)
1340 struct smb_trans2
*trans
= op
->trans
;
1341 union smb_search_first
*search
;
1344 struct find_state
*state
;
1346 /* make sure we got all the parameters */
1347 if (trans
->in
.params
.length
< 14) {
1348 return NT_STATUS_FOOBAR
;
1351 search
= talloc(op
, union smb_search_first
);
1352 NT_STATUS_HAVE_NO_MEMORY(search
);
1354 search
->t2ffirst
.in
.search_attrib
= SVAL(trans
->in
.params
.data
, 0);
1355 search
->t2ffirst
.in
.max_count
= SVAL(trans
->in
.params
.data
, 2);
1356 search
->t2ffirst
.in
.flags
= SVAL(trans
->in
.params
.data
, 4);
1357 level
= SVAL(trans
->in
.params
.data
, 6);
1358 search
->t2ffirst
.in
.storage_type
= IVAL(trans
->in
.params
.data
, 8);
1360 trans2_pull_blob_string(req
, &trans
->in
.params
, 12, &search
->t2ffirst
.in
.pattern
, 0);
1361 if (search
->t2ffirst
.in
.pattern
== NULL
) {
1362 return NT_STATUS_FOOBAR
;
1365 search
->t2ffirst
.level
= (enum smb_search_level
)level
;
1366 if (search
->t2ffirst
.level
>= RAW_SEARCH_GENERIC
) {
1367 return NT_STATUS_INVALID_LEVEL
;
1370 if (search
->t2ffirst
.level
== RAW_SEARCH_EA_LIST
) {
1371 status
= ea_pull_name_list(&trans
->in
.data
, req
,
1372 &search
->t2ffirst
.in
.num_names
,
1373 &search
->t2ffirst
.in
.ea_names
);
1374 NT_STATUS_NOT_OK_RETURN(status
);
1377 /* setup the private state structure that the backend will
1378 give us in the callback */
1379 state
= talloc(op
, struct find_state
);
1380 NT_STATUS_HAVE_NO_MEMORY(state
);
1382 state
->search
= search
;
1383 state
->level
= search
->t2ffirst
.level
;
1384 state
->last_entry_offset
= 0;
1385 state
->flags
= search
->t2ffirst
.in
.flags
;
1387 /* setup for just a header in the reply */
1388 trans2_setup_reply(trans
, 10, 0, 0);
1390 op
->op_info
= state
;
1391 op
->send_fn
= trans2_findfirst_send
;
1393 return ntvfs_search_first(req
->ntvfs
, search
, state
, find_callback
);
1398 trans2 findnext send
1400 static NTSTATUS
trans2_findnext_send(struct trans_op
*op
)
1402 struct smbsrv_request
*req
= op
->req
;
1403 struct smb_trans2
*trans
= op
->trans
;
1404 union smb_search_next
*search
;
1405 struct find_state
*state
;
1408 TRANS2_CHECK_ASYNC_STATUS(state
, struct find_state
);
1409 search
= talloc_get_type(state
->search
, union smb_search_next
);
1411 /* fill in the findfirst reply header */
1412 param
= trans
->out
.params
.data
;
1413 SSVAL(param
, VWV(0), search
->t2fnext
.out
.count
);
1414 SSVAL(param
, VWV(1), search
->t2fnext
.out
.end_of_search
);
1415 SSVAL(param
, VWV(2), 0);
1416 SSVAL(param
, VWV(3), state
->last_entry_offset
);
1418 return NT_STATUS_OK
;
1423 trans2 findnext implementation
1425 static NTSTATUS
trans2_findnext(struct smbsrv_request
*req
, struct trans_op
*op
)
1427 struct smb_trans2
*trans
= op
->trans
;
1428 union smb_search_next
*search
;
1431 struct find_state
*state
;
1433 /* make sure we got all the parameters */
1434 if (trans
->in
.params
.length
< 12) {
1435 return NT_STATUS_FOOBAR
;
1438 search
= talloc(op
, union smb_search_next
);
1439 NT_STATUS_HAVE_NO_MEMORY(search
);
1441 search
->t2fnext
.in
.handle
= SVAL(trans
->in
.params
.data
, 0);
1442 search
->t2fnext
.in
.max_count
= SVAL(trans
->in
.params
.data
, 2);
1443 level
= SVAL(trans
->in
.params
.data
, 4);
1444 search
->t2fnext
.in
.resume_key
= IVAL(trans
->in
.params
.data
, 6);
1445 search
->t2fnext
.in
.flags
= SVAL(trans
->in
.params
.data
, 10);
1447 trans2_pull_blob_string(req
, &trans
->in
.params
, 12, &search
->t2fnext
.in
.last_name
, 0);
1448 if (search
->t2fnext
.in
.last_name
== NULL
) {
1449 return NT_STATUS_FOOBAR
;
1452 search
->t2fnext
.level
= (enum smb_search_level
)level
;
1453 if (search
->t2fnext
.level
>= RAW_SEARCH_GENERIC
) {
1454 return NT_STATUS_INVALID_LEVEL
;
1457 if (search
->t2fnext
.level
== RAW_SEARCH_EA_LIST
) {
1458 status
= ea_pull_name_list(&trans
->in
.data
, req
,
1459 &search
->t2fnext
.in
.num_names
,
1460 &search
->t2fnext
.in
.ea_names
);
1461 NT_STATUS_NOT_OK_RETURN(status
);
1464 /* setup the private state structure that the backend will give us in the callback */
1465 state
= talloc(op
, struct find_state
);
1466 NT_STATUS_HAVE_NO_MEMORY(state
);
1468 state
->search
= search
;
1469 state
->level
= search
->t2fnext
.level
;
1470 state
->last_entry_offset
= 0;
1471 state
->flags
= search
->t2fnext
.in
.flags
;
1473 /* setup for just a header in the reply */
1474 trans2_setup_reply(trans
, 8, 0, 0);
1476 op
->op_info
= state
;
1477 op
->send_fn
= trans2_findnext_send
;
1479 return ntvfs_search_next(req
->ntvfs
, search
, state
, find_callback
);
1484 backend for trans2 requests
1486 static NTSTATUS
trans2_backend(struct smbsrv_request
*req
, struct trans_op
*op
)
1488 struct smb_trans2
*trans
= op
->trans
;
1491 /* direct trans2 pass thru */
1492 status
= ntvfs_trans2(req
->ntvfs
, trans
);
1493 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED
, status
)) {
1497 /* must have at least one setup word */
1498 if (trans
->in
.setup_count
< 1) {
1499 return NT_STATUS_FOOBAR
;
1502 /* the trans2 command is in setup[0] */
1503 switch (trans
->in
.setup
[0]) {
1504 case TRANSACT2_FINDFIRST
:
1505 return trans2_findfirst(req
, op
);
1506 case TRANSACT2_FINDNEXT
:
1507 return trans2_findnext(req
, op
);
1508 case TRANSACT2_QPATHINFO
:
1509 return trans2_qpathinfo(req
, op
);
1510 case TRANSACT2_QFILEINFO
:
1511 return trans2_qfileinfo(req
, op
);
1512 case TRANSACT2_SETFILEINFO
:
1513 return trans2_setfileinfo(req
, op
);
1514 case TRANSACT2_SETPATHINFO
:
1515 return trans2_setpathinfo(req
, op
);
1516 case TRANSACT2_QFSINFO
:
1517 return trans2_qfsinfo(req
, op
);
1518 case TRANSACT2_OPEN
:
1519 return trans2_open(req
, op
);
1520 case TRANSACT2_MKDIR
:
1521 return trans2_mkdir(req
, op
);
1524 /* an unknown trans2 command */
1525 return NT_STATUS_FOOBAR
;
1530 send a continue request
1532 static void reply_trans_continue(struct smbsrv_request
*req
, uint8_t command
,
1533 struct smb_trans2
*trans
)
1535 struct smbsrv_trans_partial
*tp
;
1538 /* make sure they don't flood us */
1539 for (count
=0,tp
=req
->smb_conn
->trans_partial
;tp
;tp
=tp
->next
) count
++;
1541 smbsrv_send_error(req
, NT_STATUS_INSUFFICIENT_RESOURCES
);
1545 tp
= talloc(req
, struct smbsrv_trans_partial
);
1547 tp
->req
= talloc_reference(tp
, req
);
1549 tp
->command
= command
;
1551 DLIST_ADD(req
->smb_conn
->trans_partial
, tp
);
1553 /* send a 'please continue' reply */
1554 smbsrv_setup_reply(req
, 0, 0);
1555 smbsrv_send_reply(req
);
1560 answer a reconstructed trans request
1562 static void reply_trans_send(struct ntvfs_request
*ntvfs
)
1564 struct smbsrv_request
*req
;
1565 struct trans_op
*op
;
1566 struct smb_trans2
*trans
;
1567 uint16_t params_left
, data_left
;
1568 uint8_t *params
, *data
;
1571 SMBSRV_CHECK_ASYNC_STATUS_ERR(op
, struct trans_op
);
1574 /* if this function needs work to form the nttrans reply buffer, then
1576 if (op
->send_fn
!= NULL
) {
1578 status
= op
->send_fn(op
);
1579 if (!NT_STATUS_IS_OK(status
)) {
1580 smbsrv_send_error(req
, status
);
1585 params_left
= trans
->out
.params
.length
;
1586 data_left
= trans
->out
.data
.length
;
1587 params
= trans
->out
.params
.data
;
1588 data
= trans
->out
.data
.data
;
1590 smbsrv_setup_reply(req
, 10 + trans
->out
.setup_count
, 0);
1592 if (!NT_STATUS_IS_OK(req
->ntvfs
->async_states
->status
)) {
1593 smbsrv_setup_error(req
, req
->ntvfs
->async_states
->status
);
1596 /* we need to divide up the reply into chunks that fit into
1597 the negotiated buffer size */
1599 uint16_t this_data
, this_param
, max_bytes
;
1600 uint_t align1
= 1, align2
= (params_left
? 2 : 0);
1601 struct smbsrv_request
*this_req
;
1603 max_bytes
= req_max_data(req
) - (align1
+ align2
);
1605 this_param
= params_left
;
1606 if (this_param
> max_bytes
) {
1607 this_param
= max_bytes
;
1609 max_bytes
-= this_param
;
1611 this_data
= data_left
;
1612 if (this_data
> max_bytes
) {
1613 this_data
= max_bytes
;
1616 /* don't destroy unless this is the last chunk */
1617 if (params_left
- this_param
!= 0 ||
1618 data_left
- this_data
!= 0) {
1619 this_req
= smbsrv_setup_secondary_request(req
);
1624 req_grow_data(this_req
, this_param
+ this_data
+ (align1
+ align2
));
1626 SSVAL(this_req
->out
.vwv
, VWV(0), trans
->out
.params
.length
);
1627 SSVAL(this_req
->out
.vwv
, VWV(1), trans
->out
.data
.length
);
1628 SSVAL(this_req
->out
.vwv
, VWV(2), 0);
1630 SSVAL(this_req
->out
.vwv
, VWV(3), this_param
);
1631 SSVAL(this_req
->out
.vwv
, VWV(4), align1
+ PTR_DIFF(this_req
->out
.data
, this_req
->out
.hdr
));
1632 SSVAL(this_req
->out
.vwv
, VWV(5), PTR_DIFF(params
, trans
->out
.params
.data
));
1634 SSVAL(this_req
->out
.vwv
, VWV(6), this_data
);
1635 SSVAL(this_req
->out
.vwv
, VWV(7), align1
+ align2
+
1636 PTR_DIFF(this_req
->out
.data
+ this_param
, this_req
->out
.hdr
));
1637 SSVAL(this_req
->out
.vwv
, VWV(8), PTR_DIFF(data
, trans
->out
.data
.data
));
1639 SSVAL(this_req
->out
.vwv
, VWV(9), trans
->out
.setup_count
);
1640 for (i
=0;i
<trans
->out
.setup_count
;i
++) {
1641 SSVAL(this_req
->out
.vwv
, VWV(10+i
), trans
->out
.setup
[i
]);
1644 memset(this_req
->out
.data
, 0, align1
);
1645 if (this_param
!= 0) {
1646 memcpy(this_req
->out
.data
+ align1
, params
, this_param
);
1648 memset(this_req
->out
.data
+this_param
+align1
, 0, align2
);
1649 if (this_data
!= 0) {
1650 memcpy(this_req
->out
.data
+this_param
+align1
+align2
, data
, this_data
);
1653 params_left
-= this_param
;
1654 data_left
-= this_data
;
1655 params
+= this_param
;
1658 smbsrv_send_reply(this_req
);
1659 } while (params_left
!= 0 || data_left
!= 0);
1664 answer a reconstructed trans request
1666 static void reply_trans_complete(struct smbsrv_request
*req
, uint8_t command
,
1667 struct smb_trans2
*trans
)
1669 struct trans_op
*op
;
1671 SMBSRV_TALLOC_IO_PTR(op
, struct trans_op
);
1672 SMBSRV_SETUP_NTVFS_REQUEST(reply_trans_send
, NTVFS_ASYNC_STATE_MAY_ASYNC
);
1676 op
->command
= command
;
1680 /* its a full request, give it to the backend */
1681 if (command
== SMBtrans
) {
1682 SMBSRV_CALL_NTVFS_BACKEND(ntvfs_trans(req
->ntvfs
, trans
));
1685 SMBSRV_CALL_NTVFS_BACKEND(trans2_backend(req
, op
));
1691 Reply to an SMBtrans or SMBtrans2 request
1693 static void reply_trans_generic(struct smbsrv_request
*req
, uint8_t command
)
1695 struct smb_trans2
*trans
;
1697 uint16_t param_ofs
, data_ofs
;
1698 uint16_t param_count
, data_count
;
1699 uint16_t param_total
, data_total
;
1702 if (req
->in
.wct
< 14) {
1703 smbsrv_send_error(req
, NT_STATUS_INVALID_PARAMETER
);
1707 trans
= talloc(req
, struct smb_trans2
);
1708 if (trans
== NULL
) {
1709 smbsrv_send_error(req
, NT_STATUS_NO_MEMORY
);
1713 param_total
= SVAL(req
->in
.vwv
, VWV(0));
1714 data_total
= SVAL(req
->in
.vwv
, VWV(1));
1715 trans
->in
.max_param
= SVAL(req
->in
.vwv
, VWV(2));
1716 trans
->in
.max_data
= SVAL(req
->in
.vwv
, VWV(3));
1717 trans
->in
.max_setup
= CVAL(req
->in
.vwv
, VWV(4));
1718 trans
->in
.flags
= SVAL(req
->in
.vwv
, VWV(5));
1719 trans
->in
.timeout
= IVAL(req
->in
.vwv
, VWV(6));
1720 param_count
= SVAL(req
->in
.vwv
, VWV(9));
1721 param_ofs
= SVAL(req
->in
.vwv
, VWV(10));
1722 data_count
= SVAL(req
->in
.vwv
, VWV(11));
1723 data_ofs
= SVAL(req
->in
.vwv
, VWV(12));
1724 trans
->in
.setup_count
= CVAL(req
->in
.vwv
, VWV(13));
1726 if (req
->in
.wct
!= 14 + trans
->in
.setup_count
) {
1727 smbsrv_send_error(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
1731 /* parse out the setup words */
1732 trans
->in
.setup
= talloc_array(trans
, uint16_t, trans
->in
.setup_count
);
1733 if (trans
->in
.setup_count
&& !trans
->in
.setup
) {
1734 smbsrv_send_error(req
, NT_STATUS_NO_MEMORY
);
1737 for (i
=0;i
<trans
->in
.setup_count
;i
++) {
1738 trans
->in
.setup
[i
] = SVAL(req
->in
.vwv
, VWV(14+i
));
1741 if (command
== SMBtrans
) {
1742 req_pull_string(req
, &trans
->in
.trans_name
, req
->in
.data
, -1, STR_TERMINATE
);
1745 if (!req_pull_blob(req
, req
->in
.hdr
+ param_ofs
, param_count
, &trans
->in
.params
) ||
1746 !req_pull_blob(req
, req
->in
.hdr
+ data_ofs
, data_count
, &trans
->in
.data
)) {
1747 smbsrv_send_error(req
, NT_STATUS_FOOBAR
);
1751 /* is it a partial request? if so, then send a 'send more' message */
1752 if (param_total
> param_count
|| data_total
> data_count
) {
1753 reply_trans_continue(req
, command
, trans
);
1757 reply_trans_complete(req
, command
, trans
);
1762 Reply to an SMBtranss2 request
1764 static void reply_transs_generic(struct smbsrv_request
*req
, uint8_t command
)
1766 struct smbsrv_trans_partial
*tp
;
1767 struct smb_trans2
*trans
= NULL
;
1768 uint16_t param_ofs
, data_ofs
;
1769 uint16_t param_count
, data_count
;
1770 uint16_t param_disp
, data_disp
;
1771 uint16_t param_total
, data_total
;
1772 DATA_BLOB params
, data
;
1775 if (req
->in
.wct
< 8) {
1776 smbsrv_send_error(req
, NT_STATUS_INVALID_PARAMETER
);
1780 for (tp
=req
->smb_conn
->trans_partial
;tp
;tp
=tp
->next
) {
1781 if (tp
->command
== command
&&
1782 SVAL(tp
->req
->in
.hdr
, HDR_MID
) == SVAL(req
->in
.hdr
, HDR_MID
)) {
1783 /* TODO: check the VUID, PID and TID too? */
1789 smbsrv_send_error(req
, NT_STATUS_INVALID_PARAMETER
);
1795 param_total
= SVAL(req
->in
.vwv
, VWV(0));
1796 data_total
= SVAL(req
->in
.vwv
, VWV(1));
1797 param_count
= SVAL(req
->in
.vwv
, VWV(2));
1798 param_ofs
= SVAL(req
->in
.vwv
, VWV(3));
1799 param_disp
= SVAL(req
->in
.vwv
, VWV(4));
1800 data_count
= SVAL(req
->in
.vwv
, VWV(5));
1801 data_ofs
= SVAL(req
->in
.vwv
, VWV(6));
1802 data_disp
= SVAL(req
->in
.vwv
, VWV(7));
1804 if (!req_pull_blob(req
, req
->in
.hdr
+ param_ofs
, param_count
, ¶ms
) ||
1805 !req_pull_blob(req
, req
->in
.hdr
+ data_ofs
, data_count
, &data
)) {
1806 smbsrv_send_error(req
, NT_STATUS_INVALID_PARAMETER
);
1810 /* only allow contiguous requests */
1811 if ((param_count
!= 0 &&
1812 param_disp
!= trans
->in
.params
.length
) ||
1814 data_disp
!= trans
->in
.data
.length
)) {
1815 smbsrv_send_error(req
, NT_STATUS_INVALID_PARAMETER
);
1819 /* add to the existing request */
1820 if (param_count
!= 0) {
1821 trans
->in
.params
.data
= talloc_realloc(trans
,
1822 trans
->in
.params
.data
,
1824 param_disp
+ param_count
);
1825 if (trans
->in
.params
.data
== NULL
) {
1828 trans
->in
.params
.length
= param_disp
+ param_count
;
1831 if (data_count
!= 0) {
1832 trans
->in
.data
.data
= talloc_realloc(trans
,
1833 trans
->in
.data
.data
,
1835 data_disp
+ data_count
);
1836 if (trans
->in
.data
.data
== NULL
) {
1839 trans
->in
.data
.length
= data_disp
+ data_count
;
1842 memcpy(trans
->in
.params
.data
+ param_disp
, params
.data
, params
.length
);
1843 memcpy(trans
->in
.data
.data
+ data_disp
, data
.data
, data
.length
);
1845 /* the sequence number of the reply is taken from the last secondary
1847 tp
->req
->seq_num
= req
->seq_num
;
1849 /* we don't reply to Transs2 requests */
1852 if (trans
->in
.params
.length
== param_total
&&
1853 trans
->in
.data
.length
== data_total
) {
1854 /* its now complete */
1855 DLIST_REMOVE(tp
->req
->smb_conn
->trans_partial
, tp
);
1856 reply_trans_complete(tp
->req
, command
, trans
);
1861 smbsrv_send_error(tp
->req
, NT_STATUS_NO_MEMORY
);
1862 DLIST_REMOVE(req
->smb_conn
->trans_partial
, tp
);
1869 Reply to an SMBtrans2
1871 void smbsrv_reply_trans2(struct smbsrv_request
*req
)
1873 reply_trans_generic(req
, SMBtrans2
);
1877 Reply to an SMBtrans
1879 void smbsrv_reply_trans(struct smbsrv_request
*req
)
1881 reply_trans_generic(req
, SMBtrans
);
1885 Reply to an SMBtranss request
1887 void smbsrv_reply_transs(struct smbsrv_request
*req
)
1889 reply_transs_generic(req
, SMBtrans
);
1893 Reply to an SMBtranss2 request
1895 void smbsrv_reply_transs2(struct smbsrv_request
*req
)
1897 reply_transs_generic(req
, SMBtrans2
);