a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This file and its contents are supplied under the terms of the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * You may only use this file in accordance with the terms of version
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * 1.0 of the CDDL.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross *
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * A full copy of the text of the CDDL should have accompanied this
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * source. A copy of the CDDL is also available via the Internet at
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * http://www.illumos.org/license/CDDL.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Dispatch function for SMB2_LOCK
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross#include <smbsrv/smb2_kproto.h>
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstruct SMB2_LOCK_ELEMENT {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint64_t Offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint64_t Length;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t Flags;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t reserved;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross};
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic smb_sdrc_t smb2_lock_async(smb_request_t *);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint32_t smb2_lock_exec(smb_request_t *, uint16_t);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint32_t smb2_lock_elem(smb_request_t *, struct SMB2_LOCK_ELEMENT *);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This is a somewhat arbitrary sanity limit on the length of the
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB2_LOCK_ELEMENT array. It usually has length one or two.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossint smb2_lock_max_elem = 1024;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb_sdrc_t
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_lock(smb_request_t *sr)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross struct SMB2_LOCK_ELEMENT elem;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb2fid_t smb2fid;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t save_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t LockSequence;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t status;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t StructSize;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t LockCount;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t i;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross boolean_t MayBlock = B_FALSE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int rc = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB2 Lock request
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_decodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_data, "wwlqq",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &StructSize, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &LockCount, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &LockSequence, /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &smb2fid.persistent, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &smb2fid.temporal); /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc || StructSize != 48)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_ERROR);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2sr_lookup_fid(sr, &smb2fid);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (sr->fid_ofile->f_node == NULL || LockCount == 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INVALID_PARAMETER;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (LockCount > smb2_lock_max_elem) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INSUFFICIENT_RESOURCES;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Process the array of SMB2_LOCK_ELEMENT structs
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * We do this twice. (it's always a short list)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The first time, just validate the flags, and check
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * if any of the locking request might need to block.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * The second time (either here, or in the async
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * handler function) process the locks for real.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross save_offset = sr->smb_data.chain_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross for (i = 0; i < LockCount; i++) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_decodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_data, "qqll",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &elem.Offset, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &elem.Length, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &elem.Flags, /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &elem.reserved); /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INVALID_PARAMETER;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Make sure the flags are valid;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Find out if we might block.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross switch (elem.Flags) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_SHARED_LOCK:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross MayBlock = B_TRUE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* BEGIN CSTYLED */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_SHARED_LOCK |
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_EXCLUSIVE_LOCK |
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_UNLOCK:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* END CSTYLED */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross default:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INVALID_PARAMETER;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (MayBlock) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * May need to block. "Go async".
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2sr_go_async(sr, smb2_lock_async);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross sr->smb_data.chain_offset = save_offset;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2_lock_exec(sr, LockCount);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB2 Lock reply (sync)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross StructSize = 4;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->reply, "w..",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross StructSize); /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* reserved .. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_SUCCESS);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosserrout:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb2sr_put_error(sr, status);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_SUCCESS);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic smb_sdrc_t
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_lock_async(smb_request_t *sr)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb2fid_t smb2fid;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t LockSequence;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t status;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t StructSize;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t LockCount;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int rc = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Decode the lock request again. It should all decode
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * exactly the same as the first time we saw it. If not,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * report an "internal error".
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_decodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_data, "wwlqq",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &StructSize, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &LockCount, /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &LockSequence, /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &smb2fid.persistent, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &smb2fid.temporal); /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc || StructSize != 48)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_ERROR);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2sr_lookup_fid(sr, &smb2fid);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (sr->fid_ofile->f_node == NULL || LockCount == 0) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INTERNAL_ERROR;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2_lock_exec(sr, LockCount);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross goto errout;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * SMB2 Lock reply (async)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross StructSize = 4;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (void) smb_mbc_encodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->reply, "w..",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross StructSize); /* w */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* reserved .. */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_SUCCESS);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosserrout:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb2sr_put_error(sr, status);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (SDRC_SUCCESS);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross/*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * Execute the vector of locks. This is the common function called by
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * either the sync or async code paths. We've already decoded this
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * request once when we get here, so if there are any decode errors
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * then it's some kind of internal error.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint32_t
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_lock_exec(smb_request_t *sr, uint16_t LockCount)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross struct SMB2_LOCK_ELEMENT elem;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t status = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint16_t i;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross int rc;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * On entry, out position in the input data should be
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * after both the SMB2 header and the fixed part of
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * the SMB Lock request header (24).
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ASSERT(sr->smb_data.chain_offset ==
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross (sr->smb2_cmd_hdr + SMB2_HDR_SIZE + 24));
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * This is checked by our callers, but let's make sure.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ASSERT(sr->fid_ofile->f_node != NULL);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross for (i = 0; i < LockCount; i++) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross rc = smb_mbc_decodef(
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &sr->smb_data, "qqll",
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &elem.Offset, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &elem.Length, /* q */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &elem.Flags, /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross &elem.reserved); /* l */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (rc) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INTERNAL_ERROR;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb2_lock_elem(sr, &elem);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross if (status)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (status);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rossstatic uint32_t
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Rosssmb2_lock_elem(smb_request_t *sr, struct SMB2_LOCK_ELEMENT *elem)
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross{
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross smb_node_t *node = sr->fid_ofile->f_node;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t status;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t ltype;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross uint32_t timeout = 0;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross switch (elem->Flags) {
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_SHARED_LOCK:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross timeout = UINT_MAX;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* FALLTHROUGH */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_SHARED_LOCK | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ltype = SMB_LOCK_TYPE_READONLY;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb_lock_range(sr,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross elem->Offset, elem->Length,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross timeout, ltype);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross timeout = UINT_MAX;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /* FALLTHROUGH */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_EXCLUSIVE_LOCK | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross ltype = SMB_LOCK_TYPE_READWRITE;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb_lock_range(sr,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross elem->Offset, elem->Length,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross timeout, ltype);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross case SMB2_LOCKFLAG_UNLOCK:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = smb_unlock_range(sr, node,
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross elem->Offset, elem->Length);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross /*
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * We've already checked the flags previously, so any
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross * surprises here are some kind of internal error.
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross */
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross default:
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross status = NT_STATUS_INTERNAL_ERROR;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross break;
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross }
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross return (status);
a90cf9f29973990687fa61de9f1f6ea22e924e40Gordon Ross}