summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-06-05 17:48:28 +0200
committerStefan Metzmacher <metze@samba.org>2009-06-05 17:53:49 +0200
commita3e328859b0004b974d38f0feae8ca6894c9b014 (patch)
treee92734eb49cd27939cc1e82f8d467621f5e233d5 /source3/smbd
parent4a64df164acfbcf9aad9d7b639b1dcbd5f7fb376 (diff)
downloadsamba-a3e328859b0004b974d38f0feae8ca6894c9b014.tar.gz
samba-a3e328859b0004b974d38f0feae8ca6894c9b014.tar.bz2
samba-a3e328859b0004b974d38f0feae8ca6894c9b014.zip
s3:smbd: add support for SMB2 Ioctl FSCTL_PIPE_TRANSCEIVE on IPC$
metze
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/smb2_ioctl.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c
index 3ebce3eba8..e7a3d358bb 100644
--- a/source3/smbd/smb2_ioctl.c
+++ b/source3/smbd/smb2_ioctl.c
@@ -183,6 +183,9 @@ struct smbd_smb2_ioctl_state {
DATA_BLOB out_output;
};
+static void smbd_smb2_ioctl_pipe_write_done(struct tevent_req *subreq);
+static void smbd_smb2_ioctl_pipe_read_done(struct tevent_req *subreq);
+
static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
@@ -237,6 +240,35 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
}
switch (in_ctl_code) {
+ case 0x0011C017: /* FSCTL_PIPE_TRANSCEIVE */
+
+ if (!IS_IPC(smbreq->conn)) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
+ return tevent_req_post(req, ev);
+ }
+
+ if (fsp == NULL) {
+ tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
+ return tevent_req_post(req, ev);
+ }
+
+ if (!fsp_is_np(fsp)) {
+ tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = np_write_send(state, ev,
+ fsp->fake_file_handle,
+ in_input.data,
+ in_input.length);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq,
+ smbd_smb2_ioctl_pipe_write_done,
+ req);
+ return req;
+
default:
if (IS_IPC(smbreq->conn)) {
tevent_req_nterror(req, NT_STATUS_FS_DRIVER_REQUIRED);
@@ -250,6 +282,66 @@ static struct tevent_req *smbd_smb2_ioctl_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
+static void smbd_smb2_ioctl_pipe_write_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct smbd_smb2_ioctl_state *state = tevent_req_data(req,
+ struct smbd_smb2_ioctl_state);
+ NTSTATUS status;
+ ssize_t nwritten = -1;
+
+ status = np_write_recv(subreq, &nwritten);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ if (nwritten != state->in_input.length) {
+ tevent_req_nterror(req, NT_STATUS_PIPE_NOT_AVAILABLE);
+ return;
+ }
+
+ state->out_output = data_blob_talloc(state, NULL, state->in_max_output);
+ if (state->in_max_output > 0 &&
+ tevent_req_nomem(state->out_output.data, req)) {
+ return;
+ }
+
+ subreq = np_read_send(state->smbreq->conn,
+ state->smb2req->conn->smb2.event_ctx,
+ state->fsp->fake_file_handle,
+ state->out_output.data,
+ state->out_output.length);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, smbd_smb2_ioctl_pipe_read_done, req);
+}
+
+static void smbd_smb2_ioctl_pipe_read_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct smbd_smb2_ioctl_state *state = tevent_req_data(req,
+ struct smbd_smb2_ioctl_state);
+ NTSTATUS status;
+ ssize_t nread;
+ bool is_data_outstanding;
+
+ status = np_read_recv(subreq, &nread, &is_data_outstanding);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ state->out_output.length = nread;
+
+ tevent_req_done(req);
+}
+
static NTSTATUS smbd_smb2_ioctl_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
DATA_BLOB *out_output)