Commit 31473fc4 authored by Pavel Shilovsky's avatar Pavel Shilovsky Committed by Steve French

CIFS: Separate SMB2 header structure

In order to support compounding and encryption we need to separate
RFC1001 length field and SMB2 header structure because the protocol
treats them differently. This change will allow to simplify parsing
of such complex SMB2 packets further.
Signed-off-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
parent 9c25702c
...@@ -61,4 +61,9 @@ ...@@ -61,4 +61,9 @@
/* Maximum buffer size value we can send with 1 credit */ /* Maximum buffer size value we can send with 1 credit */
#define SMB2_MAX_BUFFER_SIZE 65536 #define SMB2_MAX_BUFFER_SIZE 65536
static inline struct smb2_sync_hdr *get_sync_hdr(void *buf)
{
return &(((struct smb2_hdr *)buf)->sync_hdr);
}
#endif /* _SMB2_GLOB_H */ #endif /* _SMB2_GLOB_H */
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "smb2pdu.h" #include "smb2pdu.h"
#include "smb2proto.h" #include "smb2proto.h"
#include "smb2status.h" #include "smb2status.h"
#include "smb2glob.h"
struct status_to_posix_error { struct status_to_posix_error {
__le32 smb2_status; __le32 smb2_status;
...@@ -2449,10 +2450,10 @@ smb2_print_status(__le32 status) ...@@ -2449,10 +2450,10 @@ smb2_print_status(__le32 status)
int int
map_smb2_to_linux_error(char *buf, bool log_err) map_smb2_to_linux_error(char *buf, bool log_err)
{ {
struct smb2_hdr *hdr = (struct smb2_hdr *)buf; struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
unsigned int i; unsigned int i;
int rc = -EIO; int rc = -EIO;
__le32 smb2err = hdr->Status; __le32 smb2err = shdr->Status;
if (smb2err == 0) if (smb2err == 0)
return 0; return 0;
......
...@@ -28,31 +28,32 @@ ...@@ -28,31 +28,32 @@
#include "cifs_debug.h" #include "cifs_debug.h"
#include "cifs_unicode.h" #include "cifs_unicode.h"
#include "smb2status.h" #include "smb2status.h"
#include "smb2glob.h"
static int static int
check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid) check_smb2_hdr(struct smb2_sync_hdr *shdr, __u64 mid)
{ {
__u64 wire_mid = le64_to_cpu(hdr->MessageId); __u64 wire_mid = le64_to_cpu(shdr->MessageId);
/* /*
* Make sure that this really is an SMB, that it is a response, * Make sure that this really is an SMB, that it is a response,
* and that the message ids match. * and that the message ids match.
*/ */
if ((hdr->ProtocolId == SMB2_PROTO_NUMBER) && if ((shdr->ProtocolId == SMB2_PROTO_NUMBER) &&
(mid == wire_mid)) { (mid == wire_mid)) {
if (hdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR) if (shdr->Flags & SMB2_FLAGS_SERVER_TO_REDIR)
return 0; return 0;
else { else {
/* only one valid case where server sends us request */ /* only one valid case where server sends us request */
if (hdr->Command == SMB2_OPLOCK_BREAK) if (shdr->Command == SMB2_OPLOCK_BREAK)
return 0; return 0;
else else
cifs_dbg(VFS, "Received Request not response\n"); cifs_dbg(VFS, "Received Request not response\n");
} }
} else { /* bad signature or mid */ } else { /* bad signature or mid */
if (hdr->ProtocolId != SMB2_PROTO_NUMBER) if (shdr->ProtocolId != SMB2_PROTO_NUMBER)
cifs_dbg(VFS, "Bad protocol string signature header %x\n", cifs_dbg(VFS, "Bad protocol string signature header %x\n",
le32_to_cpu(hdr->ProtocolId)); le32_to_cpu(shdr->ProtocolId));
if (mid != wire_mid) if (mid != wire_mid)
cifs_dbg(VFS, "Mids do not match: %llu and %llu\n", cifs_dbg(VFS, "Mids do not match: %llu and %llu\n",
mid, wire_mid); mid, wire_mid);
...@@ -95,8 +96,9 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = { ...@@ -95,8 +96,9 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
int int
smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
{ {
struct smb2_hdr *hdr = (struct smb2_hdr *)buf; struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; struct smb2_hdr *hdr = &pdu->hdr;
struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
__u64 mid; __u64 mid;
__u32 len = get_rfc1002_length(buf); __u32 len = get_rfc1002_length(buf);
__u32 clc_len; /* calculated length */ __u32 clc_len; /* calculated length */
...@@ -111,7 +113,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -111,7 +113,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
* ie Validate the wct via smb2_struct_sizes table above * ie Validate the wct via smb2_struct_sizes table above
*/ */
if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
struct smb2_transform_hdr *thdr = struct smb2_transform_hdr *thdr =
(struct smb2_transform_hdr *)buf; (struct smb2_transform_hdr *)buf;
struct cifs_ses *ses = NULL; struct cifs_ses *ses = NULL;
...@@ -133,10 +135,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -133,10 +135,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
} }
} }
mid = le64_to_cpu(shdr->MessageId);
mid = le64_to_cpu(hdr->MessageId);
if (length < sizeof(struct smb2_pdu)) { if (length < sizeof(struct smb2_pdu)) {
if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) { if ((length >= sizeof(struct smb2_hdr))
&& (shdr->Status != 0)) {
pdu->StructureSize2 = 0; pdu->StructureSize2 = 0;
/* /*
* As with SMB/CIFS, on some error cases servers may * As with SMB/CIFS, on some error cases servers may
...@@ -154,29 +156,30 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -154,29 +156,30 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
return 1; return 1;
} }
if (check_smb2_hdr(hdr, mid)) if (check_smb2_hdr(shdr, mid))
return 1; return 1;
if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) { if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
cifs_dbg(VFS, "Illegal structure size %u\n", cifs_dbg(VFS, "Illegal structure size %u\n",
le16_to_cpu(hdr->StructureSize)); le16_to_cpu(shdr->StructureSize));
return 1; return 1;
} }
command = le16_to_cpu(hdr->Command); command = le16_to_cpu(shdr->Command);
if (command >= NUMBER_OF_SMB2_COMMANDS) { if (command >= NUMBER_OF_SMB2_COMMANDS) {
cifs_dbg(VFS, "Illegal SMB2 command %d\n", command); cifs_dbg(VFS, "Illegal SMB2 command %d\n", command);
return 1; return 1;
} }
if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) { if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) {
if (command != SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0 || if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 ||
pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) { pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) {
/* error packets have 9 byte structure size */ /* error packets have 9 byte structure size */
cifs_dbg(VFS, "Illegal response size %u for command %d\n", cifs_dbg(VFS, "Illegal response size %u for command %d\n",
le16_to_cpu(pdu->StructureSize2), command); le16_to_cpu(pdu->StructureSize2), command);
return 1; return 1;
} else if (command == SMB2_OPLOCK_BREAK_HE && (hdr->Status == 0) } else if (command == SMB2_OPLOCK_BREAK_HE
&& (shdr->Status == 0)
&& (le16_to_cpu(pdu->StructureSize2) != 44) && (le16_to_cpu(pdu->StructureSize2) != 44)
&& (le16_to_cpu(pdu->StructureSize2) != 36)) { && (le16_to_cpu(pdu->StructureSize2) != 36)) {
/* special case for SMB2.1 lease break message */ /* special case for SMB2.1 lease break message */
...@@ -199,7 +202,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -199,7 +202,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
clc_len, 4 + len, mid); clc_len, 4 + len, mid);
/* create failed on symlink */ /* create failed on symlink */
if (command == SMB2_CREATE_HE && if (command == SMB2_CREATE_HE &&
hdr->Status == STATUS_STOPPED_ON_SYMLINK) shdr->Status == STATUS_STOPPED_ON_SYMLINK)
return 0; return 0;
/* Windows 7 server returns 24 bytes more */ /* Windows 7 server returns 24 bytes more */
if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE) if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
...@@ -261,11 +264,12 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = { ...@@ -261,11 +264,12 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
char * char *
smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
{ {
struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
*off = 0; *off = 0;
*len = 0; *len = 0;
/* error responses do not have data area */ /* error responses do not have data area */
if (hdr->Status && hdr->Status != STATUS_MORE_PROCESSING_REQUIRED && if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
(((struct smb2_err_rsp *)hdr)->StructureSize) == (((struct smb2_err_rsp *)hdr)->StructureSize) ==
SMB2_ERROR_STRUCTURE_SIZE2) SMB2_ERROR_STRUCTURE_SIZE2)
return NULL; return NULL;
...@@ -275,7 +279,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) ...@@ -275,7 +279,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
* of the data buffer offset and data buffer length for the particular * of the data buffer offset and data buffer length for the particular
* command. * command.
*/ */
switch (hdr->Command) { switch (shdr->Command) {
case SMB2_NEGOTIATE: case SMB2_NEGOTIATE:
*off = le16_to_cpu( *off = le16_to_cpu(
((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset); ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset);
...@@ -346,7 +350,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) ...@@ -346,7 +350,7 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
/* return pointer to beginning of data area, ie offset from SMB start */ /* return pointer to beginning of data area, ie offset from SMB start */
if ((*off != 0) && (*len != 0)) if ((*off != 0) && (*len != 0))
return (char *)(&hdr->ProtocolId) + *off; return (char *)shdr + *off;
else else
return NULL; return NULL;
} }
...@@ -358,12 +362,13 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr) ...@@ -358,12 +362,13 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
unsigned int unsigned int
smb2_calc_size(void *buf) smb2_calc_size(void *buf)
{ {
struct smb2_hdr *hdr = (struct smb2_hdr *)buf; struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; struct smb2_hdr *hdr = &pdu->hdr;
struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
int offset; /* the offset from the beginning of SMB to data area */ int offset; /* the offset from the beginning of SMB to data area */
int data_length; /* the length of the variable length data area */ int data_length; /* the length of the variable length data area */
/* Structure Size has already been checked to make sure it is 64 */ /* Structure Size has already been checked to make sure it is 64 */
int len = 4 + le16_to_cpu(pdu->hdr.StructureSize); int len = 4 + le16_to_cpu(shdr->StructureSize);
/* /*
* StructureSize2, ie length of fixed parameter area has already * StructureSize2, ie length of fixed parameter area has already
...@@ -371,7 +376,7 @@ smb2_calc_size(void *buf) ...@@ -371,7 +376,7 @@ smb2_calc_size(void *buf)
*/ */
len += le16_to_cpu(pdu->StructureSize2); len += le16_to_cpu(pdu->StructureSize2);
if (has_smb2_data_area[le16_to_cpu(hdr->Command)] == false) if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
goto calc_size_exit; goto calc_size_exit;
smb2_get_data_area_len(&offset, &data_length, hdr); smb2_get_data_area_len(&offset, &data_length, hdr);
...@@ -582,7 +587,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) ...@@ -582,7 +587,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg(FYI, "Checking for oplock break\n"); cifs_dbg(FYI, "Checking for oplock break\n");
if (rsp->hdr.Command != SMB2_OPLOCK_BREAK) if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK)
return false; return false;
if (rsp->StructureSize != if (rsp->StructureSize !=
......
...@@ -119,7 +119,9 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype) ...@@ -119,7 +119,9 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
static unsigned int static unsigned int
smb2_get_credits(struct mid_q_entry *mid) smb2_get_credits(struct mid_q_entry *mid)
{ {
return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest); struct smb2_sync_hdr *shdr = get_sync_hdr(mid->resp_buf);
return le16_to_cpu(shdr->CreditRequest);
} }
static int static int
...@@ -184,10 +186,10 @@ static struct mid_q_entry * ...@@ -184,10 +186,10 @@ static struct mid_q_entry *
smb2_find_mid(struct TCP_Server_Info *server, char *buf) smb2_find_mid(struct TCP_Server_Info *server, char *buf)
{ {
struct mid_q_entry *mid; struct mid_q_entry *mid;
struct smb2_hdr *hdr = (struct smb2_hdr *)buf; struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
__u64 wire_mid = le64_to_cpu(hdr->MessageId); __u64 wire_mid = le64_to_cpu(shdr->MessageId);
if (hdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) { if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
cifs_dbg(VFS, "encrypted frame parsing not supported yet"); cifs_dbg(VFS, "encrypted frame parsing not supported yet");
return NULL; return NULL;
} }
...@@ -196,7 +198,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf) ...@@ -196,7 +198,7 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
list_for_each_entry(mid, &server->pending_mid_q, qhead) { list_for_each_entry(mid, &server->pending_mid_q, qhead) {
if ((mid->mid == wire_mid) && if ((mid->mid == wire_mid) &&
(mid->mid_state == MID_REQUEST_SUBMITTED) && (mid->mid_state == MID_REQUEST_SUBMITTED) &&
(mid->command == hdr->Command)) { (mid->command == shdr->Command)) {
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
return mid; return mid;
} }
...@@ -209,12 +211,12 @@ static void ...@@ -209,12 +211,12 @@ static void
smb2_dump_detail(void *buf) smb2_dump_detail(void *buf)
{ {
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
struct smb2_hdr *smb = (struct smb2_hdr *)buf; struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n", cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
smb->Command, smb->Status, smb->Flags, smb->MessageId, shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
smb->ProcessId); shdr->ProcessId);
cifs_dbg(VFS, "smb buf %p len %u\n", smb, smb2_calc_size(smb)); cifs_dbg(VFS, "smb buf %p len %u\n", buf, smb2_calc_size(buf));
#endif #endif
} }
...@@ -1002,14 +1004,14 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -1002,14 +1004,14 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
static bool static bool
smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length) smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
{ {
struct smb2_hdr *hdr = (struct smb2_hdr *)buf; struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
if (hdr->Status != STATUS_PENDING) if (shdr->Status != STATUS_PENDING)
return false; return false;
if (!length) { if (!length) {
spin_lock(&server->req_lock); spin_lock(&server->req_lock);
server->credits += le16_to_cpu(hdr->CreditRequest); server->credits += le16_to_cpu(shdr->CreditRequest);
spin_unlock(&server->req_lock); spin_unlock(&server->req_lock);
wake_up(&server->request_q); wake_up(&server->request_q);
} }
......
...@@ -83,6 +83,7 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , ...@@ -83,6 +83,7 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
const struct cifs_tcon *tcon) const struct cifs_tcon *tcon)
{ {
struct smb2_pdu *pdu = (struct smb2_pdu *)hdr; struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
char *temp = (char *)hdr; char *temp = (char *)hdr;
/* lookup word count ie StructureSize from table */ /* lookup word count ie StructureSize from table */
__u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_cmd)]; __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_cmd)];
...@@ -94,28 +95,28 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , ...@@ -94,28 +95,28 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
memset(temp, 0, 256); memset(temp, 0, 256);
/* Note this is only network field converted to big endian */ /* Note this is only network field converted to big endian */
hdr->smb2_buf_length = cpu_to_be32(parmsize + sizeof(struct smb2_hdr) hdr->smb2_buf_length =
- 4 /* RFC 1001 length field itself not counted */); cpu_to_be32(parmsize + sizeof(struct smb2_sync_hdr));
hdr->ProtocolId = SMB2_PROTO_NUMBER; shdr->ProtocolId = SMB2_PROTO_NUMBER;
hdr->StructureSize = cpu_to_le16(64); shdr->StructureSize = cpu_to_le16(64);
hdr->Command = smb2_cmd; shdr->Command = smb2_cmd;
if (tcon && tcon->ses && tcon->ses->server) { if (tcon && tcon->ses && tcon->ses->server) {
struct TCP_Server_Info *server = tcon->ses->server; struct TCP_Server_Info *server = tcon->ses->server;
spin_lock(&server->req_lock); spin_lock(&server->req_lock);
/* Request up to 2 credits but don't go over the limit. */ /* Request up to 2 credits but don't go over the limit. */
if (server->credits >= server->max_credits) if (server->credits >= server->max_credits)
hdr->CreditRequest = cpu_to_le16(0); shdr->CreditRequest = cpu_to_le16(0);
else else
hdr->CreditRequest = cpu_to_le16( shdr->CreditRequest = cpu_to_le16(
min_t(int, server->max_credits - min_t(int, server->max_credits -
server->credits, 2)); server->credits, 2));
spin_unlock(&server->req_lock); spin_unlock(&server->req_lock);
} else { } else {
hdr->CreditRequest = cpu_to_le16(2); shdr->CreditRequest = cpu_to_le16(2);
} }
hdr->ProcessId = cpu_to_le32((__u16)current->tgid); shdr->ProcessId = cpu_to_le32((__u16)current->tgid);
if (!tcon) if (!tcon)
goto out; goto out;
...@@ -124,13 +125,13 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , ...@@ -124,13 +125,13 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
/* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */ /* See sections 2.2.4 and 3.2.4.1.5 of MS-SMB2 */
if ((tcon->ses) && (tcon->ses->server) && if ((tcon->ses) && (tcon->ses->server) &&
(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU)) (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
hdr->CreditCharge = cpu_to_le16(1); shdr->CreditCharge = cpu_to_le16(1);
/* else CreditCharge MBZ */ /* else CreditCharge MBZ */
hdr->TreeId = tcon->tid; shdr->TreeId = tcon->tid;
/* Uid is not converted */ /* Uid is not converted */
if (tcon->ses) if (tcon->ses)
hdr->SessionId = tcon->ses->Suid; shdr->SessionId = tcon->ses->Suid;
/* /*
* If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have * If we would set SMB2_FLAGS_DFS_OPERATIONS on open we also would have
...@@ -143,10 +144,10 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ , ...@@ -143,10 +144,10 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
* but it is safer to net set it for now. * but it is safer to net set it for now.
*/ */
/* if (tcon->share_flags & SHI1005_FLAGS_DFS) /* if (tcon->share_flags & SHI1005_FLAGS_DFS)
hdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */ shdr->Flags |= SMB2_FLAGS_DFS_OPERATIONS; */
if (tcon->ses && tcon->ses->server && tcon->ses->server->sign) if (tcon->ses && tcon->ses->server && tcon->ses->server->sign)
hdr->Flags |= SMB2_FLAGS_SIGNED; shdr->Flags |= SMB2_FLAGS_SIGNED;
out: out:
pdu->StructureSize2 = cpu_to_le16(parmsize); pdu->StructureSize2 = cpu_to_le16(parmsize);
return; return;
...@@ -416,7 +417,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) ...@@ -416,7 +417,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
if (rc) if (rc)
return rc; return rc;
req->hdr.SessionId = 0; req->hdr.sync_hdr.SessionId = 0;
req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id); req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id);
...@@ -627,14 +628,15 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data) ...@@ -627,14 +628,15 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
if (rc) if (rc)
return rc; return rc;
req->hdr.SessionId = 0; /* First session, not a reauthenticate */ /* First session, not a reauthenticate */
req->hdr.sync_hdr.SessionId = 0;
/* if reconnect, we need to send previous sess id, otherwise it is 0 */ /* if reconnect, we need to send previous sess id, otherwise it is 0 */
req->PreviousSessionId = sess_data->previous_session; req->PreviousSessionId = sess_data->previous_session;
req->Flags = 0; /* MBZ */ req->Flags = 0; /* MBZ */
/* to enable echos and oplocks */ /* to enable echos and oplocks */
req->hdr.CreditRequest = cpu_to_le16(3); req->hdr.sync_hdr.CreditRequest = cpu_to_le16(3);
/* only one of SMB2 signing flags may be set in SMB2 request */ /* only one of SMB2 signing flags may be set in SMB2 request */
if (server->sign) if (server->sign)
...@@ -781,7 +783,7 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) ...@@ -781,7 +783,7 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
goto out_put_spnego_key; goto out_put_spnego_key;
rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
ses->Suid = rsp->hdr.SessionId; ses->Suid = rsp->hdr.sync_hdr.SessionId;
ses->session_flags = le16_to_cpu(rsp->SessionFlags); ses->session_flags = le16_to_cpu(rsp->SessionFlags);
if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
...@@ -859,7 +861,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) ...@@ -859,7 +861,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
/* If true, rc here is expected and not an error */ /* If true, rc here is expected and not an error */
if (sess_data->buf0_type != CIFS_NO_BUFFER && if (sess_data->buf0_type != CIFS_NO_BUFFER &&
rsp->hdr.Status == STATUS_MORE_PROCESSING_REQUIRED) rsp->hdr.sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
rc = 0; rc = 0;
if (rc) if (rc)
...@@ -880,7 +882,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data) ...@@ -880,7 +882,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n"); cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
ses->Suid = rsp->hdr.SessionId; ses->Suid = rsp->hdr.sync_hdr.SessionId;
ses->session_flags = le16_to_cpu(rsp->SessionFlags); ses->session_flags = le16_to_cpu(rsp->SessionFlags);
if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); cifs_dbg(VFS, "SMB3 encryption not supported yet\n");
...@@ -916,7 +918,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) ...@@ -916,7 +918,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
goto out; goto out;
req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base; req = (struct smb2_sess_setup_req *) sess_data->iov[0].iov_base;
req->hdr.SessionId = ses->Suid; req->hdr.sync_hdr.SessionId = ses->Suid;
rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses, rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses,
sess_data->nls_cp); sess_data->nls_cp);
...@@ -940,7 +942,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data) ...@@ -940,7 +942,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base; rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
ses->Suid = rsp->hdr.SessionId; ses->Suid = rsp->hdr.sync_hdr.SessionId;
ses->session_flags = le16_to_cpu(rsp->SessionFlags); ses->session_flags = le16_to_cpu(rsp->SessionFlags);
if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
cifs_dbg(VFS, "SMB3 encryption not supported yet\n"); cifs_dbg(VFS, "SMB3 encryption not supported yet\n");
...@@ -1035,9 +1037,9 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses) ...@@ -1035,9 +1037,9 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
return rc; return rc;
/* since no tcon, smb2_init can not do this, so do here */ /* since no tcon, smb2_init can not do this, so do here */
req->hdr.SessionId = ses->Suid; req->hdr.sync_hdr.SessionId = ses->Suid;
if (server->sign) if (server->sign)
req->hdr.Flags |= SMB2_FLAGS_SIGNED; req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
rc = SendReceiveNoRsp(xid, ses, (char *) &req->hdr, 0); rc = SendReceiveNoRsp(xid, ses, (char *) &req->hdr, 0);
/* /*
...@@ -1112,7 +1114,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, ...@@ -1112,7 +1114,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
if (tcon == NULL) { if (tcon == NULL) {
/* since no tcon, smb2_init can not do this, so do here */ /* since no tcon, smb2_init can not do this, so do here */
req->hdr.SessionId = ses->Suid; req->hdr.sync_hdr.SessionId = ses->Suid;
/* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED) /* if (ses->server->sec_mode & SECMODE_SIGN_REQUIRED)
req->hdr.Flags |= SMB2_FLAGS_SIGNED; */ req->hdr.Flags |= SMB2_FLAGS_SIGNED; */
} }
...@@ -1142,7 +1144,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, ...@@ -1142,7 +1144,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
} }
if (tcon == NULL) { if (tcon == NULL) {
ses->ipc_tid = rsp->hdr.TreeId; ses->ipc_tid = rsp->hdr.sync_hdr.TreeId;
goto tcon_exit; goto tcon_exit;
} }
...@@ -1165,7 +1167,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, ...@@ -1165,7 +1167,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
tcon->tidStatus = CifsGood; tcon->tidStatus = CifsGood;
tcon->need_reconnect = false; tcon->need_reconnect = false;
tcon->tid = rsp->hdr.TreeId; tcon->tid = rsp->hdr.sync_hdr.TreeId;
strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) && if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
...@@ -1182,7 +1184,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, ...@@ -1182,7 +1184,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
return rc; return rc;
tcon_error_exit: tcon_error_exit:
if (rsp->hdr.Status == STATUS_BAD_NETWORK_NAME) { if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree); cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
if (tcon) if (tcon)
tcon->bad_network_name = true; tcon->bad_network_name = true;
...@@ -1618,6 +1620,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, ...@@ -1618,6 +1620,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
{ {
struct smb2_ioctl_req *req; struct smb2_ioctl_req *req;
struct smb2_ioctl_rsp *rsp; struct smb2_ioctl_rsp *rsp;
struct smb2_sync_hdr *shdr;
struct TCP_Server_Info *server; struct TCP_Server_Info *server;
struct cifs_ses *ses; struct cifs_ses *ses;
struct kvec iov[2]; struct kvec iov[2];
...@@ -1742,9 +1745,8 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, ...@@ -1742,9 +1745,8 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
goto ioctl_exit; goto ioctl_exit;
} }
memcpy(*out_data, shdr = get_sync_hdr(rsp);
(char *)&rsp->hdr.ProtocolId + le32_to_cpu(rsp->OutputOffset), memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen);
*plen);
ioctl_exit: ioctl_exit:
free_rsp_buf(resp_buftype, rsp); free_rsp_buf(resp_buftype, rsp);
return rc; return rc;
...@@ -1963,11 +1965,11 @@ static void ...@@ -1963,11 +1965,11 @@ static void
smb2_echo_callback(struct mid_q_entry *mid) smb2_echo_callback(struct mid_q_entry *mid)
{ {
struct TCP_Server_Info *server = mid->callback_data; struct TCP_Server_Info *server = mid->callback_data;
struct smb2_echo_rsp *smb2 = (struct smb2_echo_rsp *)mid->resp_buf; struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
unsigned int credits_received = 1; unsigned int credits_received = 1;
if (mid->mid_state == MID_RESPONSE_RECEIVED) if (mid->mid_state == MID_RESPONSE_RECEIVED)
credits_received = le16_to_cpu(smb2->hdr.CreditRequest); credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
mutex_lock(&server->srv_mutex); mutex_lock(&server->srv_mutex);
DeleteMidQEntry(mid); DeleteMidQEntry(mid);
...@@ -2045,7 +2047,7 @@ SMB2_echo(struct TCP_Server_Info *server) ...@@ -2045,7 +2047,7 @@ SMB2_echo(struct TCP_Server_Info *server)
if (rc) if (rc)
return rc; return rc;
req->hdr.CreditRequest = cpu_to_le16(1); req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1);
iov.iov_base = (char *)req; iov.iov_base = (char *)req;
/* 4 for rfc1002 length field */ /* 4 for rfc1002 length field */
...@@ -2108,6 +2110,7 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, ...@@ -2108,6 +2110,7 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms,
{ {
int rc = -EACCES; int rc = -EACCES;
struct smb2_read_req *req = NULL; struct smb2_read_req *req = NULL;
struct smb2_sync_hdr *shdr;
rc = small_smb2_init(SMB2_READ, io_parms->tcon, (void **) &req); rc = small_smb2_init(SMB2_READ, io_parms->tcon, (void **) &req);
if (rc) if (rc)
...@@ -2115,7 +2118,8 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, ...@@ -2115,7 +2118,8 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms,
if (io_parms->tcon->ses->server == NULL) if (io_parms->tcon->ses->server == NULL)
return -ECONNABORTED; return -ECONNABORTED;
req->hdr.ProcessId = cpu_to_le32(io_parms->pid); shdr = get_sync_hdr(req);
shdr->ProcessId = cpu_to_le32(io_parms->pid);
req->PersistentFileId = io_parms->persistent_fid; req->PersistentFileId = io_parms->persistent_fid;
req->VolatileFileId = io_parms->volatile_fid; req->VolatileFileId = io_parms->volatile_fid;
...@@ -2129,18 +2133,18 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms, ...@@ -2129,18 +2133,18 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms,
if (request_type & CHAINED_REQUEST) { if (request_type & CHAINED_REQUEST) {
if (!(request_type & END_OF_CHAIN)) { if (!(request_type & END_OF_CHAIN)) {
/* 4 for rfc1002 length field */ /* 4 for rfc1002 length field */
req->hdr.NextCommand = shdr->NextCommand =
cpu_to_le32(get_rfc1002_length(req) + 4); cpu_to_le32(get_rfc1002_length(req) + 4);
} else /* END_OF_CHAIN */ } else /* END_OF_CHAIN */
req->hdr.NextCommand = 0; shdr->NextCommand = 0;
if (request_type & RELATED_REQUEST) { if (request_type & RELATED_REQUEST) {
req->hdr.Flags |= SMB2_FLAGS_RELATED_OPERATIONS; shdr->Flags |= SMB2_FLAGS_RELATED_OPERATIONS;
/* /*
* Related requests use info from previous read request * Related requests use info from previous read request
* in chain. * in chain.
*/ */
req->hdr.SessionId = 0xFFFFFFFF; shdr->SessionId = 0xFFFFFFFF;
req->hdr.TreeId = 0xFFFFFFFF; shdr->TreeId = 0xFFFFFFFF;
req->PersistentFileId = 0xFFFFFFFF; req->PersistentFileId = 0xFFFFFFFF;
req->VolatileFileId = 0xFFFFFFFF; req->VolatileFileId = 0xFFFFFFFF;
} }
...@@ -2162,7 +2166,7 @@ smb2_readv_callback(struct mid_q_entry *mid) ...@@ -2162,7 +2166,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
struct cifs_readdata *rdata = mid->callback_data; struct cifs_readdata *rdata = mid->callback_data;
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
struct TCP_Server_Info *server = tcon->ses->server; struct TCP_Server_Info *server = tcon->ses->server;
struct smb2_hdr *buf = (struct smb2_hdr *)rdata->iov.iov_base; struct smb2_sync_hdr *shdr = get_sync_hdr(rdata->iov.iov_base);
unsigned int credits_received = 1; unsigned int credits_received = 1;
struct smb_rqst rqst = { .rq_iov = &rdata->iov, struct smb_rqst rqst = { .rq_iov = &rdata->iov,
.rq_nvec = 1, .rq_nvec = 1,
...@@ -2177,7 +2181,7 @@ smb2_readv_callback(struct mid_q_entry *mid) ...@@ -2177,7 +2181,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
switch (mid->mid_state) { switch (mid->mid_state) {
case MID_RESPONSE_RECEIVED: case MID_RESPONSE_RECEIVED:
credits_received = le16_to_cpu(buf->CreditRequest); credits_received = le16_to_cpu(shdr->CreditRequest);
/* result already set, check signature */ /* result already set, check signature */
if (server->sign) { if (server->sign) {
int rc; int rc;
...@@ -2221,7 +2225,8 @@ int ...@@ -2221,7 +2225,8 @@ int
smb2_async_readv(struct cifs_readdata *rdata) smb2_async_readv(struct cifs_readdata *rdata)
{ {
int rc, flags = 0; int rc, flags = 0;
struct smb2_hdr *buf; char *buf;
struct smb2_sync_hdr *shdr;
struct cifs_io_parms io_parms; struct cifs_io_parms io_parms;
struct smb_rqst rqst = { .rq_iov = &rdata->iov, struct smb_rqst rqst = { .rq_iov = &rdata->iov,
.rq_nvec = 1 }; .rq_nvec = 1 };
...@@ -2252,17 +2257,18 @@ smb2_async_readv(struct cifs_readdata *rdata) ...@@ -2252,17 +2257,18 @@ smb2_async_readv(struct cifs_readdata *rdata)
return rc; return rc;
} }
buf = (struct smb2_hdr *)rdata->iov.iov_base; buf = rdata->iov.iov_base;
shdr = get_sync_hdr(buf);
/* 4 for rfc1002 length field */ /* 4 for rfc1002 length field */
rdata->iov.iov_len = get_rfc1002_length(rdata->iov.iov_base) + 4; rdata->iov.iov_len = get_rfc1002_length(rdata->iov.iov_base) + 4;
if (rdata->credits) { if (rdata->credits) {
buf->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes, shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
SMB2_MAX_BUFFER_SIZE)); SMB2_MAX_BUFFER_SIZE));
buf->CreditRequest = buf->CreditCharge; shdr->CreditRequest = shdr->CreditCharge;
spin_lock(&server->req_lock); spin_lock(&server->req_lock);
server->credits += rdata->credits - server->credits += rdata->credits -
le16_to_cpu(buf->CreditCharge); le16_to_cpu(shdr->CreditCharge);
spin_unlock(&server->req_lock); spin_unlock(&server->req_lock);
wake_up(&server->request_q); wake_up(&server->request_q);
flags = CIFS_HAS_CREDITS; flags = CIFS_HAS_CREDITS;
...@@ -2287,6 +2293,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, ...@@ -2287,6 +2293,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
{ {
int resp_buftype, rc = -EACCES; int resp_buftype, rc = -EACCES;
struct smb2_read_rsp *rsp = NULL; struct smb2_read_rsp *rsp = NULL;
struct smb2_sync_hdr *shdr;
struct kvec iov[1]; struct kvec iov[1];
*nbytes = 0; *nbytes = 0;
...@@ -2298,8 +2305,9 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, ...@@ -2298,8 +2305,9 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
&resp_buftype, CIFS_LOG_ERROR); &resp_buftype, CIFS_LOG_ERROR);
rsp = (struct smb2_read_rsp *)iov[0].iov_base; rsp = (struct smb2_read_rsp *)iov[0].iov_base;
shdr = get_sync_hdr(rsp);
if (rsp->hdr.Status == STATUS_END_OF_FILE) { if (shdr->Status == STATUS_END_OF_FILE) {
free_rsp_buf(resp_buftype, iov[0].iov_base); free_rsp_buf(resp_buftype, iov[0].iov_base);
return 0; return 0;
} }
...@@ -2319,8 +2327,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms, ...@@ -2319,8 +2327,7 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
} }
if (*buf) { if (*buf) {
memcpy(*buf, (char *)&rsp->hdr.ProtocolId + rsp->DataOffset, memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes);
*nbytes);
free_rsp_buf(resp_buftype, iov[0].iov_base); free_rsp_buf(resp_buftype, iov[0].iov_base);
} else if (resp_buftype != CIFS_NO_BUFFER) { } else if (resp_buftype != CIFS_NO_BUFFER) {
*buf = iov[0].iov_base; *buf = iov[0].iov_base;
...@@ -2348,7 +2355,7 @@ smb2_writev_callback(struct mid_q_entry *mid) ...@@ -2348,7 +2355,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
switch (mid->mid_state) { switch (mid->mid_state) {
case MID_RESPONSE_RECEIVED: case MID_RESPONSE_RECEIVED:
credits_received = le16_to_cpu(rsp->hdr.CreditRequest); credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
wdata->result = smb2_check_receive(mid, tcon->ses->server, 0); wdata->result = smb2_check_receive(mid, tcon->ses->server, 0);
if (wdata->result != 0) if (wdata->result != 0)
break; break;
...@@ -2394,6 +2401,7 @@ smb2_async_writev(struct cifs_writedata *wdata, ...@@ -2394,6 +2401,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
{ {
int rc = -EACCES, flags = 0; int rc = -EACCES, flags = 0;
struct smb2_write_req *req = NULL; struct smb2_write_req *req = NULL;
struct smb2_sync_hdr *shdr;
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
struct TCP_Server_Info *server = tcon->ses->server; struct TCP_Server_Info *server = tcon->ses->server;
struct kvec iov; struct kvec iov;
...@@ -2412,7 +2420,8 @@ smb2_async_writev(struct cifs_writedata *wdata, ...@@ -2412,7 +2420,8 @@ smb2_async_writev(struct cifs_writedata *wdata,
goto async_writev_out; goto async_writev_out;
} }
req->hdr.ProcessId = cpu_to_le32(wdata->cfile->pid); shdr = get_sync_hdr(req);
shdr->ProcessId = cpu_to_le32(wdata->cfile->pid);
req->PersistentFileId = wdata->cfile->fid.persistent_fid; req->PersistentFileId = wdata->cfile->fid.persistent_fid;
req->VolatileFileId = wdata->cfile->fid.volatile_fid; req->VolatileFileId = wdata->cfile->fid.volatile_fid;
...@@ -2444,12 +2453,12 @@ smb2_async_writev(struct cifs_writedata *wdata, ...@@ -2444,12 +2453,12 @@ smb2_async_writev(struct cifs_writedata *wdata,
inc_rfc1001_len(&req->hdr, wdata->bytes - 1 /* Buffer */); inc_rfc1001_len(&req->hdr, wdata->bytes - 1 /* Buffer */);
if (wdata->credits) { if (wdata->credits) {
req->hdr.CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes, shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
SMB2_MAX_BUFFER_SIZE)); SMB2_MAX_BUFFER_SIZE));
req->hdr.CreditRequest = req->hdr.CreditCharge; shdr->CreditRequest = shdr->CreditCharge;
spin_lock(&server->req_lock); spin_lock(&server->req_lock);
server->credits += wdata->credits - server->credits += wdata->credits -
le16_to_cpu(req->hdr.CreditCharge); le16_to_cpu(shdr->CreditCharge);
spin_unlock(&server->req_lock); spin_unlock(&server->req_lock);
wake_up(&server->request_q); wake_up(&server->request_q);
flags = CIFS_HAS_CREDITS; flags = CIFS_HAS_CREDITS;
...@@ -2495,7 +2504,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, ...@@ -2495,7 +2504,7 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
if (io_parms->tcon->ses->server == NULL) if (io_parms->tcon->ses->server == NULL)
return -ECONNABORTED; return -ECONNABORTED;
req->hdr.ProcessId = cpu_to_le32(io_parms->pid); req->hdr.sync_hdr.ProcessId = cpu_to_le32(io_parms->pid);
req->PersistentFileId = io_parms->persistent_fid; req->PersistentFileId = io_parms->persistent_fid;
req->VolatileFileId = io_parms->volatile_fid; req->VolatileFileId = io_parms->volatile_fid;
...@@ -2649,7 +2658,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2649,7 +2658,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base; rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base;
if (rc) { if (rc) {
if (rc == -ENODATA && rsp->hdr.Status == STATUS_NO_MORE_FILES) { if (rc == -ENODATA &&
rsp->hdr.sync_hdr.Status == STATUS_NO_MORE_FILES) {
srch_inf->endOfSearch = true; srch_inf->endOfSearch = true;
rc = 0; rc = 0;
} }
...@@ -2729,7 +2739,7 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2729,7 +2739,7 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
return rc; return rc;
} }
req->hdr.ProcessId = cpu_to_le32(pid); req->hdr.sync_hdr.ProcessId = cpu_to_le32(pid);
req->InfoType = SMB2_O_INFO_FILE; req->InfoType = SMB2_O_INFO_FILE;
req->FileInfoClass = info_class; req->FileInfoClass = info_class;
...@@ -2895,7 +2905,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -2895,7 +2905,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
req->VolatileFid = volatile_fid; req->VolatileFid = volatile_fid;
req->PersistentFid = persistent_fid; req->PersistentFid = persistent_fid;
req->OplockLevel = oplock_level; req->OplockLevel = oplock_level;
req->hdr.CreditRequest = cpu_to_le16(1); req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1);
rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, CIFS_OBREAK_OP); rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, CIFS_OBREAK_OP);
/* SMB2 buffer freed by function above */ /* SMB2 buffer freed by function above */
...@@ -3069,7 +3079,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3069,7 +3079,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
if (rc) if (rc)
return rc; return rc;
req->hdr.ProcessId = cpu_to_le32(pid); req->hdr.sync_hdr.ProcessId = cpu_to_le32(pid);
req->LockCount = cpu_to_le16(num_lock); req->LockCount = cpu_to_le16(num_lock);
req->PersistentFileId = persist_fid; req->PersistentFileId = persist_fid;
...@@ -3124,7 +3134,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3124,7 +3134,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
if (rc) if (rc)
return rc; return rc;
req->hdr.CreditRequest = cpu_to_le16(1); req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1);
req->StructureSize = cpu_to_le16(36); req->StructureSize = cpu_to_le16(36);
inc_rfc1001_len(req, 12); inc_rfc1001_len(req, 12);
......
...@@ -101,10 +101,7 @@ ...@@ -101,10 +101,7 @@
#define SMB2_HEADER_STRUCTURE_SIZE cpu_to_le16(64) #define SMB2_HEADER_STRUCTURE_SIZE cpu_to_le16(64)
struct smb2_hdr { struct smb2_sync_hdr {
__be32 smb2_buf_length; /* big endian on wire */
/* length is only two or three bytes - with
one or two byte type preceding it that MBZ */
__le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */ __le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */
__le16 StructureSize; /* 64 */ __le16 StructureSize; /* 64 */
__le16 CreditCharge; /* MBZ */ __le16 CreditCharge; /* MBZ */
...@@ -120,6 +117,13 @@ struct smb2_hdr { ...@@ -120,6 +117,13 @@ struct smb2_hdr {
__u8 Signature[16]; __u8 Signature[16];
} __packed; } __packed;
struct smb2_hdr {
__be32 smb2_buf_length; /* big endian on wire */
/* length is only two or three bytes - with */
/* one or two byte type preceding it that MBZ */
struct smb2_sync_hdr sync_hdr;
} __packed;
struct smb2_pdu { struct smb2_pdu {
struct smb2_hdr hdr; struct smb2_hdr hdr;
__le16 StructureSize2; /* size of wct area (varies, request specific) */ __le16 StructureSize2; /* size of wct area (varies, request specific) */
......
...@@ -115,13 +115,13 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server) ...@@ -115,13 +115,13 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
} }
static struct cifs_ses * static struct cifs_ses *
smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) smb2_find_smb_ses(struct smb2_sync_hdr *shdr, struct TCP_Server_Info *server)
{ {
struct cifs_ses *ses; struct cifs_ses *ses;
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
if (ses->Suid != smb2hdr->SessionId) if (ses->Suid != shdr->SessionId)
continue; continue;
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
return ses; return ses;
...@@ -131,7 +131,6 @@ smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server) ...@@ -131,7 +131,6 @@ smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server)
return NULL; return NULL;
} }
int int
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
{ {
...@@ -139,17 +138,17 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -139,17 +138,17 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
unsigned char *sigptr = smb2_signature; unsigned char *sigptr = smb2_signature;
struct kvec *iov = rqst->rq_iov; struct kvec *iov = rqst->rq_iov;
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; struct smb2_sync_hdr *shdr = get_sync_hdr(iov[0].iov_base);
struct cifs_ses *ses; struct cifs_ses *ses;
ses = smb2_find_smb_ses(smb2_pdu, server); ses = smb2_find_smb_ses(shdr, server);
if (!ses) { if (!ses) {
cifs_dbg(VFS, "%s: Could not find session\n", __func__); cifs_dbg(VFS, "%s: Could not find session\n", __func__);
return 0; return 0;
} }
memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE);
memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
rc = smb2_crypto_shash_allocate(server); rc = smb2_crypto_shash_allocate(server);
if (rc) { if (rc) {
...@@ -174,7 +173,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -174,7 +173,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
&server->secmech.sdeschmacsha256->shash); &server->secmech.sdeschmacsha256->shash);
if (!rc) if (!rc)
memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
return rc; return rc;
} }
...@@ -356,17 +355,17 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -356,17 +355,17 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
unsigned char smb3_signature[SMB2_CMACAES_SIZE]; unsigned char smb3_signature[SMB2_CMACAES_SIZE];
unsigned char *sigptr = smb3_signature; unsigned char *sigptr = smb3_signature;
struct kvec *iov = rqst->rq_iov; struct kvec *iov = rqst->rq_iov;
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base; struct smb2_sync_hdr *shdr = get_sync_hdr(iov[0].iov_base);
struct cifs_ses *ses; struct cifs_ses *ses;
ses = smb2_find_smb_ses(smb2_pdu, server); ses = smb2_find_smb_ses(shdr, server);
if (!ses) { if (!ses) {
cifs_dbg(VFS, "%s: Could not find session\n", __func__); cifs_dbg(VFS, "%s: Could not find session\n", __func__);
return 0; return 0;
} }
memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE); memset(smb3_signature, 0x0, SMB2_CMACAES_SIZE);
memset(smb2_pdu->Signature, 0x0, SMB2_SIGNATURE_SIZE); memset(shdr->Signature, 0x0, SMB2_SIGNATURE_SIZE);
rc = crypto_shash_setkey(server->secmech.cmacaes, rc = crypto_shash_setkey(server->secmech.cmacaes,
ses->smb3signingkey, SMB2_CMACAES_SIZE); ses->smb3signingkey, SMB2_CMACAES_SIZE);
...@@ -391,7 +390,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -391,7 +390,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
&server->secmech.sdesccmacaes->shash); &server->secmech.sdesccmacaes->shash);
if (!rc) if (!rc)
memcpy(smb2_pdu->Signature, sigptr, SMB2_SIGNATURE_SIZE); memcpy(shdr->Signature, sigptr, SMB2_SIGNATURE_SIZE);
return rc; return rc;
} }
...@@ -401,14 +400,14 @@ static int ...@@ -401,14 +400,14 @@ static int
smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
{ {
int rc = 0; int rc = 0;
struct smb2_hdr *smb2_pdu = rqst->rq_iov[0].iov_base; struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base);
if (!(smb2_pdu->Flags & SMB2_FLAGS_SIGNED) || if (!(shdr->Flags & SMB2_FLAGS_SIGNED) ||
server->tcpStatus == CifsNeedNegotiate) server->tcpStatus == CifsNeedNegotiate)
return rc; return rc;
if (!server->session_estab) { if (!server->session_estab) {
strncpy(smb2_pdu->Signature, "BSRSPYL", 8); strncpy(shdr->Signature, "BSRSPYL", 8);
return rc; return rc;
} }
...@@ -422,11 +421,11 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -422,11 +421,11 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
{ {
unsigned int rc; unsigned int rc;
char server_response_sig[16]; char server_response_sig[16];
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base);
if ((smb2_pdu->Command == SMB2_NEGOTIATE) || if ((shdr->Command == SMB2_NEGOTIATE) ||
(smb2_pdu->Command == SMB2_SESSION_SETUP) || (shdr->Command == SMB2_SESSION_SETUP) ||
(smb2_pdu->Command == SMB2_OPLOCK_BREAK) || (shdr->Command == SMB2_OPLOCK_BREAK) ||
(!server->session_estab)) (!server->session_estab))
return 0; return 0;
...@@ -436,17 +435,17 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -436,17 +435,17 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
*/ */
/* Do not need to verify session setups with signature "BSRSPYL " */ /* Do not need to verify session setups with signature "BSRSPYL " */
if (memcmp(smb2_pdu->Signature, "BSRSPYL ", 8) == 0) if (memcmp(shdr->Signature, "BSRSPYL ", 8) == 0)
cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n", cifs_dbg(FYI, "dummy signature received for smb command 0x%x\n",
smb2_pdu->Command); shdr->Command);
/* /*
* Save off the origiginal signature so we can modify the smb and check * Save off the origiginal signature so we can modify the smb and check
* our calculated signature against what the server sent. * our calculated signature against what the server sent.
*/ */
memcpy(server_response_sig, smb2_pdu->Signature, SMB2_SIGNATURE_SIZE); memcpy(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE);
memset(smb2_pdu->Signature, 0, SMB2_SIGNATURE_SIZE); memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE);
mutex_lock(&server->srv_mutex); mutex_lock(&server->srv_mutex);
rc = server->ops->calc_signature(rqst, server); rc = server->ops->calc_signature(rqst, server);
...@@ -455,8 +454,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -455,8 +454,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
if (rc) if (rc)
return rc; return rc;
if (memcmp(server_response_sig, smb2_pdu->Signature, if (memcmp(server_response_sig, shdr->Signature, SMB2_SIGNATURE_SIZE))
SMB2_SIGNATURE_SIZE))
return -EACCES; return -EACCES;
else else
return 0; return 0;
...@@ -467,18 +465,19 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) ...@@ -467,18 +465,19 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
* and when srv_mutex is held. * and when srv_mutex is held.
*/ */
static inline void static inline void
smb2_seq_num_into_buf(struct TCP_Server_Info *server, struct smb2_hdr *hdr) smb2_seq_num_into_buf(struct TCP_Server_Info *server,
struct smb2_sync_hdr *shdr)
{ {
unsigned int i, num = le16_to_cpu(hdr->CreditCharge); unsigned int i, num = le16_to_cpu(shdr->CreditCharge);
hdr->MessageId = get_next_mid64(server); shdr->MessageId = get_next_mid64(server);
/* skip message numbers according to CreditCharge field */ /* skip message numbers according to CreditCharge field */
for (i = 1; i < num; i++) for (i = 1; i < num; i++)
get_next_mid(server); get_next_mid(server);
} }
static struct mid_q_entry * static struct mid_q_entry *
smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, smb2_mid_entry_alloc(const struct smb2_sync_hdr *shdr,
struct TCP_Server_Info *server) struct TCP_Server_Info *server)
{ {
struct mid_q_entry *temp; struct mid_q_entry *temp;
...@@ -493,9 +492,9 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, ...@@ -493,9 +492,9 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
return temp; return temp;
else { else {
memset(temp, 0, sizeof(struct mid_q_entry)); memset(temp, 0, sizeof(struct mid_q_entry));
temp->mid = le64_to_cpu(smb_buffer->MessageId); temp->mid = le64_to_cpu(shdr->MessageId);
temp->pid = current->pid; temp->pid = current->pid;
temp->command = smb_buffer->Command; /* Always LE */ temp->command = shdr->Command; /* Always LE */
temp->when_alloc = jiffies; temp->when_alloc = jiffies;
temp->server = server; temp->server = server;
...@@ -513,7 +512,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer, ...@@ -513,7 +512,7 @@ smb2_mid_entry_alloc(const struct smb2_hdr *smb_buffer,
} }
static int static int
smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf, smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_sync_hdr *shdr,
struct mid_q_entry **mid) struct mid_q_entry **mid)
{ {
if (ses->server->tcpStatus == CifsExiting) if (ses->server->tcpStatus == CifsExiting)
...@@ -525,19 +524,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf, ...@@ -525,19 +524,19 @@ smb2_get_mid_entry(struct cifs_ses *ses, struct smb2_hdr *buf,
} }
if (ses->status == CifsNew) { if (ses->status == CifsNew) {
if ((buf->Command != SMB2_SESSION_SETUP) && if ((shdr->Command != SMB2_SESSION_SETUP) &&
(buf->Command != SMB2_NEGOTIATE)) (shdr->Command != SMB2_NEGOTIATE))
return -EAGAIN; return -EAGAIN;
/* else ok - we are setting up session */ /* else ok - we are setting up session */
} }
if (ses->status == CifsExiting) { if (ses->status == CifsExiting) {
if (buf->Command != SMB2_LOGOFF) if (shdr->Command != SMB2_LOGOFF)
return -EAGAIN; return -EAGAIN;
/* else ok - we are shutting down the session */ /* else ok - we are shutting down the session */
} }
*mid = smb2_mid_entry_alloc(buf, ses->server); *mid = smb2_mid_entry_alloc(shdr, ses->server);
if (*mid == NULL) if (*mid == NULL)
return -ENOMEM; return -ENOMEM;
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
...@@ -576,12 +575,12 @@ struct mid_q_entry * ...@@ -576,12 +575,12 @@ struct mid_q_entry *
smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst) smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
{ {
int rc; int rc;
struct smb2_hdr *hdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base);
struct mid_q_entry *mid; struct mid_q_entry *mid;
smb2_seq_num_into_buf(ses->server, hdr); smb2_seq_num_into_buf(ses->server, shdr);
rc = smb2_get_mid_entry(ses, hdr, &mid); rc = smb2_get_mid_entry(ses, shdr, &mid);
if (rc) if (rc)
return ERR_PTR(rc); return ERR_PTR(rc);
rc = smb2_sign_rqst(rqst, ses->server); rc = smb2_sign_rqst(rqst, ses->server);
...@@ -596,12 +595,12 @@ struct mid_q_entry * ...@@ -596,12 +595,12 @@ struct mid_q_entry *
smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst) smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
{ {
int rc; int rc;
struct smb2_hdr *hdr = (struct smb2_hdr *)rqst->rq_iov[0].iov_base; struct smb2_sync_hdr *shdr = get_sync_hdr(rqst->rq_iov[0].iov_base);
struct mid_q_entry *mid; struct mid_q_entry *mid;
smb2_seq_num_into_buf(server, hdr); smb2_seq_num_into_buf(server, shdr);
mid = smb2_mid_entry_alloc(hdr, server); mid = smb2_mid_entry_alloc(shdr, server);
if (mid == NULL) if (mid == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment