summaryrefslogtreecommitdiff
path: root/source4/smb_server
diff options
context:
space:
mode:
Diffstat (limited to 'source4/smb_server')
-rw-r--r--source4/smb_server/smb/trans2.c942
1 files changed, 534 insertions, 408 deletions
diff --git a/source4/smb_server/smb/trans2.c b/source4/smb_server/smb/trans2.c
index faf204607e..e350d6d9e3 100644
--- a/source4/smb_server/smb/trans2.c
+++ b/source4/smb_server/smb/trans2.c
@@ -28,6 +28,18 @@
#include "ntvfs/ntvfs.h"
#include "libcli/raw/libcliraw.h"
+/*
+ hold the state of a nttrans op while in progress. Needed to allow for async backend
+ functions.
+*/
+struct trans_op {
+ struct smbsrv_request *req;
+ struct smb_trans2 *trans;
+ uint8_t command;
+ NTSTATUS (*send_fn)(struct trans_op *);
+ void *op_info;
+};
+
#define CHECK_MIN_BLOB_SIZE(blob, size) do { \
if ((blob)->length < (size)) { \
return NT_STATUS_INFO_LENGTH_MISMATCH; \
@@ -36,25 +48,23 @@
/* grow the data allocation size of a trans2 reply - this guarantees
that requests to grow the data size later will not change the
pointer */
-static BOOL trans2_grow_data_allocation(struct smbsrv_request *req,
- struct smb_trans2 *trans,
+static BOOL trans2_grow_data_allocation(struct smb_trans2 *trans,
uint32_t new_size)
{
if (new_size <= trans->out.data.length) {
return True;
}
- trans->out.data.data = talloc_realloc(req, trans->out.data.data,
+ trans->out.data.data = talloc_realloc(trans, trans->out.data.data,
uint8_t, new_size);
return (trans->out.data.data != NULL);
}
/* grow the data size of a trans2 reply */
-static BOOL trans2_grow_data(struct smbsrv_request *req,
- struct smb_trans2 *trans,
+static BOOL trans2_grow_data(struct smb_trans2 *trans,
uint32_t new_size)
{
- if (!trans2_grow_data_allocation(req, trans, new_size)) {
+ if (!trans2_grow_data_allocation(trans, new_size)) {
return False;
}
trans->out.data.length = new_size;
@@ -62,12 +72,11 @@ static BOOL trans2_grow_data(struct smbsrv_request *req,
}
/* grow the data, zero filling any new bytes */
-static BOOL trans2_grow_data_fill(struct smbsrv_request *req,
- struct smb_trans2 *trans,
+static BOOL trans2_grow_data_fill(struct smb_trans2 *trans,
uint32_t new_size)
{
uint32_t old_size = trans->out.data.length;
- if (!trans2_grow_data(req, trans, new_size)) {
+ if (!trans2_grow_data(trans, new_size)) {
return False;
}
if (new_size > old_size) {
@@ -78,17 +87,16 @@ static BOOL trans2_grow_data_fill(struct smbsrv_request *req,
/* setup a trans2 reply, given the data and params sizes */
-static void trans2_setup_reply(struct smbsrv_request *req,
- struct smb_trans2 *trans,
+static void trans2_setup_reply(struct smb_trans2 *trans,
uint16_t param_size, uint16_t data_size,
uint16_t setup_count)
{
trans->out.setup_count = setup_count;
if (setup_count != 0) {
- trans->out.setup = talloc_zero_array(req, uint16_t, setup_count);
+ trans->out.setup = talloc_zero_array(trans, uint16_t, setup_count);
}
- trans->out.params = data_blob_talloc(req, NULL, param_size);
- trans->out.data = data_blob_talloc(req, NULL, data_size);
+ trans->out.params = data_blob_talloc(trans, NULL, param_size);
+ trans->out.data = data_blob_talloc(trans, NULL, data_size);
}
@@ -199,9 +207,9 @@ static void trans2_append_data_string(struct smbsrv_request *req,
const int max_bytes_per_char = 3;
offset = trans->out.data.length;
- trans2_grow_data(req, trans, offset + (2+strlen_m(str->s))*max_bytes_per_char);
+ trans2_grow_data(trans, offset + (2+strlen_m(str->s))*max_bytes_per_char);
ret = trans2_push_data_string(req, trans, len_offset, offset, str, -1, flags);
- trans2_grow_data(req, trans, offset + ret);
+ trans2_grow_data(trans, offset + ret);
}
/*
@@ -212,191 +220,129 @@ static void trans2_align_data(struct smbsrv_request *req, struct smb_trans2 *tra
if ((trans->out.data.length & 1) == 0) {
return;
}
- trans2_grow_data(req, trans, trans->out.data.length+1);
+ trans2_grow_data(trans, trans->out.data.length+1);
SCVAL(trans->out.data.data, trans->out.data.length-1, 0);
}
/*
- trans2 qfsinfo implementation
+ trans2 qfsinfo implementation send
*/
-static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_qfsinfo_send(struct trans_op *op)
{
- union smb_fsinfo fsinfo;
+ struct smbsrv_request *req = op->req;
+ struct smb_trans2 *trans = op->trans;
+ union smb_fsinfo *fsinfo;
NTSTATUS status;
- uint16_t level;
uint_t i;
DATA_BLOB guid_blob;
- /* make sure we got enough parameters */
- if (trans->in.params.length != 2) {
- return NT_STATUS_FOOBAR;
+ if (!NT_STATUS_IS_OK(req->async_states->status)) {
+ return req->async_states->status;
}
- level = SVAL(trans->in.params.data, 0);
+ fsinfo = talloc_get_type(op->op_info, union smb_fsinfo);
- switch (level) {
+ switch (fsinfo->generic.level) {
case SMB_QFS_ALLOCATION:
- fsinfo.allocation.level = RAW_QFS_ALLOCATION;
-
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 18, 0);
+ trans2_setup_reply(trans, 0, 18, 0);
- SIVAL(trans->out.data.data, 0, fsinfo.allocation.out.fs_id);
- SIVAL(trans->out.data.data, 4, fsinfo.allocation.out.sectors_per_unit);
- SIVAL(trans->out.data.data, 8, fsinfo.allocation.out.total_alloc_units);
- SIVAL(trans->out.data.data, 12, fsinfo.allocation.out.avail_alloc_units);
- SSVAL(trans->out.data.data, 16, fsinfo.allocation.out.bytes_per_sector);
+ SIVAL(trans->out.data.data, 0, fsinfo->allocation.out.fs_id);
+ SIVAL(trans->out.data.data, 4, fsinfo->allocation.out.sectors_per_unit);
+ SIVAL(trans->out.data.data, 8, fsinfo->allocation.out.total_alloc_units);
+ SIVAL(trans->out.data.data, 12, fsinfo->allocation.out.avail_alloc_units);
+ SSVAL(trans->out.data.data, 16, fsinfo->allocation.out.bytes_per_sector);
return NT_STATUS_OK;
case SMB_QFS_VOLUME:
- fsinfo.volume.level = RAW_QFS_VOLUME;
+ trans2_setup_reply(trans, 0, 5, 0);
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 5, 0);
-
- SIVAL(trans->out.data.data, 0, fsinfo.volume.out.serial_number);
+ SIVAL(trans->out.data.data, 0, fsinfo->volume.out.serial_number);
/* w2k3 implements this incorrectly for unicode - it
* leaves the last byte off the string */
trans2_append_data_string(req, trans,
- &fsinfo.volume.out.volume_name,
+ &fsinfo->volume.out.volume_name,
4, STR_LEN8BIT|STR_NOALIGN);
return NT_STATUS_OK;
case SMB_QFS_VOLUME_INFO:
case SMB_QFS_VOLUME_INFORMATION:
- fsinfo.volume_info.level = RAW_QFS_VOLUME_INFO;
-
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 18, 0);
+ trans2_setup_reply(trans, 0, 18, 0);
- push_nttime(trans->out.data.data, 0, fsinfo.volume_info.out.create_time);
- SIVAL(trans->out.data.data, 8, fsinfo.volume_info.out.serial_number);
+ push_nttime(trans->out.data.data, 0, fsinfo->volume_info.out.create_time);
+ SIVAL(trans->out.data.data, 8, fsinfo->volume_info.out.serial_number);
SSVAL(trans->out.data.data, 16, 0); /* padding */
trans2_append_data_string(req, trans,
- &fsinfo.volume_info.out.volume_name,
+ &fsinfo->volume_info.out.volume_name,
12, STR_UNICODE);
return NT_STATUS_OK;
case SMB_QFS_SIZE_INFO:
case SMB_QFS_SIZE_INFORMATION:
- fsinfo.size_info.level = RAW_QFS_SIZE_INFO;
+ trans2_setup_reply(trans, 0, 24, 0);
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 24, 0);
-
- SBVAL(trans->out.data.data, 0, fsinfo.size_info.out.total_alloc_units);
- SBVAL(trans->out.data.data, 8, fsinfo.size_info.out.avail_alloc_units);
- SIVAL(trans->out.data.data, 16, fsinfo.size_info.out.sectors_per_unit);
- SIVAL(trans->out.data.data, 20, fsinfo.size_info.out.bytes_per_sector);
+ SBVAL(trans->out.data.data, 0, fsinfo->size_info.out.total_alloc_units);
+ SBVAL(trans->out.data.data, 8, fsinfo->size_info.out.avail_alloc_units);
+ SIVAL(trans->out.data.data, 16, fsinfo->size_info.out.sectors_per_unit);
+ SIVAL(trans->out.data.data, 20, fsinfo->size_info.out.bytes_per_sector);
return NT_STATUS_OK;
case SMB_QFS_DEVICE_INFO:
case SMB_QFS_DEVICE_INFORMATION:
- fsinfo.device_info.level = RAW_QFS_DEVICE_INFO;
-
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- trans2_setup_reply(req, trans, 0, 8, 0);
- SIVAL(trans->out.data.data, 0, fsinfo.device_info.out.device_type);
- SIVAL(trans->out.data.data, 4, fsinfo.device_info.out.characteristics);
+ trans2_setup_reply(trans, 0, 8, 0);
+ SIVAL(trans->out.data.data, 0, fsinfo->device_info.out.device_type);
+ SIVAL(trans->out.data.data, 4, fsinfo->device_info.out.characteristics);
return NT_STATUS_OK;
case SMB_QFS_ATTRIBUTE_INFO:
case SMB_QFS_ATTRIBUTE_INFORMATION:
- fsinfo.attribute_info.level = RAW_QFS_ATTRIBUTE_INFO;
+ trans2_setup_reply(trans, 0, 12, 0);
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 12, 0);
-
- SIVAL(trans->out.data.data, 0, fsinfo.attribute_info.out.fs_attr);
- SIVAL(trans->out.data.data, 4, fsinfo.attribute_info.out.max_file_component_length);
+ SIVAL(trans->out.data.data, 0, fsinfo->attribute_info.out.fs_attr);
+ SIVAL(trans->out.data.data, 4, fsinfo->attribute_info.out.max_file_component_length);
/* this must not be null terminated or win98 gets
confused! also note that w2k3 returns this as
unicode even when ascii is negotiated */
trans2_append_data_string(req, trans,
- &fsinfo.attribute_info.out.fs_type,
+ &fsinfo->attribute_info.out.fs_type,
8, STR_UNICODE);
return NT_STATUS_OK;
case SMB_QFS_QUOTA_INFORMATION:
- fsinfo.quota_information.level = RAW_QFS_QUOTA_INFORMATION;
-
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 48, 0);
+ trans2_setup_reply(trans, 0, 48, 0);
- SBVAL(trans->out.data.data, 0, fsinfo.quota_information.out.unknown[0]);
- SBVAL(trans->out.data.data, 8, fsinfo.quota_information.out.unknown[1]);
- SBVAL(trans->out.data.data, 16, fsinfo.quota_information.out.unknown[2]);
- SBVAL(trans->out.data.data, 24, fsinfo.quota_information.out.quota_soft);
- SBVAL(trans->out.data.data, 32, fsinfo.quota_information.out.quota_hard);
- SBVAL(trans->out.data.data, 40, fsinfo.quota_information.out.quota_flags);
+ SBVAL(trans->out.data.data, 0, fsinfo->quota_information.out.unknown[0]);
+ SBVAL(trans->out.data.data, 8, fsinfo->quota_information.out.unknown[1]);
+ SBVAL(trans->out.data.data, 16, fsinfo->quota_information.out.unknown[2]);
+ SBVAL(trans->out.data.data, 24, fsinfo->quota_information.out.quota_soft);
+ SBVAL(trans->out.data.data, 32, fsinfo->quota_information.out.quota_hard);
+ SBVAL(trans->out.data.data, 40, fsinfo->quota_information.out.quota_flags);
return NT_STATUS_OK;
case SMB_QFS_FULL_SIZE_INFORMATION:
- fsinfo.full_size_information.level = RAW_QFS_FULL_SIZE_INFORMATION;
+ trans2_setup_reply(trans, 0, 32, 0);
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 32, 0);
-
- SBVAL(trans->out.data.data, 0, fsinfo.full_size_information.out.total_alloc_units);
- SBVAL(trans->out.data.data, 8, fsinfo.full_size_information.out.call_avail_alloc_units);
- SBVAL(trans->out.data.data, 16, fsinfo.full_size_information.out.actual_avail_alloc_units);
- SIVAL(trans->out.data.data, 24, fsinfo.full_size_information.out.sectors_per_unit);
- SIVAL(trans->out.data.data, 28, fsinfo.full_size_information.out.bytes_per_sector);
+ SBVAL(trans->out.data.data, 0, fsinfo->full_size_information.out.total_alloc_units);
+ SBVAL(trans->out.data.data, 8, fsinfo->full_size_information.out.call_avail_alloc_units);
+ SBVAL(trans->out.data.data, 16, fsinfo->full_size_information.out.actual_avail_alloc_units);
+ SIVAL(trans->out.data.data, 24, fsinfo->full_size_information.out.sectors_per_unit);
+ SIVAL(trans->out.data.data, 28, fsinfo->full_size_information.out.bytes_per_sector);
return NT_STATUS_OK;
case SMB_QFS_OBJECTID_INFORMATION:
- fsinfo.objectid_information.level = RAW_QFS_OBJECTID_INFORMATION;
-
- status = ntvfs_fsinfo(req, &fsinfo);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 0, 64, 0);
+ trans2_setup_reply(trans, 0, 64, 0);
status = ndr_push_struct_blob(&guid_blob, req,
- &fsinfo.objectid_information.out.guid,
+ &fsinfo->objectid_information.out.guid,
(ndr_push_flags_fn_t)ndr_push_GUID);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -405,7 +351,7 @@ static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct smb_trans2 *tr
memcpy(trans->out.data.data, guid_blob.data, guid_blob.length);
for (i=0;i<6;i++) {
- SBVAL(trans->out.data.data, 16 + 8*i, fsinfo.objectid_information.out.unknown[i]);
+ SBVAL(trans->out.data.data, 16 + 8*i, fsinfo->objectid_information.out.unknown[i]);
}
return NT_STATUS_OK;
}
@@ -413,12 +359,113 @@ static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct smb_trans2 *tr
return NT_STATUS_INVALID_LEVEL;
}
+/*
+ trans2 qfsinfo implementation
+*/
+static NTSTATUS trans2_qfsinfo(struct smbsrv_request *req, struct trans_op *op)
+{
+ struct smb_trans2 *trans = op->trans;
+ union smb_fsinfo *fsinfo;
+ uint16_t level;
+
+ /* make sure we got enough parameters */
+ if (trans->in.params.length != 2) {
+ return NT_STATUS_FOOBAR;
+ }
+
+ fsinfo = talloc(op, union smb_fsinfo);
+ NT_STATUS_HAVE_NO_MEMORY(fsinfo);
+
+ op->op_info = fsinfo;
+ op->send_fn = trans2_qfsinfo_send;
+
+ level = SVAL(trans->in.params.data, 0);
+
+ switch (level) {
+ case SMB_QFS_ALLOCATION:
+ fsinfo->allocation.level = RAW_QFS_ALLOCATION;
+ return ntvfs_fsinfo(req, fsinfo);
+
+ case SMB_QFS_VOLUME:
+ fsinfo->volume.level = RAW_QFS_VOLUME;
+ return ntvfs_fsinfo(req, fsinfo);
+
+ case SMB_QFS_VOLUME_INFO:
+ case SMB_QFS_VOLUME_INFORMATION:
+ fsinfo->volume_info.level = RAW_QFS_VOLUME_INFO;
+ return ntvfs_fsinfo(req, fsinfo);
+
+ case SMB_QFS_SIZE_INFO:
+ case SMB_QFS_SIZE_INFORMATION:
+ fsinfo->size_info.level = RAW_QFS_SIZE_INFO;
+ return ntvfs_fsinfo(req, fsinfo);
+
+ case SMB_QFS_DEVICE_INFO:
+ case SMB_QFS_DEVICE_INFORMATION:
+ fsinfo->device_info.level = RAW_QFS_DEVICE_INFO;
+ return ntvfs_fsinfo(req, fsinfo);
+
+ case SMB_QFS_ATTRIBUTE_INFO:
+ case SMB_QFS_ATTRIBUTE_INFORMATION:
+ fsinfo->attribute_info.level = RAW_QFS_ATTRIBUTE_INFO;
+ return ntvfs_fsinfo(req, fsinfo);
+
+ case SMB_QFS_QUOTA_INFORMATION:
+ fsinfo->quota_information.level = RAW_QFS_QUOTA_INFORMATION;
+ return ntvfs_fsinfo(req, fsinfo);
+
+ case SMB_QFS_FULL_SIZE_INFORMATION:
+ fsinfo->full_size_information.level = RAW_QFS_FULL_SIZE_INFORMATION;
+ return ntvfs_fsinfo(req, fsinfo);
+
+ case SMB_QFS_OBJECTID_INFORMATION:
+ fsinfo->objectid_information.level = RAW_QFS_OBJECTID_INFORMATION;
+ return ntvfs_fsinfo(req, fsinfo);
+ }
+
+ return NT_STATUS_INVALID_LEVEL;
+}
+
+
+/*
+ trans2 open implementation send
+*/
+static NTSTATUS trans2_open_send(struct trans_op *op)
+{
+ struct smbsrv_request *req = op->req;
+ struct smb_trans2 *trans = op->trans;
+ union smb_open *io;
+
+ if (!NT_STATUS_IS_OK(req->async_states->status)) {
+ return req->async_states->status;
+ }
+
+ io = talloc_get_type(op->op_info, union smb_open);
+
+ trans2_setup_reply(trans, 30, 0, 0);
+
+ SSVAL(trans->out.params.data, VWV(0), io->t2open.out.file.fnum);
+ SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib);
+ srv_push_dos_date3(req->smb_conn, trans->out.params.data,
+ VWV(2), io->t2open.out.write_time);
+ SIVAL(trans->out.params.data, VWV(4), io->t2open.out.size);
+ SSVAL(trans->out.params.data, VWV(6), io->t2open.out.access);
+ SSVAL(trans->out.params.data, VWV(7), io->t2open.out.ftype);
+ SSVAL(trans->out.params.data, VWV(8), io->t2open.out.devstate);
+ SSVAL(trans->out.params.data, VWV(9), io->t2open.out.action);
+ SIVAL(trans->out.params.data, VWV(10), 0); /* reserved */
+ SSVAL(trans->out.params.data, VWV(12), 0); /* EaErrorOffset */
+ SIVAL(trans->out.params.data, VWV(13), 0); /* EaLength */
+
+ return NT_STATUS_OK;
+}
/*
trans2 open implementation
*/
-static NTSTATUS trans2_open(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_open(struct smbsrv_request *req, struct trans_op *op)
{
+ struct smb_trans2 *trans = op->trans;
union smb_open *io;
NTSTATUS status;
@@ -427,10 +474,8 @@ static NTSTATUS trans2_open(struct smbsrv_request *req, struct smb_trans2 *trans
return NT_STATUS_FOOBAR;
}
- io = talloc(req, union smb_open);
- if (io == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ io = talloc(op, union smb_open);
+ NT_STATUS_HAVE_NO_MEMORY(io);
io->t2open.level = RAW_OPEN_T2OPEN;
io->t2open.in.flags = SVAL(trans->in.params.data, VWV(0));
@@ -448,39 +493,40 @@ static NTSTATUS trans2_open(struct smbsrv_request *req, struct smb_trans2 *trans
trans2_pull_blob_string(req, &trans->in.params, 28, &io->t2open.in.fname, 0);
status = ea_pull_list(&trans->in.data, io, &io->t2open.in.num_eas, &io->t2open.in.eas);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ NT_STATUS_NOT_OK_RETURN(status);
- status = ntvfs_open(req, io);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ op->op_info = io;
+ op->send_fn = trans2_open_send;
+
+ return ntvfs_open(req, io);
+}
+
+
+/*
+ trans2 simple send
+*/
+static NTSTATUS trans2_simple_send(struct trans_op *op)
+{
+ struct smbsrv_request *req = op->req;
+ struct smb_trans2 *trans = op->trans;
+
+ if (!NT_STATUS_IS_OK(req->async_states->status)) {
+ return req->async_states->status;
}
- trans2_setup_reply(req, trans, 30, 0, 0);
+ trans2_setup_reply(trans, 2, 0, 0);
- SSVAL(trans->out.params.data, VWV(0), io->t2open.out.file.fnum);
- SSVAL(trans->out.params.data, VWV(1), io->t2open.out.attrib);
- srv_push_dos_date3(req->smb_conn, trans->out.params.data,
- VWV(2), io->t2open.out.write_time);
- SIVAL(trans->out.params.data, VWV(4), io->t2open.out.size);
- SSVAL(trans->out.params.data, VWV(6), io->t2open.out.access);
- SSVAL(trans->out.params.data, VWV(7), io->t2open.out.ftype);
- SSVAL(trans->out.params.data, VWV(8), io->t2open.out.devstate);
- SSVAL(trans->out.params.data, VWV(9), io->t2open.out.action);
- SIVAL(trans->out.params.data, VWV(10), 0); /* reserved */
- SSVAL(trans->out.params.data, VWV(12), 0); /* EaErrorOffset */
- SIVAL(trans->out.params.data, VWV(13), 0); /* EaLength */
+ SSVAL(trans->out.params.data, VWV(0), 0);
- return status;
+ return NT_STATUS_OK;
}
-
/*
trans2 mkdir implementation
*/
-static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct trans_op *op)
{
+ struct smb_trans2 *trans = op->trans;
union smb_mkdir *io;
NTSTATUS status;
@@ -489,10 +535,8 @@ static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct smb_trans2 *tran
return NT_STATUS_FOOBAR;
}
- io = talloc(req, union smb_mkdir);
- if (io == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
+ io = talloc(op, union smb_mkdir);
+ NT_STATUS_HAVE_NO_MEMORY(io);
io->t2mkdir.level = RAW_MKDIR_T2MKDIR;
trans2_pull_blob_string(req, &trans->in.params, 4, &io->t2mkdir.in.path, 0);
@@ -500,31 +544,31 @@ static NTSTATUS trans2_mkdir(struct smbsrv_request *req, struct smb_trans2 *tran
status = ea_pull_list(&trans->in.data, io,
&io->t2mkdir.in.num_eas,
&io->t2mkdir.in.eas);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- status = ntvfs_mkdir(req, io);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- trans2_setup_reply(req, trans, 2, 0, 0);
+ NT_STATUS_NOT_OK_RETURN(status);
- SSVAL(trans->out.params.data, VWV(0), 0);
+ op->op_info = io;
+ op->send_fn = trans2_simple_send;
- return status;
+ return ntvfs_mkdir(req, io);
}
/*
fill in the reply from a qpathinfo or qfileinfo call
*/
-static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_trans2 *trans,
- union smb_fileinfo *st)
+static NTSTATUS trans2_fileinfo_send(struct trans_op *op)
{
+ struct smbsrv_request *req = op->req;
+ struct smb_trans2 *trans = op->trans;
+ union smb_fileinfo *st;
uint_t i;
uint32_t list_size;
-
+
+ if (!NT_STATUS_IS_OK(req->async_states->status)) {
+ return req->async_states->status;
+ }
+
+ st = talloc_get_type(op->op_info, union smb_fileinfo);
+
switch (st->generic.level) {
case RAW_FILEINFO_GENERIC:
case RAW_FILEINFO_GETATTR:
@@ -535,7 +579,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
case RAW_FILEINFO_BASIC_INFO:
case RAW_FILEINFO_BASIC_INFORMATION:
- trans2_setup_reply(req, trans, 2, 40, 0);
+ trans2_setup_reply(trans, 2, 40, 0);
SSVAL(trans->out.params.data, 0, 0);
push_nttime(trans->out.data.data, 0, st->basic_info.out.create_time);
@@ -547,7 +591,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
return NT_STATUS_OK;
case RAW_FILEINFO_STANDARD:
- trans2_setup_reply(req, trans, 2, 22, 0);
+ trans2_setup_reply(trans, 2, 22, 0);
SSVAL(trans->out.params.data, 0, 0);
srv_push_dos_date2(req->smb_conn, trans->out.data.data, 0, st->standard.out.create_time);
@@ -559,7 +603,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
return NT_STATUS_OK;
case RAW_FILEINFO_EA_SIZE:
- trans2_setup_reply(req, trans, 2, 26, 0);
+ trans2_setup_reply(trans, 2, 26, 0);
SSVAL(trans->out.params.data, 0, 0);
srv_push_dos_date2(req->smb_conn, trans->out.data.data, 0, st->ea_size.out.create_time);
@@ -572,7 +616,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
return NT_STATUS_OK;
case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
- trans2_setup_reply(req, trans, 2, 56, 0);
+ trans2_setup_reply(trans, 2, 56, 0);
SSVAL(trans->out.params.data, 0, 0);
push_nttime(trans->out.data.data, 0, st->network_open_information.out.create_time);
@@ -587,7 +631,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
case RAW_FILEINFO_STANDARD_INFO:
case RAW_FILEINFO_STANDARD_INFORMATION:
- trans2_setup_reply(req, trans, 2, 24, 0);
+ trans2_setup_reply( trans, 2, 24, 0);
SSVAL(trans->out.params.data, 0, 0);
SBVAL(trans->out.data.data, 0, st->standard_info.out.alloc_size);
SBVAL(trans->out.data.data, 8, st->standard_info.out.size);
@@ -598,7 +642,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
return NT_STATUS_OK;
case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
- trans2_setup_reply(req, trans, 2, 8, 0);
+ trans2_setup_reply(trans, 2, 8, 0);
SSVAL(trans->out.params.data, 0, 0);
SIVAL(trans->out.data.data, 0, st->attribute_tag_information.out.attrib);
SIVAL(trans->out.data.data, 4, st->attribute_tag_information.out.reparse_tag);
@@ -606,19 +650,19 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
case RAW_FILEINFO_EA_INFO:
case RAW_FILEINFO_EA_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
+ trans2_setup_reply(trans, 2, 4, 0);
SSVAL(trans->out.params.data, 0, 0);
SIVAL(trans->out.data.data, 0, st->ea_info.out.ea_size);
return NT_STATUS_OK;
case RAW_FILEINFO_MODE_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
+ trans2_setup_reply(trans, 2, 4, 0);
SSVAL(trans->out.params.data, 0, 0);
SIVAL(trans->out.data.data, 0, st->mode_information.out.mode);
return NT_STATUS_OK;
case RAW_FILEINFO_ALIGNMENT_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
+ trans2_setup_reply(trans, 2, 4, 0);
SSVAL(trans->out.params.data, 0, 0);
SIVAL(trans->out.data.data, 0,
st->alignment_information.out.alignment_requirement);
@@ -627,7 +671,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
case RAW_FILEINFO_EA_LIST:
list_size = ea_list_size(st->ea_list.out.num_eas,
st->ea_list.out.eas);
- trans2_setup_reply(req, trans, 2, list_size, 0);
+ trans2_setup_reply(trans, 2, list_size, 0);
SSVAL(trans->out.params.data, 0, 0);
ea_put_list(trans->out.data.data,
st->ea_list.out.num_eas, st->ea_list.out.eas);
@@ -636,27 +680,27 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
case RAW_FILEINFO_ALL_EAS:
list_size = ea_list_size(st->all_eas.out.num_eas,
st->all_eas.out.eas);
- trans2_setup_reply(req, trans, 2, list_size, 0);
+ trans2_setup_reply(trans, 2, list_size, 0);
SSVAL(trans->out.params.data, 0, 0);
ea_put_list(trans->out.data.data,
st->all_eas.out.num_eas, st->all_eas.out.eas);
return NT_STATUS_OK;
case RAW_FILEINFO_ACCESS_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
+ trans2_setup_reply(trans, 2, 4, 0);
SSVAL(trans->out.params.data, 0, 0);
SIVAL(trans->out.data.data, 0, st->access_information.out.access_flags);
return NT_STATUS_OK;
case RAW_FILEINFO_POSITION_INFORMATION:
- trans2_setup_reply(req, trans, 2, 8, 0);
+ trans2_setup_reply(trans, 2, 8, 0);
SSVAL(trans->out.params.data, 0, 0);
SBVAL(trans->out.data.data, 0, st->position_information.out.position);
return NT_STATUS_OK;
case RAW_FILEINFO_COMPRESSION_INFO:
case RAW_FILEINFO_COMPRESSION_INFORMATION:
- trans2_setup_reply(req, trans, 2, 16, 0);
+ trans2_setup_reply(trans, 2, 16, 0);
SSVAL(trans->out.params.data, 0, 0);
SBVAL(trans->out.data.data, 0, st->compression_info.out.compressed_size);
SSVAL(trans->out.data.data, 8, st->compression_info.out.format);
@@ -668,19 +712,19 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
return NT_STATUS_OK;
case RAW_FILEINFO_IS_NAME_VALID:
- trans2_setup_reply(req, trans, 2, 0, 0);
+ trans2_setup_reply(trans, 2, 0, 0);
SSVAL(trans->out.params.data, 0, 0);
return NT_STATUS_OK;
case RAW_FILEINFO_INTERNAL_INFORMATION:
- trans2_setup_reply(req, trans, 2, 8, 0);
+ trans2_setup_reply(trans, 2, 8, 0);
SSVAL(trans->out.params.data, 0, 0);
SBVAL(trans->out.data.data, 0, st->internal_information.out.file_id);
return NT_STATUS_OK;
case RAW_FILEINFO_ALL_INFO:
case RAW_FILEINFO_ALL_INFORMATION:
- trans2_setup_reply(req, trans, 2, 72, 0);
+ trans2_setup_reply(trans, 2, 72, 0);
SSVAL(trans->out.params.data, 0, 0);
push_nttime(trans->out.data.data, 0, st->all_info.out.create_time);
@@ -702,21 +746,21 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
case RAW_FILEINFO_NAME_INFO:
case RAW_FILEINFO_NAME_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
+ trans2_setup_reply(trans, 2, 4, 0);
SSVAL(trans->out.params.data, 0, 0);
trans2_append_data_string(req, trans, &st->name_info.out.fname, 0, STR_UNICODE);
return NT_STATUS_OK;
case RAW_FILEINFO_ALT_NAME_INFO:
case RAW_FILEINFO_ALT_NAME_INFORMATION:
- trans2_setup_reply(req, trans, 2, 4, 0);
+ trans2_setup_reply(trans, 2, 4, 0);
SSVAL(trans->out.params.data, 0, 0);
trans2_append_data_string(req, trans, &st->alt_name_info.out.fname, 0, STR_UNICODE);
return NT_STATUS_OK;
case RAW_FILEINFO_STREAM_INFO:
case RAW_FILEINFO_STREAM_INFORMATION:
- trans2_setup_reply(req, trans, 2, 0, 0);
+ trans2_setup_reply(trans, 2, 0, 0);
SSVAL(trans->out.params.data, 0, 0);
@@ -724,7 +768,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
uint32_t data_size = trans->out.data.length;
uint8_t *data;
- trans2_grow_data(req, trans, data_size + 24);
+ trans2_grow_data(trans, data_size + 24);
data = trans->out.data.data + data_size;
SBVAL(data, 8, st->stream_info.out.streams[i].size);
SBVAL(data, 16, st->stream_info.out.streams[i].alloc_size);
@@ -734,7 +778,7 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
if (i == st->stream_info.out.num_streams - 1) {
SIVAL(trans->out.data.data, data_size, 0);
} else {
- trans2_grow_data_fill(req, trans, (trans->out.data.length+7)&~7);
+ trans2_grow_data_fill(trans, (trans->out.data.length+7)&~7);
SIVAL(trans->out.data.data, data_size,
trans->out.data.length - data_size);
}
@@ -756,9 +800,10 @@ static NTSTATUS trans2_fileinfo_fill(struct smbsrv_request *req, struct smb_tran
/*
trans2 qpathinfo implementation
*/
-static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct trans_op *op)
{
- union smb_fileinfo st;
+ struct smb_trans2 *trans = op->trans;
+ union smb_fileinfo *st;
NTSTATUS status;
uint16_t level;
@@ -767,83 +812,75 @@ static NTSTATUS trans2_qpathinfo(struct smbsrv_request *req, struct smb_trans2 *
return NT_STATUS_FOOBAR;
}
+ st = talloc(op, union smb_fileinfo);
+ NT_STATUS_HAVE_NO_MEMORY(st);
+
level = SVAL(trans->in.params.data, 0);
- trans2_pull_blob_string(req, &trans->in.params, 6, &st.generic.in.file.path, 0);
- if (st.generic.in.file.path == NULL) {
+ trans2_pull_blob_string(req, &trans->in.params, 6, &st->generic.in.file.path, 0);
+ if (st->generic.in.file.path == NULL) {
return NT_STATUS_FOOBAR;
}
/* work out the backend level - we make it 1-1 in the header */
- st.generic.level = (enum smb_fileinfo_level)level;
- if (st.generic.level >= RAW_FILEINFO_GENERIC) {
+ st->generic.level = (enum smb_fileinfo_level)level;
+ if (st->generic.level >= RAW_FILEINFO_GENERIC) {
return NT_STATUS_INVALID_LEVEL;
}
- if (st.generic.level == RAW_FILEINFO_EA_LIST) {
+ if (st->generic.level == RAW_FILEINFO_EA_LIST) {
status = ea_pull_name_list(&trans->in.data, req,
- &st.ea_list.in.num_names,
- &st.ea_list.in.ea_names);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- }
-
- /* call the backend */
- status = ntvfs_qpathinfo(req, &st);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ &st->ea_list.in.num_names,
+ &st->ea_list.in.ea_names);
+ NT_STATUS_NOT_OK_RETURN(status);
}
- /* fill in the reply parameters */
- status = trans2_fileinfo_fill(req, trans, &st);
+ op->op_info = st;
+ op->send_fn = trans2_fileinfo_send;
- return status;
+ return ntvfs_qpathinfo(req, st);
}
/*
trans2 qpathinfo implementation
*/
-static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_qfileinfo(struct smbsrv_request *req, struct trans_op *op)
{
- union smb_fileinfo st;
+ struct smb_trans2 *trans = op->trans;
+ union smb_fileinfo *st;
NTSTATUS status;
- uint16_t level;
+ uint16_t level, fnum;
/* make sure we got enough parameters */
if (trans->in.params.length < 4) {
return NT_STATUS_FOOBAR;
}
- st.generic.in.file.fnum = SVAL(trans->in.params.data, 0);
+ st = talloc(op, union smb_fileinfo);
+ NT_STATUS_HAVE_NO_MEMORY(st);
+
+ fnum = SVAL(trans->in.params.data, 0);
level = SVAL(trans->in.params.data, 2);
+ st->generic.in.file.fnum = fnum;
/* work out the backend level - we make it 1-1 in the header */
- st.generic.level = (enum smb_fileinfo_level)level;
- if (st.generic.level >= RAW_FILEINFO_GENERIC) {
+ st->generic.level = (enum smb_fileinfo_level)level;
+ if (st->generic.level >= RAW_FILEINFO_GENERIC) {
return NT_STATUS_INVALID_LEVEL;
}
- if (st.generic.level == RAW_FILEINFO_EA_LIST) {
+ if (st->generic.level == RAW_FILEINFO_EA_LIST) {
status = ea_pull_name_list(&trans->in.data, req,
- &st.ea_list.in.num_names,
- &st.ea_list.in.ea_names);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ &st->ea_list.in.num_names,
+ &st->ea_list.in.ea_names);
+ NT_STATUS_NOT_OK_RETURN(status);
}
- /* call the backend */
- status = ntvfs_qfileinfo(req, &st);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ op->op_info = st;
+ op->send_fn = trans2_fileinfo_send;
- /* fill in the reply parameters */
- status = trans2_fileinfo_fill(req, trans, &st);
-
- return status;
+ return ntvfs_qfileinfo(req, st);
}
@@ -946,85 +983,85 @@ static NTSTATUS trans2_parse_sfileinfo(struct smbsrv_request *req,
/*
trans2 setfileinfo implementation
*/
-static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_setfileinfo(struct smbsrv_request *req, struct trans_op *op)
{
- union smb_setfileinfo st;
+ struct smb_trans2 *trans = op->trans;
+ union smb_setfileinfo *st;
NTSTATUS status;
uint16_t level, fnum;
- DATA_BLOB *blob;
/* make sure we got enough parameters */
if (trans->in.params.length < 4) {
return NT_STATUS_FOOBAR;
}
+ st = talloc(op, union smb_setfileinfo);
+ NT_STATUS_HAVE_NO_MEMORY(st);
+
fnum = SVAL(trans->in.params.data, 0);
level = SVAL(trans->in.params.data, 2);
- blob = &trans->in.data;
-
- st.generic.in.file.fnum = fnum;
- st.generic.level = (enum smb_setfileinfo_level)level;
-
- status = trans2_parse_sfileinfo(req, &st, blob);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ st->generic.in.file.fnum = fnum;
+ /* work out the backend level - we make it 1-1 in the header */
+ st->generic.level = (enum smb_setfileinfo_level)level;
+ if (st->generic.level >= RAW_SFILEINFO_GENERIC) {
+ return NT_STATUS_INVALID_LEVEL;
}
- status = ntvfs_setfileinfo(req, &st);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ status = trans2_parse_sfileinfo(req, st, &trans->in.data);
+ NT_STATUS_NOT_OK_RETURN(status);
- trans2_setup_reply(req, trans, 2, 0, 0);
- SSVAL(trans->out.params.data, 0, 0);
- return NT_STATUS_OK;
+ op->op_info = st;
+ op->send_fn = trans2_simple_send;
+
+ return ntvfs_setfileinfo(req, st);
}
/*
trans2 setpathinfo implementation
*/
-static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_setpathinfo(struct smbsrv_request *req, struct trans_op *op)
{
- union smb_setfileinfo st;
+ struct smb_trans2 *trans = op->trans;
+ union smb_setfileinfo *st;
NTSTATUS status;
uint16_t level;
- DATA_BLOB *blob;
/* make sure we got enough parameters */
if (trans->in.params.length < 4) {
return NT_STATUS_FOOBAR;
}
+ st = talloc(op, union smb_setfileinfo);
+ NT_STATUS_HAVE_NO_MEMORY(st);
+
level = SVAL(trans->in.params.data, 0);
- blob = &trans->in.data;
- st.generic.level = (enum smb_setfileinfo_level)level;
- trans2_pull_blob_string(req, &trans->in.params, 6, &st.generic.in.file.path, 0);
- if (st.generic.in.file.path == NULL) {
+ trans2_pull_blob_string(req, &trans->in.params, 6, &st->generic.in.file.path, 0);
+ if (st->generic.in.file.path == NULL) {
return NT_STATUS_FOOBAR;
}
- status = trans2_parse_sfileinfo(req, &st, blob);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ /* work out the backend level - we make it 1-1 in the header */
+ st->generic.level = (enum smb_setfileinfo_level)level;
+ if (st->generic.level >= RAW_SFILEINFO_GENERIC) {
+ return NT_STATUS_INVALID_LEVEL;
}
- status = ntvfs_setpathinfo(req, &st);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ status = trans2_parse_sfileinfo(req, st, &trans->in.data);
+ NT_STATUS_NOT_OK_RETURN(status);
- trans2_setup_reply(req, trans, 2, 0, 0);
- SSVAL(trans->out.params.data, 0, 0);
- return NT_STATUS_OK;
+ op->op_info = st;
+ op->send_fn = trans2_simple_send;
+
+ return ntvfs_setpathinfo(req, st);
}
/* a structure to encapsulate the state information about an in-progress ffirst/fnext operation */
struct find_state {
- struct smbsrv_request *req;
- struct smb_trans2 *trans;
+ struct trans_op *op;
+ void *search;
enum smb_search_level level;
uint16_t last_entry_offset;
uint16_t flags;
@@ -1033,11 +1070,11 @@ struct find_state {
/*
fill a single entry in a trans2 find reply
*/
-static BOOL find_fill_info(struct smbsrv_request *req,
- struct smb_trans2 *trans,
- struct find_state *state,
+static BOOL find_fill_info(struct find_state *state,
union smb_search_data *file)
{
+ struct smbsrv_request *req = state->op->req;
+ struct smb_trans2 *trans = state->op->trans;
uint8_t *data;
uint_t ofs = trans->out.data.length;
uint32_t ea_size;
@@ -1052,11 +1089,11 @@ static BOOL find_fill_info(struct smbsrv_request *req,
case RAW_SEARCH_STANDARD:
if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
- trans2_grow_data(req, trans, ofs + 27);
+ trans2_grow_data(trans, ofs + 27);
SIVAL(trans->out.data.data, ofs, file->standard.resume_key);
ofs += 4;
} else {
- trans2_grow_data(req, trans, ofs + 23);
+ trans2_grow_data(trans, ofs + 23);
}
data = trans->out.data.data + ofs;
srv_push_dos_date2(req->smb_conn, data, 0, file->standard.create_time);
@@ -1071,11 +1108,11 @@ static BOOL find_fill_info(struct smbsrv_request *req,
case RAW_SEARCH_EA_SIZE:
if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
- trans2_grow_data(req, trans, ofs + 31);
+ trans2_grow_data(trans, ofs + 31);
SIVAL(trans->out.data.data, ofs, file->ea_size.resume_key);
ofs += 4;
} else {
- trans2_grow_data(req, trans, ofs + 27);
+ trans2_grow_data(trans, ofs + 27);
}
data = trans->out.data.data + ofs;
srv_push_dos_date2(req->smb_conn, data, 0, file->ea_size.create_time);
@@ -1087,20 +1124,20 @@ static BOOL find_fill_info(struct smbsrv_request *req,
SIVAL(data, 22, file->ea_size.ea_size);
trans2_append_data_string(req, trans, &file->ea_size.name,
ofs + 26, STR_LEN8BIT | STR_NOALIGN);
- trans2_grow_data(req, trans, trans->out.data.length + 1);
+ trans2_grow_data(trans, trans->out.data.length + 1);
trans->out.data.data[trans->out.data.length-1] = 0;
break;
case RAW_SEARCH_EA_LIST:
ea_size = ea_list_size(file->ea_list.eas.num_eas, file->ea_list.eas.eas);
if (state->flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) {
- if (!trans2_grow_data(req, trans, ofs + 27 + ea_size)) {
+ if (!trans2_grow_data(trans, ofs + 27 + ea_size)) {
return False;
}
SIVAL(trans->out.data.data, ofs, file->ea_list.resume_key);
ofs += 4;
} else {
- if (!trans2_grow_data(req, trans, ofs + 23 + ea_size)) {
+ if (!trans2_grow_data(trans, ofs + 23 + ea_size)) {
return False;
}
}
@@ -1114,12 +1151,12 @@ static BOOL find_fill_info(struct smbsrv_request *req,
ea_put_list(data+22, file->ea_list.eas.num_eas, file->ea_list.eas.eas);
trans2_append_data_string(req, trans, &file->ea_list.name,
ofs + 22 + ea_size, STR_LEN8BIT | STR_NOALIGN);
- trans2_grow_data(req, trans, trans->out.data.length + 1);
+ trans2_grow_data(trans, trans->out.data.length + 1);
trans->out.data.data[trans->out.data.length-1] = 0;
break;
case RAW_SEARCH_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 64);
+ trans2_grow_data(trans, ofs + 64);
data = trans->out.data.data + ofs;
SIVAL(data, 4, file->directory_info.file_index);
push_nttime(data, 8, file->directory_info.create_time);
@@ -1136,7 +1173,7 @@ static BOOL find_fill_info(struct smbsrv_request *req,
break;
case RAW_SEARCH_FULL_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 68);
+ trans2_grow_data(trans, ofs + 68);
data = trans->out.data.data + ofs;
SIVAL(data, 4, file->full_directory_info.file_index);
push_nttime(data, 8, file->full_directory_info.create_time);
@@ -1154,7 +1191,7 @@ static BOOL find_fill_info(struct smbsrv_request *req,
break;
case RAW_SEARCH_NAME_INFO:
- trans2_grow_data(req, trans, ofs + 12);
+ trans2_grow_data(trans, ofs + 12);
data = trans->out.data.data + ofs;
SIVAL(data, 4, file->name_info.file_index);
trans2_append_data_string(req, trans, &file->name_info.name,
@@ -1164,7 +1201,7 @@ static BOOL find_fill_info(struct smbsrv_request *req,
break;
case RAW_SEARCH_BOTH_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 94);
+ trans2_grow_data(trans, ofs + 94);
data = trans->out.data.data + ofs;
SIVAL(data, 4, file->both_directory_info.file_index);
push_nttime(data, 8, file->both_directory_info.create_time);
@@ -1189,7 +1226,7 @@ static BOOL find_fill_info(struct smbsrv_request *req,
break;
case RAW_SEARCH_ID_FULL_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 80);
+ trans2_grow_data(trans, ofs + 80);
data = trans->out.data.data + ofs;
SIVAL(data, 4, file->id_full_directory_info.file_index);
push_nttime(data, 8, file->id_full_directory_info.create_time);
@@ -1209,7 +1246,7 @@ static BOOL find_fill_info(struct smbsrv_request *req,
break;
case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO:
- trans2_grow_data(req, trans, ofs + 104);
+ trans2_grow_data(trans, ofs + 104);
data = trans->out.data.data + ofs;
SIVAL(data, 4, file->id_both_directory_info.file_index);
push_nttime(data, 8, file->id_both_directory_info.create_time);
@@ -1240,16 +1277,16 @@ static BOOL find_fill_info(struct smbsrv_request *req,
/* callback function for trans2 findfirst/findnext */
static BOOL find_callback(void *private, union smb_search_data *file)
{
- struct find_state *state = (struct find_state *)private;
- struct smb_trans2 *trans = state->trans;
+ struct find_state *state = talloc_get_type(private, struct find_state);
+ struct smb_trans2 *trans = state->op->trans;
uint_t old_length;
old_length = trans->out.data.length;
- if (!find_fill_info(state->req, trans, state, file) ||
+ if (!find_fill_info(state, file) ||
trans->out.data.length > trans->in.max_data) {
/* restore the old length and tell the backend to stop */
- trans2_grow_data(state->req, trans, old_length);
+ trans2_grow_data(trans, old_length);
return False;
}
@@ -1257,74 +1294,125 @@ static BOOL find_callback(void *private, union smb_search_data *file)
return True;
}
+/*
+ trans2 findfirst send
+ */
+static NTSTATUS trans2_findfirst_send(struct trans_op *op)
+{
+ struct smbsrv_request *req = op->req;
+ struct smb_trans2 *trans = op->trans;
+ union smb_search_first *search;
+ struct find_state *state;
+ uint8_t *param;
+
+ if (!NT_STATUS_IS_OK(req->async_states->status)) {
+ trans2_setup_reply(trans, 0, 0, 0);
+ return req->async_states->status;
+ }
+
+ state = talloc_get_type(op->op_info, struct find_state);
+ search = talloc_get_type(state->search, union smb_search_first);
+
+ /* fill in the findfirst reply header */
+ param = trans->out.params.data;
+ SSVAL(param, VWV(0), search->t2ffirst.out.handle);
+ SSVAL(param, VWV(1), search->t2ffirst.out.count);
+ SSVAL(param, VWV(2), search->t2ffirst.out.end_of_search);
+ SSVAL(param, VWV(3), 0);
+ SSVAL(param, VWV(4), state->last_entry_offset);
+
+ return NT_STATUS_OK;
+}
+
/*
trans2 findfirst implementation
*/
-static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct trans_op *op)
{
- union smb_search_first search;
+ struct smb_trans2 *trans = op->trans;
+ union smb_search_first *search;
NTSTATUS status;
uint16_t level;
- uint8_t *param;
- struct find_state state;
+ struct find_state *state;
/* make sure we got all the parameters */
if (trans->in.params.length < 14) {
return NT_STATUS_FOOBAR;
}
- search.t2ffirst.in.search_attrib = SVAL(trans->in.params.data, 0);
- search.t2ffirst.in.max_count = SVAL(trans->in.params.data, 2);
- search.t2ffirst.in.flags = SVAL(trans->in.params.data, 4);
- level = SVAL(trans->in.params.data, 6);
- search.t2ffirst.in.storage_type = IVAL(trans->in.params.data, 8);
+ search = talloc(op, union smb_search_first);
+ NT_STATUS_HAVE_NO_MEMORY(search);
- trans2_pull_blob_string(req, &trans->in.params, 12, &search.t2ffirst.in.pattern, 0);
- if (search.t2ffirst.in.pattern == NULL) {
+ search->t2ffirst.in.search_attrib = SVAL(trans->in.params.data, 0);
+ search->t2ffirst.in.max_count = SVAL(trans->in.params.data, 2);
+ search->t2ffirst.in.flags = SVAL(trans->in.params.data, 4);
+ level = SVAL(trans->in.params.data, 6);
+ search->t2ffirst.in.storage_type = IVAL(trans->in.params.data, 8);
+
+ trans2_pull_blob_string(req, &trans->in.params, 12, &search->t2ffirst.in.pattern, 0);
+ if (search->t2ffirst.in.pattern == NULL) {
return NT_STATUS_FOOBAR;
}
- search.t2ffirst.level = (enum smb_search_level)level;
- if (search.t2ffirst.level >= RAW_SEARCH_GENERIC) {
+ search->t2ffirst.level = (enum smb_search_level)level;
+ if (search->t2ffirst.level >= RAW_SEARCH_GENERIC) {
return NT_STATUS_INVALID_LEVEL;
}
- if (search.t2ffirst.level == RAW_SEARCH_EA_LIST) {
+ if (search->t2ffirst.level == RAW_SEARCH_EA_LIST) {
status = ea_pull_name_list(&trans->in.data, req,
- &search.t2ffirst.in.num_names,
- &search.t2ffirst.in.ea_names);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ &search->t2ffirst.in.num_names,
+ &search->t2ffirst.in.ea_names);
+ NT_STATUS_NOT_OK_RETURN(status);
}
/* setup the private state structure that the backend will
give us in the callback */
- state.req = req;
- state.trans = trans;
- state.level = search.t2ffirst.level;
- state.last_entry_offset = 0;
- state.flags = search.t2ffirst.in.flags;
+ state = talloc(op, struct find_state);
+ NT_STATUS_HAVE_NO_MEMORY(state);
+ state->op = op;
+ state->search = search;
+ state->level = search->t2ffirst.level;
+ state->last_entry_offset= 0;
+ state->flags = search->t2ffirst.in.flags;
/* setup for just a header in the reply */
- trans2_setup_reply(req, trans, 10, 0, 0);
+ trans2_setup_reply(trans, 10, 0, 0);
- /* call the backend */
- status = ntvfs_search_first(req, &search, &state, find_callback);
- if (!NT_STATUS_IS_OK(status)) {
- trans2_setup_reply(req, trans, 0, 0, 0);
- return status;
+ op->op_info = state;
+ op->send_fn = trans2_findfirst_send;
+
+ return ntvfs_search_first(req, search, state, find_callback);
+}
+
+
+/*
+ trans2 findnext send
+*/
+static NTSTATUS trans2_findnext_send(struct trans_op *op)
+{
+ struct smbsrv_request *req = op->req;
+ struct smb_trans2 *trans = op->trans;
+ union smb_search_next *search;
+ struct find_state *state;
+ uint8_t *param;
+
+ if (!NT_STATUS_IS_OK(req->async_states->status)) {
+ trans2_setup_reply(trans, 0, 0, 0);
+ return req->async_states->status;
}
+ state = talloc_get_type(op->op_info, struct find_state);
+ search = talloc_get_type(state->search, union smb_search_next);
+
/* fill in the findfirst reply header */
param = trans->out.params.data;
- SSVAL(param, VWV(0), search.t2ffirst.out.handle);
- SSVAL(param, VWV(1), search.t2ffirst.out.count);
- SSVAL(param, VWV(2), search.t2ffirst.out.end_of_search);
- SSVAL(param, VWV(3), 0);
- SSVAL(param, VWV(4), state.last_entry_offset);
-
+ SSVAL(param, VWV(0), search->t2fnext.out.count);
+ SSVAL(param, VWV(1), search->t2fnext.out.end_of_search);
+ SSVAL(param, VWV(2), 0);
+ SSVAL(param, VWV(3), state->last_entry_offset);
+
return NT_STATUS_OK;
}
@@ -1332,76 +1420,70 @@ static NTSTATUS trans2_findfirst(struct smbsrv_request *req, struct smb_trans2 *
/*
trans2 findnext implementation
*/
-static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_findnext(struct smbsrv_request *req, struct trans_op *op)
{
- union smb_search_next search;
+ struct smb_trans2 *trans = op->trans;
+ union smb_search_next *search;
NTSTATUS status;
uint16_t level;
- uint8_t *param;
- struct find_state state;
+ struct find_state *state;
/* make sure we got all the parameters */
if (trans->in.params.length < 12) {
return NT_STATUS_FOOBAR;
}
- search.t2fnext.in.handle = SVAL(trans->in.params.data, 0);
- search.t2fnext.in.max_count = SVAL(trans->in.params.data, 2);
- level = SVAL(trans->in.params.data, 4);
- search.t2fnext.in.resume_key = IVAL(trans->in.params.data, 6);
- search.t2fnext.in.flags = SVAL(trans->in.params.data, 10);
+ search = talloc(op, union smb_search_next);
+ NT_STATUS_HAVE_NO_MEMORY(search);
+
+ search->t2fnext.in.handle = SVAL(trans->in.params.data, 0);
+ search->t2fnext.in.max_count = SVAL(trans->in.params.data, 2);
+ level = SVAL(trans->in.params.data, 4);
+ search->t2fnext.in.resume_key = IVAL(trans->in.params.data, 6);
+ search->t2fnext.in.flags = SVAL(trans->in.params.data, 10);
- trans2_pull_blob_string(req, &trans->in.params, 12, &search.t2fnext.in.last_name, 0);
- if (search.t2fnext.in.last_name == NULL) {
+ trans2_pull_blob_string(req, &trans->in.params, 12, &search->t2fnext.in.last_name, 0);
+ if (search->t2fnext.in.last_name == NULL) {
return NT_STATUS_FOOBAR;
}
- search.t2fnext.level = (enum smb_search_level)level;
- if (search.t2fnext.level >= RAW_SEARCH_GENERIC) {
+ search->t2fnext.level = (enum smb_search_level)level;
+ if (search->t2fnext.level >= RAW_SEARCH_GENERIC) {
return NT_STATUS_INVALID_LEVEL;
}
- if (search.t2fnext.level == RAW_SEARCH_EA_LIST) {
+ if (search->t2fnext.level == RAW_SEARCH_EA_LIST) {
status = ea_pull_name_list(&trans->in.data, req,
- &search.t2fnext.in.num_names,
- &search.t2fnext.in.ea_names);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ &search->t2fnext.in.num_names,
+ &search->t2fnext.in.ea_names);
+ NT_STATUS_NOT_OK_RETURN(status);
}
/* setup the private state structure that the backend will give us in the callback */
- state.req = req;
- state.trans = trans;
- state.level = search.t2fnext.level;
- state.last_entry_offset = 0;
- state.flags = search.t2fnext.in.flags;
+ state = talloc(op, struct find_state);
+ NT_STATUS_HAVE_NO_MEMORY(state);
+ state->op = op;
+ state->search = search;
+ state->level = search->t2fnext.level;
+ state->last_entry_offset= 0;
+ state->flags = search->t2fnext.in.flags;
/* setup for just a header in the reply */
- trans2_setup_reply(req, trans, 8, 0, 0);
+ trans2_setup_reply(trans, 8, 0, 0);
- /* call the backend */
- status = ntvfs_search_next(req, &search, &state, find_callback);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ op->op_info = state;
+ op->send_fn = trans2_findnext_send;
- /* fill in the findfirst reply header */
- param = trans->out.params.data;
- SSVAL(param, VWV(0), search.t2fnext.out.count);
- SSVAL(param, VWV(1), search.t2fnext.out.end_of_search);
- SSVAL(param, VWV(2), 0);
- SSVAL(param, VWV(3), state.last_entry_offset);
-
- return NT_STATUS_OK;
+ return ntvfs_search_next(req, search, state, find_callback);
}
/*
backend for trans2 requests
*/
-static NTSTATUS trans2_backend(struct smbsrv_request *req, struct smb_trans2 *trans)
+static NTSTATUS trans2_backend(struct smbsrv_request *req, struct trans_op *op)
{
+ struct smb_trans2 *trans = op->trans;
NTSTATUS status;
/* direct trans2 pass thru */
@@ -1418,23 +1500,23 @@ static NTSTATUS trans2_backend(struct smbsrv_request *req, struct smb_trans2 *tr
/* the trans2 command is in setup[0] */
switch (trans->in.setup[0]) {
case TRANSACT2_FINDFIRST:
- return trans2_findfirst(req, trans);
+ return trans2_findfirst(req, op);
case TRANSACT2_FINDNEXT:
- return trans2_findnext(req, trans);
+ return trans2_findnext(req, op);
case TRANSACT2_QPATHINFO:
- return trans2_qpathinfo(req, trans);
+ return trans2_qpathinfo(req, op);
case TRANSACT2_QFILEINFO:
- return trans2_qfileinfo(req, trans);
+ return trans2_qfileinfo(req, op);
case TRANSACT2_SETFILEINFO:
- return trans2_setfileinfo(req, trans);
+ return trans2_setfileinfo(req, op);
case TRANSACT2_SETPATHINFO:
- return trans2_setpathinfo(req, trans);
+ return trans2_setpathinfo(req, op);
case TRANSACT2_QFSINFO:
- return trans2_qfsinfo(req, trans);
+ return trans2_qfsinfo(req, op);
case TRANSACT2_OPEN:
- return trans2_open(req, trans);
+ return trans2_open(req, op);
case TRANSACT2_MKDIR:
- return trans2_mkdir(req, trans);
+ return trans2_mkdir(req, op);
}
/* an unknown trans2 command */
@@ -1445,7 +1527,7 @@ static NTSTATUS trans2_backend(struct smbsrv_request *req, struct smb_trans2 *tr
/*
send a continue request
*/
-static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
+static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
struct smb_trans2 *trans)
{
struct smbsrv_trans_partial *tp;
@@ -1475,24 +1557,31 @@ static void reply_trans_continue(struct smbsrv_request *req, uint8_t command,
/*
answer a reconstructed trans request
*/
-static void reply_trans_complete(struct smbsrv_request *req, uint8_t command,
- struct smb_trans2 *trans)
+static void reply_trans_send(struct smbsrv_request *req)
{
+ struct trans_op *op;
+ struct smb_trans2 *trans;
uint16_t params_left, data_left;
uint8_t *params, *data;
- NTSTATUS status;
int i;
- /* its a full request, give it to the backend */
- if (command == SMBtrans) {
- status = ntvfs_trans(req, trans);
- } else {
- status = trans2_backend(req, trans);
+ if (NT_STATUS_IS_ERR(req->async_states->status)) {
+ smbsrv_send_error(req, req->async_states->status);
+ return;
}
- if (NT_STATUS_IS_ERR(status)) {
- smbsrv_send_error(req, status);
- return;
+ op = talloc_get_type(req->async_states->private_data, struct trans_op);
+ trans = op->trans;
+
+ /* if this function needs work to form the nttrans reply buffer, then
+ call that now */
+ if (op->send_fn != NULL) {
+ NTSTATUS status;
+ status = op->send_fn(op);
+ if (!NT_STATUS_IS_OK(status)) {
+ smbsrv_send_error(req, status);
+ return;
+ }
}
params_left = trans->out.params.length;
@@ -1502,8 +1591,8 @@ static void reply_trans_complete(struct smbsrv_request *req, uint8_t command,
smbsrv_setup_reply(req, 10 + trans->out.setup_count, 0);
- if (!NT_STATUS_IS_OK(status)) {
- smbsrv_setup_error(req, status);
+ if (!NT_STATUS_IS_OK(req->async_states->status)) {
+ smbsrv_setup_error(req, req->async_states->status);
}
/* we need to divide up the reply into chunks that fit into
@@ -1574,6 +1663,42 @@ static void reply_trans_complete(struct smbsrv_request *req, uint8_t command,
/*
+ answer a reconstructed trans request
+*/
+static void reply_trans_complete(struct smbsrv_request *req, uint8_t command,
+ struct smb_trans2 *trans)
+{
+ struct trans_op *op;
+
+ op = talloc(trans, struct trans_op);
+ if (op == NULL) {
+ smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ op->req = req;
+ op->trans = trans;
+ op->command = command;
+ op->op_info = NULL;
+ op->send_fn = NULL;
+
+ req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+ req->async_states->send_fn = reply_trans_send;
+ req->async_states->private_data = op;
+
+ /* its a full request, give it to the backend */
+ if (command == SMBtrans) {
+ req->async_states->status = ntvfs_trans(req, trans);
+ } else {
+ req->async_states->status = trans2_backend(req, op);
+ }
+
+ if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) {
+ req->async_states->send_fn(req);
+ }
+}
+
+/*
Reply to an SMBtrans or SMBtrans2 request
*/
static void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
@@ -1584,18 +1709,18 @@ static void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
uint16_t param_count, data_count;
uint16_t param_total, data_total;
- trans = talloc(req, struct smb_trans2);
- if (trans == NULL) {
- smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
- return;
- }
-
/* parse request */
if (req->in.wct < 14) {
smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
return;
}
+ trans = talloc(req, struct smb_trans2);
+ if (trans == NULL) {
+ smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
param_total = SVAL(req->in.vwv, VWV(0));
data_total = SVAL(req->in.vwv, VWV(1));
trans->in.max_param = SVAL(req->in.vwv, VWV(2));
@@ -1615,7 +1740,7 @@ static void reply_trans_generic(struct smbsrv_request *req, uint8_t command)
}
/* parse out the setup words */
- trans->in.setup = talloc_array(req, uint16_t, trans->in.setup_count);
+ trans->in.setup = talloc_array(trans, uint16_t, trans->in.setup_count);
if (trans->in.setup_count && !trans->in.setup) {
smbsrv_send_error(req, NT_STATUS_NO_MEMORY);
return;
@@ -1657,9 +1782,16 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
uint16_t param_total, data_total;
DATA_BLOB params, data;
+ /* parse request */
+ if (req->in.wct < 8) {
+ smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+
for (tp=req->smb_conn->trans_partial;tp;tp=tp->next) {
if (tp->command == command &&
SVAL(tp->req->in.hdr, HDR_MID) == SVAL(req->in.hdr, HDR_MID)) {
+/* TODO: check the VUID, PID and TID too? */
break;
}
}
@@ -1671,12 +1803,6 @@ static void reply_transs_generic(struct smbsrv_request *req, uint8_t command)
trans = tp->trans;
- /* parse request */
- if (req->in.wct < 8) {
- smbsrv_send_error(req, NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
param_total = SVAL(req->in.vwv, VWV(0));
data_total = SVAL(req->in.vwv, VWV(1));
param_count = SVAL(req->in.vwv, VWV(2));