Commit 93012bf9 authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Steve French

cifs: add server->vals->header_preamble_size

This variable is set to 4 for all protocol versions and replaces
the hardcoded constant 4 throughought the code.
This will later be updated to reflect whether a response packet
has a 4 byte length preamble or not once we start removing this
field from the SMB2+ dialects.
Signed-off-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
Reviewed-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
parent 21a4e14a
...@@ -468,6 +468,7 @@ struct smb_version_values { ...@@ -468,6 +468,7 @@ struct smb_version_values {
__u32 exclusive_lock_type; __u32 exclusive_lock_type;
__u32 shared_lock_type; __u32 shared_lock_type;
__u32 unlock_lock_type; __u32 unlock_lock_type;
size_t header_preamble_size;
size_t header_size; size_t header_size;
size_t max_header_size; size_t max_header_size;
size_t read_rsp_size; size_t read_rsp_size;
......
...@@ -1454,7 +1454,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1454,7 +1454,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
unsigned int data_offset, data_len; unsigned int data_offset, data_len;
struct cifs_readdata *rdata = mid->callback_data; struct cifs_readdata *rdata = mid->callback_data;
char *buf = server->smallbuf; char *buf = server->smallbuf;
unsigned int buflen = get_rfc1002_length(buf) + 4; unsigned int buflen = get_rfc1002_length(buf) +
server->vals->header_preamble_size;
bool use_rdma_mr = false; bool use_rdma_mr = false;
cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n", cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
...@@ -1504,7 +1505,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -1504,7 +1505,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return cifs_readv_discard(server, mid); return cifs_readv_discard(server, mid);
} }
data_offset = server->ops->read_data_offset(buf) + 4; data_offset = server->ops->read_data_offset(buf) +
server->vals->header_preamble_size;
if (data_offset < server->total_read) { if (data_offset < server->total_read) {
/* /*
* win2k8 sometimes sends an offset of 0 when the read * win2k8 sometimes sends an offset of 0 when the read
......
...@@ -775,7 +775,8 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -775,7 +775,8 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
unsigned int pdu_length = get_rfc1002_length(buf); unsigned int pdu_length = get_rfc1002_length(buf);
/* make sure this will fit in a large buffer */ /* make sure this will fit in a large buffer */
if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 4) { if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
server->vals->header_preamble_size) {
cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); cifs_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
cifs_reconnect(server); cifs_reconnect(server);
wake_up(&server->response_q); wake_up(&server->response_q);
...@@ -791,7 +792,9 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) ...@@ -791,7 +792,9 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
/* now read the rest */ /* now read the rest */
length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
pdu_length - HEADER_SIZE(server) + 1 + 4); pdu_length - HEADER_SIZE(server) + 1
+ server->vals->header_preamble_size);
if (length < 0) if (length < 0)
return length; return length;
server->total_read += length; server->total_read += length;
...@@ -884,7 +887,8 @@ cifs_demultiplex_thread(void *p) ...@@ -884,7 +887,8 @@ cifs_demultiplex_thread(void *p)
continue; continue;
/* make sure we have enough to get to the MID */ /* make sure we have enough to get to the MID */
if (pdu_length < HEADER_SIZE(server) - 1 - 4) { if (pdu_length < HEADER_SIZE(server) - 1 -
server->vals->header_preamble_size) {
cifs_dbg(VFS, "SMB response too short (%u bytes)\n", cifs_dbg(VFS, "SMB response too short (%u bytes)\n",
pdu_length); pdu_length);
cifs_reconnect(server); cifs_reconnect(server);
...@@ -893,8 +897,10 @@ cifs_demultiplex_thread(void *p) ...@@ -893,8 +897,10 @@ cifs_demultiplex_thread(void *p)
} }
/* read down to the MID */ /* read down to the MID */
length = cifs_read_from_socket(server, buf + 4, length = cifs_read_from_socket(server,
HEADER_SIZE(server) - 1 - 4); buf + server->vals->header_preamble_size,
HEADER_SIZE(server) - 1
- server->vals->header_preamble_size);
if (length < 0) if (length < 0)
continue; continue;
server->total_read += length; server->total_read += length;
......
...@@ -1122,6 +1122,7 @@ struct smb_version_values smb1_values = { ...@@ -1122,6 +1122,7 @@ struct smb_version_values smb1_values = {
.exclusive_lock_type = 0, .exclusive_lock_type = 0,
.shared_lock_type = LOCKING_ANDX_SHARED_LOCK, .shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
.unlock_lock_type = 0, .unlock_lock_type = 0,
.header_preamble_size = 4,
.header_size = sizeof(struct smb_hdr), .header_size = sizeof(struct smb_hdr),
.max_header_size = MAX_CIFS_HDR_SIZE, .max_header_size = MAX_CIFS_HDR_SIZE,
.read_rsp_size = sizeof(READ_RSP), .read_rsp_size = sizeof(READ_RSP),
......
...@@ -150,7 +150,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -150,7 +150,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
} }
return 1; return 1;
} }
if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) { if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE -
srvr->vals->header_preamble_size) {
cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n", cifs_dbg(VFS, "SMB length greater than maximum, mid=%llu\n",
mid); mid);
return 1; return 1;
...@@ -189,26 +190,26 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -189,26 +190,26 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
} }
} }
if (4 + len != length) { if (srvr->vals->header_preamble_size + len != length) {
cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n", cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
length, 4 + len, mid); length, srvr->vals->header_preamble_size + len, mid);
return 1; return 1;
} }
clc_len = smb2_calc_size(hdr); clc_len = smb2_calc_size(hdr);
if (4 + len != clc_len) { if (srvr->vals->header_preamble_size + len != clc_len) {
cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n", cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
clc_len, 4 + len, mid); clc_len, srvr->vals->header_preamble_size + len, mid);
/* create failed on symlink */ /* create failed on symlink */
if (command == SMB2_CREATE_HE && if (command == SMB2_CREATE_HE &&
shdr->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 + 24 - srvr->vals->header_preamble_size == len && command == SMB2_OPLOCK_BREAK_HE)
return 0; return 0;
/* server can return one byte more due to implied bcc[0] */ /* server can return one byte more due to implied bcc[0] */
if (clc_len == 4 + len + 1) if (clc_len == srvr->vals->header_preamble_size + len + 1)
return 0; return 0;
/* /*
...@@ -218,10 +219,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr) ...@@ -218,10 +219,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
* Log the server error (once), but allow it and continue * Log the server error (once), but allow it and continue
* since the frame is parseable. * since the frame is parseable.
*/ */
if (clc_len < 4 /* RFC1001 header size */ + len) { if (clc_len < srvr->vals->header_preamble_size /* RFC1001 header size */ + len) {
printk_once(KERN_WARNING printk_once(KERN_WARNING
"SMB2 server sent bad RFC1001 len %d not %d\n", "SMB2 server sent bad RFC1001 len %d not %d\n",
len, clc_len - 4); len, clc_len - srvr->vals->header_preamble_size);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -1471,7 +1471,7 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, ...@@ -1471,7 +1471,7 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
unsigned int remaining; unsigned int remaining;
char *name; char *name;
data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset); data_offset = (char *)rsp + server->vals->header_preamble_size + le32_to_cpu(rsp->CreateContextsOffset);
remaining = le32_to_cpu(rsp->CreateContextsLength); remaining = le32_to_cpu(rsp->CreateContextsLength);
cc = (struct create_context *)data_offset; cc = (struct create_context *)data_offset;
while (remaining >= sizeof(struct create_context)) { while (remaining >= sizeof(struct create_context)) {
...@@ -3452,6 +3452,7 @@ static int ...@@ -3452,6 +3452,7 @@ static int
build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
int outbuf_len, u64 persistent_fid, u64 volatile_fid) int outbuf_len, u64 persistent_fid, u64 volatile_fid)
{ {
struct TCP_Server_Info *server = tcon->ses->server;
int rc; int rc;
struct smb2_query_info_req *req; struct smb2_query_info_req *req;
unsigned int total_len; unsigned int total_len;
...@@ -3474,7 +3475,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level, ...@@ -3474,7 +3475,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
req->InputBufferOffset = req->InputBufferOffset =
cpu_to_le16(sizeof(struct smb2_query_info_req) - 1); cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
req->OutputBufferLength = cpu_to_le32( req->OutputBufferLength = cpu_to_le32(
outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - 4); outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - server->vals->header_preamble_size);
iov->iov_base = (char *)req; iov->iov_base = (char *)req;
iov->iov_len = total_len; iov->iov_len = total_len;
...@@ -3491,6 +3492,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3491,6 +3492,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
int rc = 0; int rc = 0;
int resp_buftype; int resp_buftype;
struct cifs_ses *ses = tcon->ses; struct cifs_ses *ses = tcon->ses;
struct TCP_Server_Info *server = ses->server;
struct smb2_fs_full_size_info *info = NULL; struct smb2_fs_full_size_info *info = NULL;
int flags = 0; int flags = 0;
...@@ -3511,7 +3513,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3511,7 +3513,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
} }
rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base; rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
info = (struct smb2_fs_full_size_info *)(4 /* RFC1001 len */ + info = (struct smb2_fs_full_size_info *)(server->vals->header_preamble_size +
le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr); le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset), rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr, le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
...@@ -3534,6 +3536,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3534,6 +3536,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
int rc = 0; int rc = 0;
int resp_buftype, max_len, min_len; int resp_buftype, max_len, min_len;
struct cifs_ses *ses = tcon->ses; struct cifs_ses *ses = tcon->ses;
struct TCP_Server_Info *server = ses->server;
unsigned int rsp_len, offset; unsigned int rsp_len, offset;
int flags = 0; int flags = 0;
...@@ -3574,15 +3577,15 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3574,15 +3577,15 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
goto qfsattr_exit; goto qfsattr_exit;
if (level == FS_ATTRIBUTE_INFORMATION) if (level == FS_ATTRIBUTE_INFORMATION)
memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset memcpy(&tcon->fsAttrInfo, server->vals->header_preamble_size + offset
+ (char *)&rsp->hdr, min_t(unsigned int, + (char *)&rsp->hdr, min_t(unsigned int,
rsp_len, max_len)); rsp_len, max_len));
else if (level == FS_DEVICE_INFORMATION) else if (level == FS_DEVICE_INFORMATION)
memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset memcpy(&tcon->fsDevInfo, server->vals->header_preamble_size + offset
+ (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO)); + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
else if (level == FS_SECTOR_SIZE_INFORMATION) { else if (level == FS_SECTOR_SIZE_INFORMATION) {
struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *) struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
(4 /* RFC1001 len */ + offset + (char *)&rsp->hdr); (server->vals->header_preamble_size + offset + (char *)&rsp->hdr);
tcon->ss_flags = le32_to_cpu(ss_info->Flags); tcon->ss_flags = le32_to_cpu(ss_info->Flags);
tcon->perf_sector_size = tcon->perf_sector_size =
le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf); le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
......
...@@ -790,7 +790,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses, ...@@ -790,7 +790,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
buf = (char *)midQ->resp_buf; buf = (char *)midQ->resp_buf;
resp_iov->iov_base = buf; resp_iov->iov_base = buf;
resp_iov->iov_len = get_rfc1002_length(buf) + 4; resp_iov->iov_len = get_rfc1002_length(buf) +
ses->server->vals->header_preamble_size;
if (midQ->large_buf) if (midQ->large_buf)
*resp_buf_type = CIFS_LARGE_BUFFER; *resp_buf_type = CIFS_LARGE_BUFFER;
else else
......
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