summaryrefslogtreecommitdiff
path: root/source3/smbd/smb2_create.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2010-04-23 13:10:15 -0700
committerJeremy Allison <jra@samba.org>2010-04-23 13:10:15 -0700
commit2bbb8c917e372ceeb1e144259d9d2b0eab7cc212 (patch)
treef9cbf789caf28cf2cbd3506e82b575f9ac4af2d8 /source3/smbd/smb2_create.c
parentdd2025947136f28b22b70de59309e149a1f45f3d (diff)
downloadsamba-2bbb8c917e372ceeb1e144259d9d2b0eab7cc212.tar.gz
samba-2bbb8c917e372ceeb1e144259d9d2b0eab7cc212.tar.bz2
samba-2bbb8c917e372ceeb1e144259d9d2b0eab7cc212.zip
Allow smb2 create requests to be cancelled.
Jeremy.
Diffstat (limited to 'source3/smbd/smb2_create.c')
-rw-r--r--source3/smbd/smb2_create.c80
1 files changed, 69 insertions, 11 deletions
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index ec20b7c365..d97d4af63a 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -199,6 +199,12 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
return smbd_smb2_request_pending_queue(smb2req, tsubreq);
}
+static uint64_t get_mid_from_smb2req(struct smbd_smb2_request *smb2req)
+{
+ uint8_t *reqhdr = (uint8_t *)smb2req->out.vector[smb2req->current_idx].iov_base;
+ return BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
+}
+
static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
{
struct smbd_smb2_request *smb2req = tevent_req_callback_data(tsubreq,
@@ -223,6 +229,19 @@ static void smbd_smb2_request_create_done(struct tevent_req *tsubreq)
NTSTATUS status;
NTSTATUS error; /* transport error */
+ if (smb2req->cancelled) {
+ uint64_t mid = get_mid_from_smb2req(smb2req);
+ DEBUG(10,("smbd_smb2_request_create_done: cancelled mid %llu\n",
+ (unsigned long long)mid ));
+ error = smbd_smb2_request_error(smb2req, NT_STATUS_CANCELLED);
+ if (!NT_STATUS_IS_OK(error)) {
+ smbd_server_connection_terminate(smb2req->sconn,
+ nt_errstr(error));
+ return;
+ }
+ return;
+ }
+
status = smbd_smb2_create_recv(tsubreq,
smb2req,
&out_oplock_level,
@@ -318,6 +337,7 @@ struct smbd_smb2_create_state {
struct smb_request *smb1req;
struct timed_event *te;
struct timeval request_time;
+ struct file_id id;
DATA_BLOB private_data;
uint8_t out_oplock_level;
uint32_t out_create_action;
@@ -818,8 +838,7 @@ static struct smbd_smb2_request *find_open_smb2req(uint64_t mid)
struct smbd_smb2_request *smb2req;
for (smb2req = sconn->smb2.requests; smb2req; smb2req = smb2req->next) {
- uint8_t *reqhdr = (uint8_t *)smb2req->out.vector[smb2req->current_idx].iov_base;
- uint64_t message_id = BVAL(reqhdr, SMB2_HDR_MESSAGE_ID);
+ uint64_t message_id = get_mid_from_smb2req(smb2req);
if (message_id == mid) {
return smb2req;
}
@@ -859,17 +878,11 @@ bool open_was_deferred_smb2(uint64_t mid)
return true;
}
-void remove_deferred_open_message_smb2(uint64_t mid)
+static void remove_deferred_open_message_smb2_internal(struct smbd_smb2_request *smb2req,
+ uint64_t mid)
{
struct smbd_smb2_create_state *state = NULL;
- struct smbd_smb2_request *smb2req = find_open_smb2req(mid);
- if (!smb2req) {
- DEBUG(10,("remove_deferred_open_message_smb2: "
- "can't find mid %llu\n",
- (unsigned long long)mid ));
- return;
- }
if (!smb2req->subreq) {
return;
}
@@ -882,7 +895,7 @@ void remove_deferred_open_message_smb2(uint64_t mid)
return;
}
- DEBUG(10,("remove_deferred_open_message_smb2: "
+ DEBUG(10,("remove_deferred_open_message_smb2_internal: "
"mid %llu\n",
(unsigned long long)mid ));
@@ -890,6 +903,19 @@ void remove_deferred_open_message_smb2(uint64_t mid)
TALLOC_FREE(state->te);
}
+void remove_deferred_open_message_smb2(uint64_t mid)
+{
+ struct smbd_smb2_request *smb2req = find_open_smb2req(mid);
+
+ if (!smb2req) {
+ DEBUG(10,("remove_deferred_open_message_smb2: "
+ "can't find mid %llu\n",
+ (unsigned long long)mid ));
+ return;
+ }
+ remove_deferred_open_message_smb2_internal(smb2req, mid);
+}
+
void schedule_deferred_open_message_smb2(uint64_t mid)
{
struct tevent_immediate *im = NULL;
@@ -979,9 +1005,36 @@ static void smb2_deferred_open_timer(struct event_context *ev,
}
}
+static bool smbd_smb2_create_cancel(struct tevent_req *req)
+{
+ struct smbd_smb2_request *smb2req = NULL;
+ struct smbd_smb2_create_state *state = tevent_req_data(req,
+ struct smbd_smb2_create_state);
+ uint64_t mid;
+
+ if (!state) {
+ return false;
+ }
+
+ if (!state->smb2req) {
+ return false;
+ }
+
+ smb2req = state->smb2req;
+ mid = get_mid_from_smb2req(smb2req);
+
+ remove_deferred_open_entry(state->id, mid);
+ remove_deferred_open_message_smb2_internal(smb2req, mid);
+ smb2req->cancelled = true;
+
+ tevent_req_done(req);
+ return true;
+}
+
bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
struct timeval request_time,
struct timeval timeout,
+ struct file_id id,
char *private_data,
size_t priv_len)
{
@@ -1000,6 +1053,7 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
if (!state) {
return false;
}
+ state->id = id;
state->request_time = request_time;
state->private_data = data_blob_talloc(state, private_data,
priv_len);
@@ -1048,5 +1102,9 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req,
if (!state->te) {
return false;
}
+
+ /* allow this request to be canceled */
+ tevent_req_set_cancel_fn(req, smbd_smb2_create_cancel);
+
return true;
}