*/
#include "includes.h"
+#include "smbd/smbd.h"
#include "smbd/globals.h"
#include "../libcli/smb/smb_common.h"
-#include "librpc/gen_ndr/messaging.h"
+#include "../lib/util/tevent_ntstatus.h"
+#include "messages.h"
struct smbd_smb2_lock_element {
uint64_t offset;
struct smbd_lock_element *locks;
};
-static void remove_pending_lock(TALLOC_CTX *mem_ctx, struct blocking_lock_record *blr);
+static void remove_pending_lock(struct smbd_smb2_lock_state *state,
+ struct blocking_lock_record *blr);
static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
- uint32_t in_smbpid,
- uint64_t in_file_id_volatile,
+ struct files_struct *in_fsp,
uint16_t in_lock_count,
struct smbd_smb2_lock_element *in_locks);
static NTSTATUS smbd_smb2_lock_recv(struct tevent_req *req);
static void smbd_smb2_request_lock_done(struct tevent_req *subreq);
NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req)
{
- const uint8_t *inhdr;
const uint8_t *inbody;
- const int i = req->current_idx;
- size_t expected_body_size = 0x30;
- size_t body_size;
- uint32_t in_smbpid;
uint16_t in_lock_count;
uint64_t in_file_id_persistent;
uint64_t in_file_id_volatile;
+ struct files_struct *in_fsp;
struct smbd_smb2_lock_element *in_locks;
struct tevent_req *subreq;
const uint8_t *lock_buffer;
uint16_t l;
+ NTSTATUS status;
- inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
- if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
- }
-
- inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
-
- body_size = SVAL(inbody, 0x00);
- if (body_size != expected_body_size) {
- return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
+ status = smbd_smb2_request_verify_sizes(req, 0x30);
+ if (!NT_STATUS_IS_OK(status)) {
+ return smbd_smb2_request_error(req, status);
}
-
- in_smbpid = IVAL(inhdr, SMB2_HDR_PID);
+ inbody = SMBD_SMB2_IN_BODY_PTR(req);
in_lock_count = CVAL(inbody, 0x02);
/* 0x04 - 4 bytes reserved */
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
}
- if (((in_lock_count - 1) * 0x18) > req->in.vector[i+2].iov_len) {
+ if (((in_lock_count - 1) * 0x18) > SMBD_SMB2_IN_DYN_LEN(req)) {
return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
}
- if (req->compat_chain_fsp) {
- /* skip check */
- } else if (in_file_id_persistent != 0) {
- return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
- }
-
in_locks = talloc_array(req, struct smbd_smb2_lock_element,
in_lock_count);
if (in_locks == NULL) {
in_locks[l].flags = IVAL(lock_buffer, 0x10);
/* 0x14 - 4 reserved bytes */
- lock_buffer = (const uint8_t *)req->in.vector[i+2].iov_base;
+ lock_buffer = SMBD_SMB2_IN_DYN_PTR(req);
for (l=1; l < in_lock_count; l++) {
in_locks[l].offset = BVAL(lock_buffer, 0x00);
lock_buffer += 0x18;
}
- subreq = smbd_smb2_lock_send(req,
- req->sconn->smb2.event_ctx,
- req,
- in_smbpid,
- in_file_id_volatile,
+ in_fsp = file_fsp_smb2(req, in_file_id_persistent, in_file_id_volatile);
+ if (in_fsp == NULL) {
+ return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
+ }
+
+ subreq = smbd_smb2_lock_send(req, req->sconn->ev_ctx,
+ req, in_fsp,
in_lock_count,
in_locks);
if (subreq == NULL) {
}
tevent_req_set_callback(subreq, smbd_smb2_request_lock_done, req);
- return smbd_smb2_request_pending_queue(req, subreq);
+ return smbd_smb2_request_pending_queue(req, subreq, 500);
}
static void smbd_smb2_request_lock_done(struct tevent_req *subreq)
NTSTATUS status;
NTSTATUS error; /* transport error */
- if (smb2req->cancelled) {
- const uint8_t *inhdr = (const uint8_t *)
- smb2req->in.vector[smb2req->current_idx].iov_base;
- uint64_t mid = BVAL(inhdr, SMB2_HDR_MESSAGE_ID);
- struct smbd_smb2_lock_state *state;
-
- DEBUG(10,("smbd_smb2_request_lock_done: cancelled mid %llu\n",
- (unsigned long long)mid ));
-
- state = tevent_req_data(smb2req->subreq,
- struct smbd_smb2_lock_state);
-
- SMB_ASSERT(state);
- SMB_ASSERT(state->blr);
-
- remove_pending_lock(state, state->blr);
-
- 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_lock_recv(subreq);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) {
error = smbd_smb2_request_error(smb2req, status);
if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(smb2req->sconn,
+ smbd_server_connection_terminate(smb2req->xconn,
nt_errstr(error));
return;
}
return;
}
- outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x04);
+ outbody = smbd_smb2_generate_outbody(smb2req, 0x04);
if (outbody.data == NULL) {
error = smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(smb2req->sconn,
+ smbd_server_connection_terminate(smb2req->xconn,
nt_errstr(error));
return;
}
error = smbd_smb2_request_done(smb2req, outbody, NULL);
if (!NT_STATUS_IS_OK(error)) {
- smbd_server_connection_terminate(smb2req->sconn,
+ smbd_server_connection_terminate(smb2req->xconn,
nt_errstr(error));
return;
}
static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct smbd_smb2_request *smb2req,
- uint32_t in_smbpid,
- uint64_t in_file_id_volatile,
+ struct files_struct *fsp,
uint16_t in_lock_count,
struct smbd_smb2_lock_element *in_locks)
{
struct tevent_req *req;
struct smbd_smb2_lock_state *state;
struct smb_request *smb1req;
- connection_struct *conn = smb2req->tcon->compat_conn;
- files_struct *fsp;
int32_t timeout = -1;
bool isunlock = false;
uint16_t i;
}
state->smb1req = smb1req;
- DEBUG(10,("smbd_smb2_lock_send: file_id[0x%016llX]\n",
- (unsigned long long)in_file_id_volatile));
-
- fsp = file_fsp(smb1req, (uint16_t)in_file_id_volatile);
- if (fsp == NULL) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (conn != fsp->conn) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
- if (smb2req->session->vuid != fsp->vuid) {
- tevent_req_nterror(req, NT_STATUS_FILE_CLOSED);
- return tevent_req_post(req, ev);
- }
+ DEBUG(10,("smbd_smb2_lock_send: %s - %s\n",
+ fsp_str_dbg(fsp), fsp_fnum_dbg(fsp)));
locks = talloc_array(state, struct smbd_lock_element, in_lock_count);
if (locks == NULL) {
return tevent_req_post(req, ev);
}
+ if (!isunlock && (in_lock_count > 1)) {
+
+ /*
+ * 3.3.5.14.2 says we SHOULD fail with INVALID_PARAMETER if we
+ * have more than one lock and one of those is blocking.
+ */
+
+ for (i=0; i<in_lock_count; i++) {
+ uint32_t flags = in_locks[i].flags;
+
+ if ((flags & SMB2_LOCK_FLAG_FAIL_IMMEDIATELY) == 0) {
+ tevent_req_nterror(
+ req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+ }
+ }
+
for (i=0; i<in_lock_count; i++) {
bool invalid = false;
switch (in_locks[i].flags) {
case SMB2_LOCK_FLAG_SHARED:
case SMB2_LOCK_FLAG_EXCLUSIVE:
- if (i > 0) {
- tevent_req_nterror(req,
- NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
- }
if (isunlock) {
- tevent_req_nterror(req,
- NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
+ invalid = true;
+ break;
}
break;
case SMB2_LOCK_FLAG_SHARED|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY:
case SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY:
if (isunlock) {
- tevent_req_nterror(req,
- NT_STATUS_INVALID_PARAMETER);
- return tevent_req_post(req, ev);
+ invalid = true;
}
break;
default:
if (isunlock) {
/*
- * is the first element was a UNLOCK
- * we need to deferr the error response
+ * If the first element was a UNLOCK
+ * we need to defer the error response
* to the backend, because we need to process
* all unlock elements before
*/
return tevent_req_post(req, ev);
}
- locks[i].smblctx = in_file_id_volatile;
+ locks[i].smblctx = fsp->op->global->open_persistent_id;
locks[i].offset = in_locks[i].offset;
locks[i].count = in_locks[i].length;
* this is an invalid UNLOCK element
* and the backend needs to test for
* brltype != UNLOCK_LOCK and return
- * NT_STATUS_INVALID_PARAMER
+ * NT_STATUS_INVALID_PARAMETER
*/
locks[i].brltype = READ_LOCK;
} else {
(unsigned long long)locks[i].count,
(unsigned long long)locks[i].smblctx,
(int)locks[i].brltype ));
-
}
state->locks = locks;
state->lock_count = in_lock_count;
if (isunlock) {
- status = smbd_do_locking(smb1req, fsp,
- 0,
- timeout,
- in_lock_count,
- locks,
- 0,
- NULL,
- &async);
+ status = smbd_do_unlocking(smb1req, fsp,
+ in_lock_count, locks);
+ async = false;
} else {
status = smbd_do_locking(smb1req, fsp,
0,
timeout,
- 0,
- NULL,
in_lock_count,
locks,
&async);
}
if (async) {
+ tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
+ SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
return req;
}
static bool smbd_smb2_lock_cancel(struct tevent_req *req)
{
- struct smbd_smb2_request *smb2req = NULL;
- struct smbd_smb2_lock_state *state = tevent_req_data(req,
- struct smbd_smb2_lock_state);
- if (!state) {
- return false;
- }
+ struct smbd_smb2_request *smb2req = NULL;
+ struct smbd_smb2_lock_state *state = tevent_req_data(req,
+ struct smbd_smb2_lock_state);
+ if (!state) {
+ return false;
+ }
- if (!state->smb2req) {
- return false;
- }
+ if (!state->smb2req) {
+ return false;
+ }
+
+ smb2req = state->smb2req;
+
+ remove_pending_lock(state, state->blr);
+
+ /*
+ * If the request is canceled because of logoff, tdis or close
+ * the status is NT_STATUS_RANGE_NOT_LOCKED instead of
+ * NT_STATUS_CANCELLED.
+ *
+ * Note that the close case is handled in
+ * cancel_pending_lock_requests_by_fid_smb2(SHUTDOWN_CLOSE)
+ * for now.
+ */
+ if (!NT_STATUS_IS_OK(smb2req->session->status)) {
+ tevent_req_nterror(req, NT_STATUS_RANGE_NOT_LOCKED);
+ return true;
+ }
- smb2req = state->smb2req;
- smb2req->cancelled = true;
+ if (!NT_STATUS_IS_OK(smb2req->tcon->status)) {
+ tevent_req_nterror(req, NT_STATUS_RANGE_NOT_LOCKED);
+ return true;
+ }
- tevent_req_done(req);
- return true;
+ tevent_req_nterror(req, NT_STATUS_CANCELLED);
+ return true;
}
/****************************************************************
struct server_id server_id,
DATA_BLOB *data)
{
+ struct smbd_server_connection *sconn =
+ talloc_get_type_abort(private_data,
+ struct smbd_server_connection);
+
DEBUG(10,("received_unlock_msg (SMB2)\n"));
- process_blocking_lock_queue_smb2(timeval_current());
+
+ process_blocking_lock_queue_smb2(sconn, timeval_current());
}
/****************************************************************
if (!tevent_req_is_in_progress(smb2req->subreq)) {
return NULL;
}
- inhdr = (const uint8_t *)smb2req->in.vector[smb2req->current_idx].iov_base;
+ inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_LOCK) {
return NULL;
}
static bool recalc_smb2_brl_timeout(struct smbd_server_connection *sconn)
{
- struct smbd_smb2_request *smb2req;
+ struct smbXsrv_connection *xconn = NULL;
struct timeval next_timeout = timeval_zero();
int max_brl_timeout = lp_parm_int(-1, "brl", "recalctime", 5);
TALLOC_FREE(sconn->smb2.locks.brl_timeout);
- for (smb2req = sconn->smb2.requests; smb2req; smb2req = smb2req->next) {
- struct blocking_lock_record *blr =
- get_pending_smb2req_blr(smb2req);
- if (!blr) {
- continue;
- }
- if (timeval_is_zero(&blr->expire_time)) {
+ if (sconn->client != NULL) {
+ xconn = sconn->client->connections;
+ }
+
+ for (; xconn != NULL; xconn = xconn->next) {
+ struct smbd_smb2_request *smb2req, *nextreq;
+
+ for (smb2req = xconn->smb2.requests; smb2req; smb2req = nextreq) {
+ struct blocking_lock_record *blr =
+ get_pending_smb2req_blr(smb2req);
+
+ nextreq = smb2req->next;
+
+ if (blr == NULL) {
+ continue;
+ }
+
+ if (!timeval_is_zero(&blr->expire_time)) {
+ next_timeout = timeval_brl_min(&next_timeout,
+ &blr->expire_time);
+ continue;
+ }
+
/*
* If we're blocked on pid 0xFFFFFFFFFFFFFFFFLL this is
* a POSIX lock, so calculate a timeout of
* 10 seconds into the future.
*/
if (blr->blocking_smblctx == 0xFFFFFFFFFFFFFFFFLL) {
- struct timeval psx_to = timeval_current_ofs(10, 0);
- next_timeout = timeval_brl_min(&next_timeout, &psx_to);
- }
+ struct timeval psx_to;
- continue;
+ psx_to = timeval_current_ofs(10, 0);
+ next_timeout = timeval_brl_min(&next_timeout,
+ &psx_to);
+ }
}
-
- next_timeout = timeval_brl_min(&next_timeout, &blr->expire_time);
}
if (timeval_is_zero(&next_timeout)) {
(int)from_now.tv_sec, (int)from_now.tv_usec));
}
- sconn->smb2.locks.brl_timeout = event_add_timed(
- smbd_event_context(),
+ sconn->smb2.locks.brl_timeout = tevent_add_timer(
+ sconn->ev_ctx,
NULL,
next_timeout,
brl_timeout_fn,
- NULL);
+ sconn);
if (!sconn->smb2.locks.brl_timeout) {
return false;
}
}
/****************************************************************
- Get an SMB2 lock reqeust to go async. lock_timeout should
+ Get an SMB2 lock request to go async. lock_timeout should
always be -1 here.
*****************************************************************/
uint64_t count,
uint64_t blocking_smblctx)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
+ struct smbd_server_connection *sconn = smb1req->sconn;
struct smbd_smb2_request *smb2req = smb1req->smb2req;
struct tevent_req *req = NULL;
struct smbd_smb2_lock_state *state = NULL;
blr->expire_time.tv_sec = 0;
blr->expire_time.tv_usec = 0; /* Never expire. */
} else {
- blr->expire_time = timeval_current_ofs(
- lock_timeout/1000,
- (lock_timeout % 1000) * 1000);
+ blr->expire_time = timeval_current_ofs_msec(lock_timeout);
}
blr->lock_num = lock_num;
blr->blr_private = NULL;
/* Add a pending lock record for this. */
- status = brl_lock(smbd_messaging_context(),
+ status = brl_lock(sconn->msg_ctx,
br_lck,
smblctx,
- procid_self(),
+ messaging_server_id(sconn->msg_ctx),
offset,
count,
lock_type == READ_LOCK ? PENDING_READ_LOCK : PENDING_WRITE_LOCK,
blr->lock_flav,
true,
- NULL,
- blr);
+ NULL);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("push_blocking_lock_request_smb2: "
/* Ensure we'll receive messages when this is unlocked. */
if (!sconn->smb2.locks.blocking_lock_unlock_state) {
- messaging_register(smbd_messaging_context(), NULL,
+ messaging_register(sconn->msg_ctx, sconn,
MSG_SMB_UNLOCK, received_unlock_msg);
sconn->smb2.locks.blocking_lock_unlock_state = true;
}
Remove a pending lock record under lock.
*****************************************************************/
-static void remove_pending_lock(TALLOC_CTX *mem_ctx, struct blocking_lock_record *blr)
+static void remove_pending_lock(struct smbd_smb2_lock_state *state,
+ struct blocking_lock_record *blr)
{
struct byte_range_lock *br_lck = brl_get_locks(
- mem_ctx, blr->fsp);
+ state, blr->fsp);
DEBUG(10, ("remove_pending_lock: BLR = %p\n", blr));
if (br_lck) {
brl_lock_cancel(br_lck,
blr->smblctx,
- procid_self(),
+ messaging_server_id(blr->fsp->conn->sconn->msg_ctx),
blr->offset,
blr->count,
- blr->lock_flav,
- blr);
+ blr->lock_flav);
TALLOC_FREE(br_lck);
}
}
static void reprocess_blocked_smb2_lock(struct smbd_smb2_request *smb2req,
struct timeval tv_curr)
{
- NTSTATUS status;
+ NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
struct blocking_lock_record *blr = NULL;
struct smbd_smb2_lock_state *state = NULL;
+ struct byte_range_lock *br_lck = NULL;
+ struct smbd_lock_element *e = NULL;
files_struct *fsp = NULL;
if (!smb2req->subreq) {
return;
}
+ SMBPROFILE_IOBYTES_ASYNC_SET_BUSY(smb2req->profile);
+
state = tevent_req_data(smb2req->subreq, struct smbd_smb2_lock_state);
if (!state) {
return;
blr = state->blr;
fsp = blr->fsp;
- /* Try and finish off getting all the outstanding locks. */
-
- for (; blr->lock_num < state->lock_count; blr->lock_num++) {
- struct byte_range_lock *br_lck = NULL;
- struct smbd_lock_element *e = &state->locks[blr->lock_num];
+ /* We can only have one blocked lock in SMB2. */
+ SMB_ASSERT(state->lock_count == 1);
+ SMB_ASSERT(blr->lock_num == 0);
- br_lck = do_lock(smbd_messaging_context(),
- fsp,
- e->smblctx,
- e->count,
- e->offset,
- e->brltype,
- WINDOWS_LOCK,
- true,
- &status,
- &blr->blocking_smblctx,
- blr);
+ /* Try and get the outstanding lock. */
+ e = &state->locks[blr->lock_num];
- TALLOC_FREE(br_lck);
+ br_lck = do_lock(fsp->conn->sconn->msg_ctx,
+ fsp,
+ e->smblctx,
+ e->count,
+ e->offset,
+ e->brltype,
+ WINDOWS_LOCK,
+ true,
+ &status,
+ &blr->blocking_smblctx);
- if (NT_STATUS_IS_ERR(status)) {
- break;
- }
- }
+ TALLOC_FREE(br_lck);
- if(blr->lock_num == state->lock_count) {
+ if (NT_STATUS_IS_OK(status)) {
/*
- * Success - we got all the locks.
+ * Success - we got the lock.
*/
DEBUG(3,("reprocess_blocked_smb2_lock SUCCESS file = %s, "
- "fnum=%d num_locks=%d\n",
+ "%s, num_locks=%d\n",
fsp_str_dbg(fsp),
- fsp->fnum,
+ fsp_fnum_dbg(fsp),
(int)state->lock_count));
+ remove_pending_lock(state, blr);
tevent_req_done(smb2req->subreq);
return;
}
}
/*
- * We couldn't get the locks for this record on the list.
+ * We couldn't get the lock for this record.
* If the time has expired, return a lock error.
*/
}
/*
- * Still can't get all the locks - keep waiting.
+ * Still can't get the lock - keep waiting.
*/
- DEBUG(10,("reprocess_blocked_smb2_lock: only got %d locks of %d needed "
- "for file %s, fnum = %d. Still waiting....\n",
- (int)blr->lock_num,
- (int)state->lock_count,
+ DEBUG(10,("reprocess_blocked_smb2_lock: failed to get lock "
+ "for file %s, %s. Still waiting....\n",
fsp_str_dbg(fsp),
- (int)fsp->fnum));
+ fsp_fnum_dbg(fsp)));
+ SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
return;
-
}
/****************************************************************
the request queue.
*****************************************************************/
-void process_blocking_lock_queue_smb2(struct timeval tv_curr)
+void process_blocking_lock_queue_smb2(
+ struct smbd_server_connection *sconn, struct timeval tv_curr)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
- struct smbd_smb2_request *smb2req, *nextreq;
+ struct smbXsrv_connection *xconn = NULL;
- for (smb2req = sconn->smb2.requests; smb2req; smb2req = nextreq) {
- const uint8_t *inhdr;
+ if (sconn != NULL && sconn->client != NULL) {
+ xconn = sconn->client->connections;
+ }
- nextreq = smb2req->next;
+ for (; xconn != NULL; xconn = xconn->next) {
+ struct smbd_smb2_request *smb2req, *nextreq;
- if (smb2req->subreq == NULL) {
- /* This message has been processed. */
- continue;
- }
- if (!tevent_req_is_in_progress(smb2req->subreq)) {
- /* This message has been processed. */
- continue;
- }
+ for (smb2req = xconn->smb2.requests; smb2req; smb2req = nextreq) {
+ const uint8_t *inhdr;
+
+ nextreq = smb2req->next;
- inhdr = (const uint8_t *)smb2req->in.vector[smb2req->current_idx].iov_base;
- if (SVAL(inhdr, SMB2_HDR_OPCODE) == SMB2_OP_LOCK) {
- reprocess_blocked_smb2_lock(smb2req, tv_curr);
+ if (smb2req->subreq == NULL) {
+ /* This message has been processed. */
+ continue;
+ }
+ if (!tevent_req_is_in_progress(smb2req->subreq)) {
+ /* This message has been processed. */
+ continue;
+ }
+
+ inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
+ if (SVAL(inhdr, SMB2_HDR_OPCODE) == SMB2_OP_LOCK) {
+ reprocess_blocked_smb2_lock(smb2req, tv_curr);
+ }
}
}
struct byte_range_lock *br_lck,
enum file_close_type close_type)
{
- struct smbd_server_connection *sconn = smbd_server_conn;
- struct smbd_smb2_request *smb2req, *nextreq;
-
- for (smb2req = sconn->smb2.requests; smb2req; smb2req = nextreq) {
- struct smbd_smb2_lock_state *state = NULL;
- files_struct *fsp_curr = NULL;
- int i = smb2req->current_idx;
- uint64_t in_file_id_volatile;
- struct blocking_lock_record *blr = NULL;
- const uint8_t *inhdr;
- const uint8_t *inbody;
-
- nextreq = smb2req->next;
-
- if (smb2req->subreq == NULL) {
- /* This message has been processed. */
- continue;
- }
- if (!tevent_req_is_in_progress(smb2req->subreq)) {
- /* This message has been processed. */
- continue;
- }
+ struct smbd_server_connection *sconn = fsp->conn->sconn;
+ struct smbXsrv_connection *xconn = NULL;
- inhdr = (const uint8_t *)smb2req->in.vector[i].iov_base;
- if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_LOCK) {
- /* Not a lock call. */
- continue;
- }
+ if (sconn != NULL && sconn->client != NULL) {
+ xconn = sconn->client->connections;
+ }
- inbody = (const uint8_t *)smb2req->in.vector[i+1].iov_base;
- in_file_id_volatile = BVAL(inbody, 0x10);
+ for (; xconn != NULL; xconn = xconn->next) {
+ struct smbd_smb2_request *smb2req, *nextreq;
- state = tevent_req_data(smb2req->subreq,
- struct smbd_smb2_lock_state);
- if (!state) {
- /* Strange - is this even possible ? */
- continue;
- }
+ for (smb2req = xconn->smb2.requests; smb2req; smb2req = nextreq) {
+ struct smbd_smb2_lock_state *state = NULL;
+ files_struct *fsp_curr = NULL;
+ struct blocking_lock_record *blr = NULL;
+ const uint8_t *inhdr;
- fsp_curr = file_fsp(state->smb1req, (uint16_t)in_file_id_volatile);
- if (fsp_curr == NULL) {
- /* Strange - is this even possible ? */
- continue;
- }
+ nextreq = smb2req->next;
- if (fsp_curr != fsp) {
- /* It's not our fid */
- continue;
- }
+ if (smb2req->subreq == NULL) {
+ /* This message has been processed. */
+ continue;
+ }
+ if (!tevent_req_is_in_progress(smb2req->subreq)) {
+ /* This message has been processed. */
+ continue;
+ }
- blr = state->blr;
+ inhdr = SMBD_SMB2_IN_HDR_PTR(smb2req);
+ if (SVAL(inhdr, SMB2_HDR_OPCODE) != SMB2_OP_LOCK) {
+ /* Not a lock call. */
+ continue;
+ }
- /* Remove the entries from the lock db. */
- brl_lock_cancel(br_lck,
- blr->smblctx,
- procid_self(),
- blr->offset,
- blr->count,
- blr->lock_flav,
- blr);
+ state = tevent_req_data(smb2req->subreq,
+ struct smbd_smb2_lock_state);
+ if (!state) {
+ /* Strange - is this even possible ? */
+ continue;
+ }
- /* Finally end the request. */
- if (close_type == SHUTDOWN_CLOSE) {
- tevent_req_done(smb2req->subreq);
- } else {
- tevent_req_nterror(smb2req->subreq,
- NT_STATUS_RANGE_NOT_LOCKED);
+ fsp_curr = smb2req->compat_chain_fsp;
+ if (fsp_curr == NULL) {
+ /* Strange - is this even possible ? */
+ continue;
+ }
+
+ if (fsp_curr != fsp) {
+ /* It's not our fid */
+ continue;
+ }
+
+ blr = state->blr;
+
+ /* Remove the entries from the lock db. */
+ brl_lock_cancel(br_lck,
+ blr->smblctx,
+ messaging_server_id(sconn->msg_ctx),
+ blr->offset,
+ blr->count,
+ blr->lock_flav);
+
+ /* Finally end the request. */
+ if (close_type == SHUTDOWN_CLOSE) {
+ tevent_req_done(smb2req->subreq);
+ } else {
+ tevent_req_nterror(smb2req->subreq,
+ NT_STATUS_RANGE_NOT_LOCKED);
+ }
}
}
}