cifs: Remove the RFC1002 header from smb_hdr
Remove the RFC1002 header from struct smb_hdr as used for SMB-1.0. This simplifies the SMB-1.0 code by simplifying a lot of places that have to add or subtract 4 to work around the fact that the RFC1002 header isn't really part of the message and the base for various offsets within the message is from the base of the smb_hdr, not the RFC1002 header. Further, clean up a bunch of places that require an extra kvec struct specifically pointing to the RFC1002 header, such that kvec[0].iov_base must be exactly 4 bytes before kvec[1].iov_base. This allows the header preamble size stuff to be removed too. The size of the request and response message are then handed around either directly or by summing the size of all the iov_len members in the kvec array for which we have a count. Also, this simplifies and cleans up the common transmission and receive paths for SMB1 and SMB2/3 as there no longer needs to be special handling casing for SMB1 messages as the RFC1002 header is now generated on the fly for SMB1 as it is for SMB2/3. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Tom Talpey <tom@talpey.com> Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> cc: Shyam Prasad N <sprasad@microsoft.com> cc: linux-cifs@vger.kernel.org cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
committed by
Steve French
parent
9d85ac939d
commit
83bfbd0bb9
@@ -37,7 +37,7 @@ cifs_dump_mem(char *label, void *data, int length)
|
||||
data, length, true);
|
||||
}
|
||||
|
||||
void cifs_dump_detail(void *buf, struct TCP_Server_Info *server)
|
||||
void cifs_dump_detail(void *buf, size_t buf_len, struct TCP_Server_Info *server)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
struct smb_hdr *smb = buf;
|
||||
@@ -45,7 +45,7 @@ void cifs_dump_detail(void *buf, struct TCP_Server_Info *server)
|
||||
cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d Wct: %d\n",
|
||||
smb->Command, smb->Status.CifsError, smb->Flags,
|
||||
smb->Flags2, smb->Mid, smb->Pid, smb->WordCount);
|
||||
if (!server->ops->check_message(buf, server->total_read, server)) {
|
||||
if (!server->ops->check_message(buf, buf_len, server->total_read, server)) {
|
||||
cifs_dbg(VFS, "smb buf %p len %u\n", smb,
|
||||
server->ops->calc_smb_size(smb));
|
||||
}
|
||||
@@ -79,9 +79,9 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
|
||||
cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
|
||||
mid_entry->multiRsp, mid_entry->multiEnd);
|
||||
if (mid_entry->resp_buf) {
|
||||
cifs_dump_detail(mid_entry->resp_buf, server);
|
||||
cifs_dump_mem("existing buf: ",
|
||||
mid_entry->resp_buf, 62);
|
||||
cifs_dump_detail(mid_entry->resp_buf,
|
||||
mid_entry->response_pdu_len, server);
|
||||
cifs_dump_mem("existing buf: ", mid_entry->resp_buf, 62);
|
||||
}
|
||||
}
|
||||
spin_unlock(&server->mid_queue_lock);
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
#define pr_fmt(fmt) "CIFS: " fmt
|
||||
|
||||
void cifs_dump_mem(char *label, void *data, int length);
|
||||
void cifs_dump_detail(void *buf, struct TCP_Server_Info *ptcp_info);
|
||||
void cifs_dump_mids(struct TCP_Server_Info *);
|
||||
void cifs_dump_detail(void *buf, size_t buf_len, struct TCP_Server_Info *server);
|
||||
void cifs_dump_mids(struct TCP_Server_Info *server);
|
||||
extern bool traceSMB; /* flag which enables the function below */
|
||||
void dump_smb(void *, int);
|
||||
void dump_smb(void *buf, int smb_buf_length);
|
||||
#define CIFS_INFO 0x01
|
||||
#define CIFS_RC 0x02
|
||||
#define CIFS_TIMER 0x04
|
||||
|
||||
@@ -91,18 +91,7 @@ int __cifs_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
||||
struct kvec *iov = rqst->rq_iov;
|
||||
int n_vec = rqst->rq_nvec;
|
||||
|
||||
/* iov[0] is actual data and not the rfc1002 length for SMB2+ */
|
||||
if (!is_smb1(server)) {
|
||||
if (iov[0].iov_len <= 4)
|
||||
return -EIO;
|
||||
i = 0;
|
||||
} else {
|
||||
if (n_vec < 2 || iov[0].iov_len != 4)
|
||||
return -EIO;
|
||||
i = 1; /* skip rfc1002 length */
|
||||
}
|
||||
|
||||
for (; i < n_vec; i++) {
|
||||
for (i = 0; i < n_vec; i++) {
|
||||
if (iov[i].iov_len == 0)
|
||||
continue;
|
||||
if (iov[i].iov_base == NULL) {
|
||||
@@ -165,10 +154,6 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
||||
char smb_signature[20];
|
||||
struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
|
||||
|
||||
if (rqst->rq_iov[0].iov_len != 4 ||
|
||||
rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
|
||||
return -EIO;
|
||||
|
||||
if ((cifs_pdu == NULL) || (server == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -211,17 +196,16 @@ int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
|
||||
}
|
||||
|
||||
/* must be called with server->srv_mutex held */
|
||||
int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server,
|
||||
int cifs_sign_smb(struct smb_hdr *cifs_pdu, unsigned int pdu_len,
|
||||
struct TCP_Server_Info *server,
|
||||
__u32 *pexpected_response_sequence_number)
|
||||
{
|
||||
struct kvec iov[2];
|
||||
struct kvec iov[1] = {
|
||||
[0].iov_base = (char *)cifs_pdu,
|
||||
[0].iov_len = pdu_len,
|
||||
};
|
||||
|
||||
iov[0].iov_base = cifs_pdu;
|
||||
iov[0].iov_len = 4;
|
||||
iov[1].iov_base = (char *)cifs_pdu + 4;
|
||||
iov[1].iov_len = be32_to_cpu(cifs_pdu->smb_buf_length);
|
||||
|
||||
return cifs_sign_smbv(iov, 2, server,
|
||||
return cifs_sign_smbv(iov, ARRAY_SIZE(iov), server,
|
||||
pexpected_response_sequence_number);
|
||||
}
|
||||
|
||||
@@ -234,10 +218,6 @@ int cifs_verify_signature(struct smb_rqst *rqst,
|
||||
char what_we_think_sig_should_be[20];
|
||||
struct smb_hdr *cifs_pdu = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
|
||||
|
||||
if (rqst->rq_iov[0].iov_len != 4 ||
|
||||
rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
|
||||
return -EIO;
|
||||
|
||||
if (cifs_pdu == NULL || server == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -346,13 +346,14 @@ struct smb_version_operations {
|
||||
/* map smb to linux error */
|
||||
int (*map_error)(char *, bool);
|
||||
/* find mid corresponding to the response message */
|
||||
struct mid_q_entry * (*find_mid)(struct TCP_Server_Info *, char *);
|
||||
void (*dump_detail)(void *buf, struct TCP_Server_Info *ptcp_info);
|
||||
struct mid_q_entry *(*find_mid)(struct TCP_Server_Info *server, char *buf);
|
||||
void (*dump_detail)(void *buf, size_t buf_len, struct TCP_Server_Info *ptcp_info);
|
||||
void (*clear_stats)(struct cifs_tcon *);
|
||||
void (*print_stats)(struct seq_file *m, struct cifs_tcon *);
|
||||
void (*dump_share_caps)(struct seq_file *, struct cifs_tcon *);
|
||||
/* verify the message */
|
||||
int (*check_message)(char *, unsigned int, struct TCP_Server_Info *);
|
||||
int (*check_message)(char *buf, unsigned int pdu_len, unsigned int len,
|
||||
struct TCP_Server_Info *server);
|
||||
bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
|
||||
int (*handle_cancelled_mid)(struct mid_q_entry *, struct TCP_Server_Info *);
|
||||
void (*downgrade_oplock)(struct TCP_Server_Info *server,
|
||||
@@ -636,8 +637,7 @@ struct smb_version_operations {
|
||||
|
||||
#define HEADER_SIZE(server) (server->vals->header_size)
|
||||
#define MAX_HEADER_SIZE(server) (server->vals->max_header_size)
|
||||
#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size)
|
||||
#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1 - HEADER_PREAMBLE_SIZE(server))
|
||||
#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1)
|
||||
|
||||
/**
|
||||
* CIFS superblock mount flags (mnt_cifs_flags) to consider when
|
||||
@@ -832,9 +832,9 @@ struct TCP_Server_Info {
|
||||
char dns_dom[CIFS_MAX_DOMAINNAME_LEN + 1];
|
||||
};
|
||||
|
||||
static inline bool is_smb1(struct TCP_Server_Info *server)
|
||||
static inline bool is_smb1(const struct TCP_Server_Info *server)
|
||||
{
|
||||
return HEADER_PREAMBLE_SIZE(server) != 0;
|
||||
return server->vals->protocol_id == SMB10_PROT_ID;
|
||||
}
|
||||
|
||||
static inline void cifs_server_lock(struct TCP_Server_Info *server)
|
||||
@@ -973,16 +973,16 @@ compare_mid(__u16 mid, const struct smb_hdr *smb)
|
||||
* of kvecs to handle the receive, though that should only need to be done
|
||||
* once.
|
||||
*/
|
||||
#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
|
||||
#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4)
|
||||
#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ))
|
||||
#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP))
|
||||
|
||||
/*
|
||||
* When the server doesn't allow large posix writes, only allow a rsize/wsize
|
||||
* of 2^17-1 minus the size of the call header. That allows for a read or
|
||||
* write up to the maximum size described by RFC1002.
|
||||
*/
|
||||
#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
|
||||
#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
|
||||
#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ))
|
||||
#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP))
|
||||
|
||||
/*
|
||||
* Windows only supports a max of 60kb reads and 65535 byte writes. Default to
|
||||
@@ -1701,6 +1701,7 @@ struct mid_q_entry {
|
||||
struct task_struct *creator;
|
||||
void *resp_buf; /* pointer to received SMB header */
|
||||
unsigned int resp_buf_size;
|
||||
u32 response_pdu_len;
|
||||
int mid_state; /* wish this were enum but can not pass to wait_event */
|
||||
int mid_rc; /* rc for MID_RC */
|
||||
__le16 command; /* smb command code */
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
|
||||
/* future chained NTCreateXReadX bigger, but for time being NTCreateX biggest */
|
||||
/* among the requests (NTCreateX response is bigger with wct of 34) */
|
||||
#define MAX_CIFS_HDR_SIZE 0x58 /* 4 len + 32 hdr + (2*24 wct) + 2 bct + 2 pad */
|
||||
#define MAX_CIFS_HDR_SIZE 0x54 /* 32 hdr + (2*24 wct) + 2 bct + 2 pad */
|
||||
#define CIFS_SMALL_PATH 120 /* allows for (448-88)/3 */
|
||||
|
||||
/* internal cifs vfs structures */
|
||||
|
||||
@@ -111,18 +111,16 @@ extern int compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
||||
const int flags, const int num_rqst,
|
||||
struct smb_rqst *rqst, int *resp_buf_type,
|
||||
struct kvec *resp_iov);
|
||||
extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *,
|
||||
struct smb_hdr * /* input */ ,
|
||||
struct smb_hdr * /* out */ ,
|
||||
int * /* bytes returned */ , const int);
|
||||
extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
|
||||
char *in_buf, int flags);
|
||||
int SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct smb_hdr *in_buf, unsigned int in_len,
|
||||
struct smb_hdr *out_buf, int *pbytes_returned, const int flags);
|
||||
int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
|
||||
char *in_buf, unsigned int in_len, int flags);
|
||||
int cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server);
|
||||
extern struct mid_q_entry *cifs_setup_request(struct cifs_ses *,
|
||||
struct TCP_Server_Info *,
|
||||
struct smb_rqst *);
|
||||
extern struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info *,
|
||||
struct smb_rqst *);
|
||||
struct mid_q_entry *cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored,
|
||||
struct smb_rqst *rqst);
|
||||
struct mid_q_entry *cifs_setup_async_request(struct TCP_Server_Info *server,
|
||||
struct smb_rqst *rqst);
|
||||
int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
|
||||
struct smb_rqst *rqst);
|
||||
extern int cifs_check_receive(struct mid_q_entry *mid,
|
||||
@@ -146,11 +144,9 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
|
||||
struct kvec *, int /* nvec to send */,
|
||||
int * /* type of buf returned */, const int flags,
|
||||
struct kvec * /* resp vec */);
|
||||
extern int SendReceiveBlockingLock(const unsigned int xid,
|
||||
struct cifs_tcon *ptcon,
|
||||
struct smb_hdr *in_buf,
|
||||
struct smb_hdr *out_buf,
|
||||
int *bytes_returned);
|
||||
int SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct smb_hdr *in_buf, unsigned int in_len,
|
||||
struct smb_hdr *out_buf, int *pbytes_returned);
|
||||
|
||||
void smb2_query_server_interfaces(struct work_struct *work);
|
||||
void
|
||||
@@ -161,7 +157,8 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
|
||||
bool mark_smb_session);
|
||||
extern int cifs_reconnect(struct TCP_Server_Info *server,
|
||||
bool mark_smb_session);
|
||||
extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
|
||||
int checkSMB(char *buf, unsigned int pdu_len, unsigned int len,
|
||||
struct TCP_Server_Info *srvr);
|
||||
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
|
||||
extern bool backup_cred(struct cifs_sb_info *);
|
||||
extern bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 eof,
|
||||
@@ -188,9 +185,9 @@ extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
|
||||
extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port);
|
||||
extern int map_smb_to_linux_error(char *buf, bool logErr);
|
||||
extern int map_and_check_smb_error(struct mid_q_entry *mid, bool logErr);
|
||||
extern void header_assemble(struct smb_hdr *, char /* command */ ,
|
||||
const struct cifs_tcon *, int /* length of
|
||||
fixed section (word count) in two byte units */);
|
||||
unsigned int header_assemble(struct smb_hdr *buffer, char smb_command,
|
||||
const struct cifs_tcon *treeCon, int word_count
|
||||
/* length of fixed section word count in two byte units */);
|
||||
extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
|
||||
struct cifs_ses *ses,
|
||||
void **request_buf);
|
||||
@@ -565,12 +562,14 @@ extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
|
||||
|
||||
extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
|
||||
__u32 *pexpected_response_sequence_number);
|
||||
extern int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *,
|
||||
__u32 *);
|
||||
extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *);
|
||||
extern int cifs_verify_signature(struct smb_rqst *rqst,
|
||||
struct TCP_Server_Info *server,
|
||||
__u32 expected_sequence_number);
|
||||
int cifs_sign_smbv(struct kvec *iov, int n_vec, struct TCP_Server_Info *server,
|
||||
__u32 *pexpected_response_sequence);
|
||||
int cifs_sign_smb(struct smb_hdr *cifs_pdu, unsigned int pdu_len,
|
||||
struct TCP_Server_Info *server,
|
||||
__u32 *pexpected_response_sequence_number);
|
||||
int cifs_verify_signature(struct smb_rqst *rqst,
|
||||
struct TCP_Server_Info *server,
|
||||
__u32 expected_sequence_number);
|
||||
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
|
||||
extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
|
||||
extern int calc_seckey(struct cifs_ses *);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -74,14 +74,14 @@ int
|
||||
smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
|
||||
unsigned int smb_buf_length)
|
||||
{
|
||||
struct kvec iov[2];
|
||||
struct smb_rqst rqst = { .rq_iov = iov,
|
||||
.rq_nvec = 2 };
|
||||
|
||||
iov[0].iov_base = smb_buffer;
|
||||
iov[0].iov_len = 4;
|
||||
iov[1].iov_base = (char *)smb_buffer + 4;
|
||||
iov[1].iov_len = smb_buf_length;
|
||||
struct kvec iov[1] = {
|
||||
[0].iov_base = smb_buffer,
|
||||
[0].iov_len = smb_buf_length,
|
||||
};
|
||||
struct smb_rqst rqst = {
|
||||
.rq_iov = iov,
|
||||
.rq_nvec = ARRAY_SIZE(iov),
|
||||
};
|
||||
|
||||
return __smb_send_rqst(server, 1, &rqst);
|
||||
}
|
||||
@@ -125,10 +125,6 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
|
||||
struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
|
||||
struct mid_q_entry *mid;
|
||||
|
||||
if (rqst->rq_iov[0].iov_len != 4 ||
|
||||
rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
/* enable signing if server requires it */
|
||||
if (server->sign)
|
||||
hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
|
||||
@@ -157,7 +153,7 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
|
||||
*/
|
||||
int
|
||||
SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
|
||||
char *in_buf, int flags)
|
||||
char *in_buf, unsigned int in_len, int flags)
|
||||
{
|
||||
int rc;
|
||||
struct kvec iov[1];
|
||||
@@ -165,7 +161,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
|
||||
int resp_buf_type;
|
||||
|
||||
iov[0].iov_base = in_buf;
|
||||
iov[0].iov_len = get_rfc1002_len(in_buf) + 4;
|
||||
iov[0].iov_len = in_len;
|
||||
flags |= CIFS_NO_RSP_BUF;
|
||||
rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
|
||||
cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
|
||||
@@ -177,21 +173,19 @@ int
|
||||
cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
|
||||
bool log_error)
|
||||
{
|
||||
unsigned int len = get_rfc1002_len(mid->resp_buf) + 4;
|
||||
unsigned int len = mid->response_pdu_len;
|
||||
|
||||
dump_smb(mid->resp_buf, min_t(u32, 92, len));
|
||||
|
||||
/* convert the length into a more usable form */
|
||||
if (server->sign) {
|
||||
struct kvec iov[2];
|
||||
struct kvec iov[1];
|
||||
int rc = 0;
|
||||
struct smb_rqst rqst = { .rq_iov = iov,
|
||||
.rq_nvec = 2 };
|
||||
.rq_nvec = ARRAY_SIZE(iov) };
|
||||
|
||||
iov[0].iov_base = mid->resp_buf;
|
||||
iov[0].iov_len = 4;
|
||||
iov[1].iov_base = (char *)mid->resp_buf + 4;
|
||||
iov[1].iov_len = len - 4;
|
||||
iov[0].iov_len = len;
|
||||
/* FIXME: add code to kill session */
|
||||
rc = cifs_verify_signature(&rqst, server,
|
||||
mid->sequence_number);
|
||||
@@ -212,10 +206,6 @@ cifs_setup_request(struct cifs_ses *ses, struct TCP_Server_Info *ignored,
|
||||
struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
|
||||
struct mid_q_entry *mid;
|
||||
|
||||
if (rqst->rq_iov[0].iov_len != 4 ||
|
||||
rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
|
||||
return ERR_PTR(-EIO);
|
||||
|
||||
rc = allocate_mid(ses, hdr, &mid);
|
||||
if (rc)
|
||||
return ERR_PTR(rc);
|
||||
@@ -232,53 +222,29 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
|
||||
const int flags, struct kvec *resp_iov)
|
||||
{
|
||||
struct smb_rqst rqst;
|
||||
struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
|
||||
int rc;
|
||||
struct smb_rqst rqst = {
|
||||
.rq_iov = iov,
|
||||
.rq_nvec = n_vec,
|
||||
};
|
||||
|
||||
if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
|
||||
new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec),
|
||||
GFP_KERNEL);
|
||||
if (!new_iov) {
|
||||
/* otherwise cifs_send_recv below sets resp_buf_type */
|
||||
*resp_buf_type = CIFS_NO_BUFFER;
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else
|
||||
new_iov = s_iov;
|
||||
|
||||
/* 1st iov is a RFC1001 length followed by the rest of the packet */
|
||||
memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
|
||||
|
||||
new_iov[0].iov_base = new_iov[1].iov_base;
|
||||
new_iov[0].iov_len = 4;
|
||||
new_iov[1].iov_base += 4;
|
||||
new_iov[1].iov_len -= 4;
|
||||
|
||||
memset(&rqst, 0, sizeof(struct smb_rqst));
|
||||
rqst.rq_iov = new_iov;
|
||||
rqst.rq_nvec = n_vec + 1;
|
||||
|
||||
rc = cifs_send_recv(xid, ses, ses->server,
|
||||
&rqst, resp_buf_type, flags, resp_iov);
|
||||
if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
|
||||
kfree(new_iov);
|
||||
return rc;
|
||||
return cifs_send_recv(xid, ses, ses->server,
|
||||
&rqst, resp_buf_type, flags, resp_iov);
|
||||
}
|
||||
|
||||
int
|
||||
SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
struct smb_hdr *in_buf, struct smb_hdr *out_buf,
|
||||
int *pbytes_returned, const int flags)
|
||||
struct smb_hdr *in_buf, unsigned int in_len,
|
||||
struct smb_hdr *out_buf, int *pbytes_returned, const int flags)
|
||||
{
|
||||
int rc = 0;
|
||||
struct mid_q_entry *midQ;
|
||||
unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
|
||||
struct kvec iov = { .iov_base = in_buf, .iov_len = len };
|
||||
struct mid_q_entry *mid;
|
||||
struct kvec iov = { .iov_base = in_buf, .iov_len = in_len };
|
||||
struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
|
||||
struct cifs_credits credits = { .value = 1, .instance = 0 };
|
||||
struct TCP_Server_Info *server;
|
||||
|
||||
if (WARN_ON_ONCE(in_len > 0xffffff))
|
||||
return -EIO;
|
||||
if (ses == NULL) {
|
||||
cifs_dbg(VFS, "Null smb session\n");
|
||||
return -EIO;
|
||||
@@ -300,9 +266,9 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
to the same server. We may make this configurable later or
|
||||
use ses->maxReq */
|
||||
|
||||
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
|
||||
if (in_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
|
||||
cifs_server_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
|
||||
len);
|
||||
in_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -316,7 +282,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
|
||||
cifs_server_lock(server);
|
||||
|
||||
rc = allocate_mid(ses, in_buf, &midQ);
|
||||
rc = allocate_mid(ses, in_buf, &mid);
|
||||
if (rc) {
|
||||
cifs_server_unlock(server);
|
||||
/* Update # of requests on wire to server */
|
||||
@@ -324,16 +290,16 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
|
||||
rc = cifs_sign_smb(in_buf, in_len, server, &mid->sequence_number);
|
||||
if (rc) {
|
||||
cifs_server_unlock(server);
|
||||
goto out;
|
||||
}
|
||||
|
||||
midQ->mid_state = MID_REQUEST_SUBMITTED;
|
||||
mid->mid_state = MID_REQUEST_SUBMITTED;
|
||||
|
||||
rc = smb_send(server, in_buf, len);
|
||||
cifs_save_when_sent(midQ);
|
||||
rc = smb_send(server, in_buf, in_len);
|
||||
cifs_save_when_sent(mid);
|
||||
|
||||
if (rc < 0)
|
||||
server->sequence_number -= 2;
|
||||
@@ -343,38 +309,38 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = wait_for_response(server, midQ);
|
||||
rc = wait_for_response(server, mid);
|
||||
if (rc != 0) {
|
||||
send_cancel(server, &rqst, midQ);
|
||||
spin_lock(&midQ->mid_lock);
|
||||
if (midQ->callback) {
|
||||
send_cancel(server, &rqst, mid);
|
||||
spin_lock(&mid->mid_lock);
|
||||
if (mid->callback) {
|
||||
/* no longer considered to be "in-flight" */
|
||||
midQ->callback = release_mid;
|
||||
spin_unlock(&midQ->mid_lock);
|
||||
mid->callback = release_mid;
|
||||
spin_unlock(&mid->mid_lock);
|
||||
add_credits(server, &credits, 0);
|
||||
return rc;
|
||||
}
|
||||
spin_unlock(&midQ->mid_lock);
|
||||
spin_unlock(&mid->mid_lock);
|
||||
}
|
||||
|
||||
rc = cifs_sync_mid_result(midQ, server);
|
||||
rc = cifs_sync_mid_result(mid, server);
|
||||
if (rc != 0) {
|
||||
add_credits(server, &credits, 0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!midQ->resp_buf || !out_buf ||
|
||||
midQ->mid_state != MID_RESPONSE_READY) {
|
||||
if (!mid->resp_buf || !out_buf ||
|
||||
mid->mid_state != MID_RESPONSE_READY) {
|
||||
rc = -EIO;
|
||||
cifs_server_dbg(VFS, "Bad MID state?\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*pbytes_returned = get_rfc1002_len(midQ->resp_buf);
|
||||
memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
|
||||
rc = cifs_check_receive(midQ, server, 0);
|
||||
*pbytes_returned = mid->response_pdu_len;
|
||||
memcpy(out_buf, mid->resp_buf, *pbytes_returned);
|
||||
rc = cifs_check_receive(mid, server, 0);
|
||||
out:
|
||||
delete_mid(midQ);
|
||||
delete_mid(mid);
|
||||
add_credits(server, &credits, 0);
|
||||
|
||||
return rc;
|
||||
@@ -385,8 +351,8 @@ out:
|
||||
|
||||
static int
|
||||
send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct smb_hdr *in_buf,
|
||||
struct smb_hdr *out_buf)
|
||||
struct smb_hdr *in_buf, unsigned int in_len,
|
||||
struct smb_hdr *out_buf)
|
||||
{
|
||||
int bytes_returned;
|
||||
struct cifs_ses *ses = tcon->ses;
|
||||
@@ -401,25 +367,25 @@ send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
pSMB->Timeout = 0;
|
||||
pSMB->hdr.Mid = get_next_mid(ses->server);
|
||||
|
||||
return SendReceive(xid, ses, in_buf, out_buf,
|
||||
return SendReceive(xid, ses, in_buf, in_len, out_buf,
|
||||
&bytes_returned, 0);
|
||||
}
|
||||
|
||||
int
|
||||
SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct smb_hdr *in_buf, struct smb_hdr *out_buf,
|
||||
int *pbytes_returned)
|
||||
int SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct smb_hdr *in_buf, unsigned int in_len,
|
||||
struct smb_hdr *out_buf, int *pbytes_returned)
|
||||
{
|
||||
int rc = 0;
|
||||
int rstart = 0;
|
||||
struct mid_q_entry *midQ;
|
||||
struct mid_q_entry *mid;
|
||||
struct cifs_ses *ses;
|
||||
unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
|
||||
struct kvec iov = { .iov_base = in_buf, .iov_len = len };
|
||||
struct kvec iov = { .iov_base = in_buf, .iov_len = in_len };
|
||||
struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
|
||||
unsigned int instance;
|
||||
struct TCP_Server_Info *server;
|
||||
|
||||
if (WARN_ON_ONCE(in_len > 0xffffff))
|
||||
return -EIO;
|
||||
if (tcon == NULL || tcon->ses == NULL) {
|
||||
cifs_dbg(VFS, "Null smb session\n");
|
||||
return -EIO;
|
||||
@@ -443,9 +409,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
to the same server. We may make this configurable later or
|
||||
use ses->maxReq */
|
||||
|
||||
if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
|
||||
if (in_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
|
||||
cifs_tcon_dbg(VFS, "Invalid length, greater than maximum frame, %d\n",
|
||||
len);
|
||||
in_len);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -459,22 +425,22 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
|
||||
cifs_server_lock(server);
|
||||
|
||||
rc = allocate_mid(ses, in_buf, &midQ);
|
||||
rc = allocate_mid(ses, in_buf, &mid);
|
||||
if (rc) {
|
||||
cifs_server_unlock(server);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = cifs_sign_smb(in_buf, server, &midQ->sequence_number);
|
||||
rc = cifs_sign_smb(in_buf, in_len, server, &mid->sequence_number);
|
||||
if (rc) {
|
||||
delete_mid(midQ);
|
||||
delete_mid(mid);
|
||||
cifs_server_unlock(server);
|
||||
return rc;
|
||||
}
|
||||
|
||||
midQ->mid_state = MID_REQUEST_SUBMITTED;
|
||||
rc = smb_send(server, in_buf, len);
|
||||
cifs_save_when_sent(midQ);
|
||||
mid->mid_state = MID_REQUEST_SUBMITTED;
|
||||
rc = smb_send(server, in_buf, in_len);
|
||||
cifs_save_when_sent(mid);
|
||||
|
||||
if (rc < 0)
|
||||
server->sequence_number -= 2;
|
||||
@@ -482,22 +448,22 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
cifs_server_unlock(server);
|
||||
|
||||
if (rc < 0) {
|
||||
delete_mid(midQ);
|
||||
delete_mid(mid);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Wait for a reply - allow signals to interrupt. */
|
||||
rc = wait_event_interruptible(server->response_q,
|
||||
(!(midQ->mid_state == MID_REQUEST_SUBMITTED ||
|
||||
midQ->mid_state == MID_RESPONSE_RECEIVED)) ||
|
||||
(!(mid->mid_state == MID_REQUEST_SUBMITTED ||
|
||||
mid->mid_state == MID_RESPONSE_RECEIVED)) ||
|
||||
((server->tcpStatus != CifsGood) &&
|
||||
(server->tcpStatus != CifsNew)));
|
||||
|
||||
/* Were we interrupted by a signal ? */
|
||||
spin_lock(&server->srv_lock);
|
||||
if ((rc == -ERESTARTSYS) &&
|
||||
(midQ->mid_state == MID_REQUEST_SUBMITTED ||
|
||||
midQ->mid_state == MID_RESPONSE_RECEIVED) &&
|
||||
(mid->mid_state == MID_REQUEST_SUBMITTED ||
|
||||
mid->mid_state == MID_RESPONSE_RECEIVED) &&
|
||||
((server->tcpStatus == CifsGood) ||
|
||||
(server->tcpStatus == CifsNew))) {
|
||||
spin_unlock(&server->srv_lock);
|
||||
@@ -505,36 +471,36 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
if (in_buf->Command == SMB_COM_TRANSACTION2) {
|
||||
/* POSIX lock. We send a NT_CANCEL SMB to cause the
|
||||
blocking lock to return. */
|
||||
rc = send_cancel(server, &rqst, midQ);
|
||||
rc = send_cancel(server, &rqst, mid);
|
||||
if (rc) {
|
||||
delete_mid(midQ);
|
||||
delete_mid(mid);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
/* Windows lock. We send a LOCKINGX_CANCEL_LOCK
|
||||
to cause the blocking lock to return. */
|
||||
|
||||
rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
|
||||
rc = send_lock_cancel(xid, tcon, in_buf, in_len, out_buf);
|
||||
|
||||
/* If we get -ENOLCK back the lock may have
|
||||
already been removed. Don't exit in this case. */
|
||||
if (rc && rc != -ENOLCK) {
|
||||
delete_mid(midQ);
|
||||
delete_mid(mid);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = wait_for_response(server, midQ);
|
||||
rc = wait_for_response(server, mid);
|
||||
if (rc) {
|
||||
send_cancel(server, &rqst, midQ);
|
||||
spin_lock(&midQ->mid_lock);
|
||||
if (midQ->callback) {
|
||||
send_cancel(server, &rqst, mid);
|
||||
spin_lock(&mid->mid_lock);
|
||||
if (mid->callback) {
|
||||
/* no longer considered to be "in-flight" */
|
||||
midQ->callback = release_mid;
|
||||
spin_unlock(&midQ->mid_lock);
|
||||
mid->callback = release_mid;
|
||||
spin_unlock(&mid->mid_lock);
|
||||
return rc;
|
||||
}
|
||||
spin_unlock(&midQ->mid_lock);
|
||||
spin_unlock(&mid->mid_lock);
|
||||
}
|
||||
|
||||
/* We got the response - restart system call. */
|
||||
@@ -543,22 +509,22 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
}
|
||||
spin_unlock(&server->srv_lock);
|
||||
|
||||
rc = cifs_sync_mid_result(midQ, server);
|
||||
rc = cifs_sync_mid_result(mid, server);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
/* rcvd frame is ok */
|
||||
if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) {
|
||||
if (out_buf == NULL || mid->mid_state != MID_RESPONSE_READY) {
|
||||
rc = -EIO;
|
||||
cifs_tcon_dbg(VFS, "Bad MID state?\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
*pbytes_returned = get_rfc1002_len(midQ->resp_buf);
|
||||
memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
|
||||
rc = cifs_check_receive(midQ, server, 0);
|
||||
*pbytes_returned = mid->response_pdu_len;
|
||||
memcpy(out_buf, mid->resp_buf, *pbytes_returned);
|
||||
rc = cifs_check_receive(mid, server, 0);
|
||||
out:
|
||||
delete_mid(midQ);
|
||||
delete_mid(mid);
|
||||
if (rstart && rc == -EACCES)
|
||||
return -ERESTARTSYS;
|
||||
return rc;
|
||||
|
||||
@@ -1155,15 +1155,14 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
unsigned int pdu_length = server->pdu_size;
|
||||
|
||||
/* make sure this will fit in a large buffer */
|
||||
if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
|
||||
HEADER_PREAMBLE_SIZE(server)) {
|
||||
if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server)) {
|
||||
cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
|
||||
cifs_reconnect(server, true);
|
||||
return -ECONNABORTED;
|
||||
}
|
||||
|
||||
/* switch to large buffer if too big for a small one */
|
||||
if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) {
|
||||
if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE) {
|
||||
server->large_buf = true;
|
||||
memcpy(server->bigbuf, buf, server->total_read);
|
||||
buf = server->bigbuf;
|
||||
@@ -1196,7 +1195,8 @@ cifs_handle_standard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
* 48 bytes is enough to display the header and a little bit
|
||||
* into the payload for debugging purposes.
|
||||
*/
|
||||
rc = server->ops->check_message(buf, server->total_read, server);
|
||||
rc = server->ops->check_message(buf, server->pdu_size,
|
||||
server->total_read, server);
|
||||
if (rc)
|
||||
cifs_dump_mem("Bad SMB: ", buf,
|
||||
min_t(unsigned int, server->total_read, 48));
|
||||
@@ -1286,16 +1286,13 @@ cifs_demultiplex_thread(void *p)
|
||||
if (length < 0)
|
||||
continue;
|
||||
|
||||
if (is_smb1(server))
|
||||
server->total_read = length;
|
||||
else
|
||||
server->total_read = 0;
|
||||
server->total_read = 0;
|
||||
|
||||
/*
|
||||
* The right amount was read from socket - 4 bytes,
|
||||
* so we can now interpret the length field.
|
||||
*/
|
||||
pdu_length = get_rfc1002_len(buf);
|
||||
pdu_length = be32_to_cpup(((__be32 *)buf)) & 0xffffff;
|
||||
|
||||
cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
|
||||
if (!is_smb_response(server, buf[0]))
|
||||
@@ -1314,9 +1311,8 @@ next_pdu:
|
||||
}
|
||||
|
||||
/* read down to the MID */
|
||||
length = cifs_read_from_socket(server,
|
||||
buf + HEADER_PREAMBLE_SIZE(server),
|
||||
MID_HEADER_SIZE(server));
|
||||
length = cifs_read_from_socket(server, buf,
|
||||
MID_HEADER_SIZE(server));
|
||||
if (length < 0)
|
||||
continue;
|
||||
server->total_read += length;
|
||||
@@ -1348,6 +1344,8 @@ next_pdu:
|
||||
bufs[0] = buf;
|
||||
num_mids = 1;
|
||||
|
||||
if (mids[0])
|
||||
mids[0]->response_pdu_len = pdu_length;
|
||||
if (!mids[0] || !mids[0]->receive)
|
||||
length = standard_receive3(server, mids[0]);
|
||||
else
|
||||
@@ -1406,7 +1404,7 @@ next_pdu:
|
||||
smb2_add_credits_from_hdr(bufs[i], server);
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
if (server->ops->dump_detail)
|
||||
server->ops->dump_detail(bufs[i],
|
||||
server->ops->dump_detail(bufs[i], pdu_length,
|
||||
server);
|
||||
cifs_dump_mids(server);
|
||||
#endif /* CIFS_DEBUG2 */
|
||||
@@ -3999,7 +3997,7 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
|
||||
TCONX_RSP *pSMBr;
|
||||
unsigned char *bcc_ptr;
|
||||
int rc = 0;
|
||||
int length;
|
||||
int length, in_len;
|
||||
__u16 bytes_left, count;
|
||||
|
||||
if (ses == NULL)
|
||||
@@ -4011,8 +4009,8 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
|
||||
|
||||
smb_buffer_response = smb_buffer;
|
||||
|
||||
header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
|
||||
NULL /*no tid */, 4 /*wct */);
|
||||
in_len = header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX,
|
||||
NULL /*no tid */, 4 /*wct */);
|
||||
|
||||
smb_buffer->Mid = get_next_mid(ses->server);
|
||||
smb_buffer->Uid = ses->Suid;
|
||||
@@ -4053,11 +4051,11 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
|
||||
bcc_ptr += strlen("?????");
|
||||
bcc_ptr += 1;
|
||||
count = bcc_ptr - &pSMB->Password[0];
|
||||
be32_add_cpu(&pSMB->hdr.smb_buf_length, count);
|
||||
in_len += count;
|
||||
pSMB->ByteCount = cpu_to_le16(count);
|
||||
|
||||
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
|
||||
0);
|
||||
rc = SendReceive(xid, ses, smb_buffer, in_len, smb_buffer_response,
|
||||
&length, 0);
|
||||
|
||||
/* above now done in SendReceive */
|
||||
if (rc == 0) {
|
||||
|
||||
@@ -264,19 +264,18 @@ free_rsp_buf(int resp_buftype, void *rsp)
|
||||
|
||||
/* NB: MID can not be set if treeCon not passed in, in that
|
||||
case it is responsibility of caller to set the mid */
|
||||
void
|
||||
header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||
unsigned int
|
||||
header_assemble(struct smb_hdr *buffer, char smb_command,
|
||||
const struct cifs_tcon *treeCon, int word_count
|
||||
/* length of fixed section (word count) in two byte units */)
|
||||
{
|
||||
unsigned int in_len;
|
||||
char *temp = (char *) buffer;
|
||||
|
||||
memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */
|
||||
|
||||
buffer->smb_buf_length = cpu_to_be32(
|
||||
(2 * word_count) + sizeof(struct smb_hdr) -
|
||||
4 /* RFC 1001 length field does not count */ +
|
||||
2 /* for bcc field itself */) ;
|
||||
in_len = (2 * word_count) + sizeof(struct smb_hdr) +
|
||||
2 /* for bcc field itself */;
|
||||
|
||||
buffer->Protocol[0] = 0xFF;
|
||||
buffer->Protocol[1] = 'S';
|
||||
@@ -311,7 +310,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ ,
|
||||
|
||||
/* endian conversion of flags is now done just before sending */
|
||||
buffer->WordCount = (char) word_count;
|
||||
return;
|
||||
return in_len;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -346,10 +345,11 @@ check_smb_hdr(struct smb_hdr *smb)
|
||||
}
|
||||
|
||||
int
|
||||
checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
|
||||
checkSMB(char *buf, unsigned int pdu_len, unsigned int total_read,
|
||||
struct TCP_Server_Info *server)
|
||||
{
|
||||
struct smb_hdr *smb = (struct smb_hdr *)buf;
|
||||
__u32 rfclen = be32_to_cpu(smb->smb_buf_length);
|
||||
__u32 rfclen = pdu_len;
|
||||
__u32 clc_len; /* calculated length */
|
||||
cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x\n",
|
||||
total_read, rfclen);
|
||||
@@ -394,24 +394,24 @@ checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
|
||||
return -EIO;
|
||||
clc_len = smbCalcSize(smb);
|
||||
|
||||
if (4 + rfclen != total_read) {
|
||||
cifs_dbg(VFS, "Length read does not match RFC1001 length %d\n",
|
||||
rfclen);
|
||||
if (rfclen != total_read) {
|
||||
cifs_dbg(VFS, "Length read does not match RFC1001 length %d/%d\n",
|
||||
rfclen, total_read);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (4 + rfclen != clc_len) {
|
||||
if (rfclen != clc_len) {
|
||||
__u16 mid = get_mid(smb);
|
||||
/* check if bcc wrapped around for large read responses */
|
||||
if ((rfclen > 64 * 1024) && (rfclen > clc_len)) {
|
||||
/* check if lengths match mod 64K */
|
||||
if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
|
||||
if (((rfclen) & 0xFFFF) == (clc_len & 0xFFFF))
|
||||
return 0; /* bcc wrapped */
|
||||
}
|
||||
cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u\n",
|
||||
clc_len, 4 + rfclen, mid);
|
||||
clc_len, rfclen, mid);
|
||||
|
||||
if (4 + rfclen < clc_len) {
|
||||
if (rfclen < clc_len) {
|
||||
cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u\n",
|
||||
rfclen, mid);
|
||||
return -EIO;
|
||||
@@ -451,7 +451,7 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
|
||||
(struct smb_com_transaction_change_notify_rsp *)buf;
|
||||
struct file_notify_information *pnotify;
|
||||
__u32 data_offset = 0;
|
||||
size_t len = srv->total_read - sizeof(pSMBr->hdr.smb_buf_length);
|
||||
size_t len = srv->total_read - srv->pdu_size;
|
||||
|
||||
if (get_bcc(buf) > sizeof(struct file_notify_information)) {
|
||||
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
||||
|
||||
@@ -1313,6 +1313,7 @@ struct sess_data {
|
||||
struct nls_table *nls_cp;
|
||||
void (*func)(struct sess_data *);
|
||||
int result;
|
||||
unsigned int in_len;
|
||||
|
||||
/* we will send the SMB in three pieces:
|
||||
* a fixed length beginning part, an optional
|
||||
@@ -1336,11 +1337,12 @@ sess_alloc_buffer(struct sess_data *sess_data, int wct)
|
||||
rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
|
||||
(void **)&smb_buf);
|
||||
|
||||
if (rc)
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
sess_data->in_len = rc;
|
||||
sess_data->iov[0].iov_base = (char *)smb_buf;
|
||||
sess_data->iov[0].iov_len = be32_to_cpu(smb_buf->smb_buf_length) + 4;
|
||||
sess_data->iov[0].iov_len = sess_data->in_len;
|
||||
/*
|
||||
* This variable will be used to clear the buffer
|
||||
* allocated above in case of any error in the calling function.
|
||||
@@ -1418,7 +1420,7 @@ sess_sendreceive(struct sess_data *sess_data)
|
||||
struct kvec rsp_iov = { NULL, 0 };
|
||||
|
||||
count = sess_data->iov[1].iov_len + sess_data->iov[2].iov_len;
|
||||
be32_add_cpu(&smb_buf->smb_buf_length, count);
|
||||
sess_data->in_len += count;
|
||||
put_bcc(count, smb_buf);
|
||||
|
||||
rc = SendReceive2(sess_data->xid, sess_data->ses,
|
||||
|
||||
@@ -35,15 +35,15 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
|
||||
{
|
||||
int rc = 0;
|
||||
struct smb_hdr *in_buf = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
|
||||
unsigned int in_len = rqst->rq_iov[0].iov_len;
|
||||
|
||||
/* -4 for RFC1001 length and +2 for BCC field */
|
||||
in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2);
|
||||
/* +2 for BCC field */
|
||||
in_buf->Command = SMB_COM_NT_CANCEL;
|
||||
in_buf->WordCount = 0;
|
||||
put_bcc(0, in_buf);
|
||||
|
||||
cifs_server_lock(server);
|
||||
rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
|
||||
rc = cifs_sign_smb(in_buf, in_len, server, &mid->sequence_number);
|
||||
if (rc) {
|
||||
cifs_server_unlock(server);
|
||||
return rc;
|
||||
@@ -55,7 +55,7 @@ send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
|
||||
* after signing here.
|
||||
*/
|
||||
--server->sequence_number;
|
||||
rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
|
||||
rc = smb_send(server, in_buf, in_len);
|
||||
if (rc < 0)
|
||||
server->sequence_number--;
|
||||
|
||||
@@ -289,7 +289,7 @@ check2ndT2(char *buf)
|
||||
}
|
||||
|
||||
static int
|
||||
coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
|
||||
coalesce_t2(char *second_buf, struct smb_hdr *target_hdr, unsigned int *pdu_len)
|
||||
{
|
||||
struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf;
|
||||
struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr;
|
||||
@@ -355,15 +355,15 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr)
|
||||
}
|
||||
put_bcc(byte_count, target_hdr);
|
||||
|
||||
byte_count = be32_to_cpu(target_hdr->smb_buf_length);
|
||||
byte_count = *pdu_len;
|
||||
byte_count += total_in_src;
|
||||
/* don't allow buffer to overflow */
|
||||
if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
|
||||
if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
|
||||
cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n",
|
||||
byte_count);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
target_hdr->smb_buf_length = cpu_to_be32(byte_count);
|
||||
*pdu_len = byte_count;
|
||||
|
||||
/* copy second buffer into end of first buffer */
|
||||
memcpy(data_area_of_tgt, data_area_of_src, total_in_src);
|
||||
@@ -398,7 +398,7 @@ cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server,
|
||||
mid->multiRsp = true;
|
||||
if (mid->resp_buf) {
|
||||
/* merge response - fix up 1st*/
|
||||
malformed = coalesce_t2(buf, mid->resp_buf);
|
||||
malformed = coalesce_t2(buf, mid->resp_buf, &mid->response_pdu_len);
|
||||
if (malformed > 0)
|
||||
return true;
|
||||
/* All parts received or packet is malformed. */
|
||||
@@ -461,7 +461,7 @@ smb1_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx)
|
||||
if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
|
||||
(!(server->capabilities & CAP_UNIX) && server->sign))
|
||||
wsize = min_t(unsigned int, wsize,
|
||||
server->maxBuf - sizeof(WRITE_REQ) + 4);
|
||||
server->maxBuf - sizeof(WRITE_REQ));
|
||||
|
||||
/* hard limit of CIFS_MAX_WSIZE */
|
||||
wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
|
||||
@@ -1487,7 +1487,6 @@ struct smb_version_values smb1_values = {
|
||||
.exclusive_lock_type = 0,
|
||||
.shared_lock_type = LOCKING_ANDX_SHARED_LOCK,
|
||||
.unlock_lock_type = 0,
|
||||
.header_preamble_size = 4,
|
||||
.header_size = sizeof(struct smb_hdr),
|
||||
.max_header_size = MAX_CIFS_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(READ_RSP),
|
||||
|
||||
@@ -134,7 +134,8 @@ static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len,
|
||||
}
|
||||
|
||||
int
|
||||
smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *server)
|
||||
smb2_check_message(char *buf, unsigned int pdu_len, unsigned int len,
|
||||
struct TCP_Server_Info *server)
|
||||
{
|
||||
struct TCP_Server_Info *pserver;
|
||||
struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
|
||||
|
||||
@@ -432,7 +432,7 @@ smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
|
||||
}
|
||||
|
||||
static void
|
||||
smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
|
||||
smb2_dump_detail(void *buf, size_t buf_len, struct TCP_Server_Info *server)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_DEBUG2
|
||||
struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
|
||||
@@ -440,7 +440,7 @@ smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
|
||||
cifs_server_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
|
||||
shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
|
||||
shdr->Id.SyncId.ProcessId);
|
||||
if (!server->ops->check_message(buf, server->total_read, server)) {
|
||||
if (!server->ops->check_message(buf, buf_len, server->total_read, server)) {
|
||||
cifs_server_dbg(VFS, "smb buf %p len %u\n", buf,
|
||||
server->ops->calc_smb_size(buf));
|
||||
}
|
||||
@@ -5767,7 +5767,6 @@ struct smb_version_values smb20_values = {
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
|
||||
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
|
||||
.header_size = sizeof(struct smb2_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
@@ -5789,7 +5788,6 @@ struct smb_version_values smb21_values = {
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
|
||||
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
|
||||
.header_size = sizeof(struct smb2_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
@@ -5810,7 +5808,6 @@ struct smb_version_values smb3any_values = {
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
|
||||
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
|
||||
.header_size = sizeof(struct smb2_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
@@ -5831,7 +5828,6 @@ struct smb_version_values smbdefault_values = {
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
|
||||
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
|
||||
.header_size = sizeof(struct smb2_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
@@ -5852,7 +5848,6 @@ struct smb_version_values smb30_values = {
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
|
||||
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
|
||||
.header_size = sizeof(struct smb2_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
@@ -5873,7 +5868,6 @@ struct smb_version_values smb302_values = {
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
|
||||
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
|
||||
.header_size = sizeof(struct smb2_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
@@ -5894,7 +5888,6 @@ struct smb_version_values smb311_values = {
|
||||
.shared_lock_type = SMB2_LOCKFLAG_SHARED,
|
||||
.unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
|
||||
.header_size = sizeof(struct smb2_hdr),
|
||||
.header_preamble_size = 0,
|
||||
.max_header_size = MAX_SMB2_HDR_SIZE,
|
||||
.read_rsp_size = sizeof(struct smb2_read_rsp),
|
||||
.lock_cmd = SMB2_LOCK,
|
||||
|
||||
@@ -4532,7 +4532,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
|
||||
.rreq_debug_id = rdata->rreq->debug_id,
|
||||
.rreq_debug_index = rdata->subreq.debug_index,
|
||||
};
|
||||
struct smb_rqst rqst = { .rq_iov = &rdata->iov[1], .rq_nvec = 1 };
|
||||
struct smb_rqst rqst = { .rq_iov = &rdata->iov[0], .rq_nvec = 1 };
|
||||
unsigned int rreq_debug_id = rdata->rreq->debug_id;
|
||||
unsigned int subreq_debug_index = rdata->subreq.debug_index;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ struct smb_rqst;
|
||||
*****************************************************************
|
||||
*/
|
||||
extern int map_smb2_to_linux_error(char *buf, bool log_err);
|
||||
extern int smb2_check_message(char *buf, unsigned int length,
|
||||
extern int smb2_check_message(char *buf, unsigned int pdu_len, unsigned int length,
|
||||
struct TCP_Server_Info *server);
|
||||
extern unsigned int smb2_calc_size(void *buf);
|
||||
extern char *smb2_get_data_area_len(int *off, int *len,
|
||||
|
||||
@@ -289,8 +289,8 @@ int __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
|
||||
sigfillset(&mask);
|
||||
sigprocmask(SIG_BLOCK, &mask, &oldmask);
|
||||
|
||||
/* Generate a rfc1002 marker for SMB2+ */
|
||||
if (!is_smb1(server)) {
|
||||
/* Generate a rfc1002 marker */
|
||||
{
|
||||
struct kvec hiov = {
|
||||
.iov_base = &rfc1002_marker,
|
||||
.iov_len = 4
|
||||
@@ -640,13 +640,13 @@ cifs_wait_mtu_credits(struct TCP_Server_Info *server, size_t size,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
|
||||
int wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = wait_event_state(server->response_q,
|
||||
midQ->mid_state != MID_REQUEST_SUBMITTED &&
|
||||
midQ->mid_state != MID_RESPONSE_RECEIVED,
|
||||
mid->mid_state != MID_REQUEST_SUBMITTED &&
|
||||
mid->mid_state != MID_RESPONSE_RECEIVED,
|
||||
(TASK_KILLABLE|TASK_FREEZABLE_UNSAFE));
|
||||
if (error < 0)
|
||||
return -ERESTARTSYS;
|
||||
@@ -866,7 +866,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
||||
int *resp_buf_type, struct kvec *resp_iov)
|
||||
{
|
||||
int i, j, optype, rc = 0;
|
||||
struct mid_q_entry *midQ[MAX_COMPOUND];
|
||||
struct mid_q_entry *mid[MAX_COMPOUND];
|
||||
bool cancelled_mid[MAX_COMPOUND] = {false};
|
||||
struct cifs_credits credits[MAX_COMPOUND] = {
|
||||
{ .value = 0, .instance = 0 }
|
||||
@@ -932,35 +932,35 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
||||
}
|
||||
|
||||
for (i = 0; i < num_rqst; i++) {
|
||||
midQ[i] = server->ops->setup_request(ses, server, &rqst[i]);
|
||||
if (IS_ERR(midQ[i])) {
|
||||
mid[i] = server->ops->setup_request(ses, server, &rqst[i]);
|
||||
if (IS_ERR(mid[i])) {
|
||||
revert_current_mid(server, i);
|
||||
for (j = 0; j < i; j++)
|
||||
delete_mid(midQ[j]);
|
||||
delete_mid(mid[j]);
|
||||
cifs_server_unlock(server);
|
||||
|
||||
/* Update # of requests on wire to server */
|
||||
for (j = 0; j < num_rqst; j++)
|
||||
add_credits(server, &credits[j], optype);
|
||||
return PTR_ERR(midQ[i]);
|
||||
return PTR_ERR(mid[i]);
|
||||
}
|
||||
|
||||
midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
|
||||
midQ[i]->optype = optype;
|
||||
mid[i]->mid_state = MID_REQUEST_SUBMITTED;
|
||||
mid[i]->optype = optype;
|
||||
/*
|
||||
* Invoke callback for every part of the compound chain
|
||||
* to calculate credits properly. Wake up this thread only when
|
||||
* the last element is received.
|
||||
*/
|
||||
if (i < num_rqst - 1)
|
||||
midQ[i]->callback = cifs_compound_callback;
|
||||
mid[i]->callback = cifs_compound_callback;
|
||||
else
|
||||
midQ[i]->callback = cifs_compound_last_callback;
|
||||
mid[i]->callback = cifs_compound_last_callback;
|
||||
}
|
||||
rc = smb_send_rqst(server, num_rqst, rqst, flags);
|
||||
|
||||
for (i = 0; i < num_rqst; i++)
|
||||
cifs_save_when_sent(midQ[i]);
|
||||
cifs_save_when_sent(mid[i]);
|
||||
|
||||
if (rc < 0) {
|
||||
revert_current_mid(server, num_rqst);
|
||||
@@ -1003,23 +1003,23 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
||||
spin_unlock(&ses->ses_lock);
|
||||
|
||||
for (i = 0; i < num_rqst; i++) {
|
||||
rc = wait_for_response(server, midQ[i]);
|
||||
rc = wait_for_response(server, mid[i]);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
if (rc != 0) {
|
||||
for (; i < num_rqst; i++) {
|
||||
cifs_server_dbg(FYI, "Cancelling wait for mid %llu cmd: %d\n",
|
||||
midQ[i]->mid, le16_to_cpu(midQ[i]->command));
|
||||
send_cancel(server, &rqst[i], midQ[i]);
|
||||
spin_lock(&midQ[i]->mid_lock);
|
||||
midQ[i]->wait_cancelled = true;
|
||||
if (midQ[i]->callback) {
|
||||
midQ[i]->callback = cifs_cancelled_callback;
|
||||
mid[i]->mid, le16_to_cpu(mid[i]->command));
|
||||
send_cancel(server, &rqst[i], mid[i]);
|
||||
spin_lock(&mid[i]->mid_lock);
|
||||
mid[i]->wait_cancelled = true;
|
||||
if (mid[i]->callback) {
|
||||
mid[i]->callback = cifs_cancelled_callback;
|
||||
cancelled_mid[i] = true;
|
||||
credits[i].value = 0;
|
||||
}
|
||||
spin_unlock(&midQ[i]->mid_lock);
|
||||
spin_unlock(&mid[i]->mid_lock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1027,36 +1027,35 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
rc = cifs_sync_mid_result(midQ[i], server);
|
||||
rc = cifs_sync_mid_result(mid[i], server);
|
||||
if (rc != 0) {
|
||||
/* mark this mid as cancelled to not free it below */
|
||||
cancelled_mid[i] = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!midQ[i]->resp_buf ||
|
||||
midQ[i]->mid_state != MID_RESPONSE_READY) {
|
||||
if (!mid[i]->resp_buf ||
|
||||
mid[i]->mid_state != MID_RESPONSE_READY) {
|
||||
rc = -EIO;
|
||||
cifs_dbg(FYI, "Bad MID state?\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf = (char *)midQ[i]->resp_buf;
|
||||
buf = (char *)mid[i]->resp_buf;
|
||||
resp_iov[i].iov_base = buf;
|
||||
resp_iov[i].iov_len = midQ[i]->resp_buf_size +
|
||||
HEADER_PREAMBLE_SIZE(server);
|
||||
resp_iov[i].iov_len = mid[i]->resp_buf_size;
|
||||
|
||||
if (midQ[i]->large_buf)
|
||||
if (mid[i]->large_buf)
|
||||
resp_buf_type[i] = CIFS_LARGE_BUFFER;
|
||||
else
|
||||
resp_buf_type[i] = CIFS_SMALL_BUFFER;
|
||||
|
||||
rc = server->ops->check_receive(midQ[i], server,
|
||||
rc = server->ops->check_receive(mid[i], server,
|
||||
flags & CIFS_LOG_ERROR);
|
||||
|
||||
/* mark it so buf will not be freed by delete_mid */
|
||||
if ((flags & CIFS_NO_RSP_BUF) == 0)
|
||||
midQ[i]->resp_buf = NULL;
|
||||
mid[i]->resp_buf = NULL;
|
||||
|
||||
}
|
||||
|
||||
@@ -1086,7 +1085,7 @@ out:
|
||||
*/
|
||||
for (i = 0; i < num_rqst; i++) {
|
||||
if (!cancelled_mid[i])
|
||||
delete_mid(midQ[i]);
|
||||
delete_mid(mid[i]);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -1111,8 +1110,7 @@ int
|
||||
cifs_discard_remaining_data(struct TCP_Server_Info *server)
|
||||
{
|
||||
unsigned int rfclen = server->pdu_size;
|
||||
size_t remaining = rfclen + HEADER_PREAMBLE_SIZE(server) -
|
||||
server->total_read;
|
||||
size_t remaining = rfclen - server->total_read;
|
||||
|
||||
while (remaining > 0) {
|
||||
ssize_t length;
|
||||
@@ -1157,7 +1155,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
unsigned int data_offset, data_len;
|
||||
struct cifs_io_subrequest *rdata = mid->callback_data;
|
||||
char *buf = server->smallbuf;
|
||||
unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server);
|
||||
unsigned int buflen = server->pdu_size;
|
||||
bool use_rdma_mr = false;
|
||||
|
||||
cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%zu\n",
|
||||
@@ -1191,14 +1189,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
|
||||
/* set up first two iov for signature check and to get credits */
|
||||
rdata->iov[0].iov_base = buf;
|
||||
rdata->iov[0].iov_len = HEADER_PREAMBLE_SIZE(server);
|
||||
rdata->iov[1].iov_base = buf + HEADER_PREAMBLE_SIZE(server);
|
||||
rdata->iov[1].iov_len =
|
||||
server->total_read - HEADER_PREAMBLE_SIZE(server);
|
||||
rdata->iov[0].iov_len = server->total_read;
|
||||
cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
|
||||
rdata->iov[0].iov_base, rdata->iov[0].iov_len);
|
||||
cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
|
||||
rdata->iov[1].iov_base, rdata->iov[1].iov_len);
|
||||
|
||||
/* Was the SMB read successful? */
|
||||
rdata->result = server->ops->map_error(buf, false);
|
||||
@@ -1218,8 +1211,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
return cifs_readv_discard(server, mid);
|
||||
}
|
||||
|
||||
data_offset = server->ops->read_data_offset(buf) +
|
||||
HEADER_PREAMBLE_SIZE(server);
|
||||
data_offset = server->ops->read_data_offset(buf);
|
||||
if (data_offset < server->total_read) {
|
||||
/*
|
||||
* win2k8 sometimes sends an offset of 0 when the read
|
||||
@@ -1248,6 +1240,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
||||
if (length < 0)
|
||||
return length;
|
||||
server->total_read += length;
|
||||
rdata->iov[0].iov_len = server->total_read;
|
||||
}
|
||||
|
||||
/* how much data is in the response? */
|
||||
|
||||
@@ -2016,9 +2016,6 @@ struct smb2_lease_ack {
|
||||
* MS-SMB 2.2.3.1
|
||||
*/
|
||||
struct smb_hdr {
|
||||
__be32 smb_buf_length; /* BB length is only two (rarely three) bytes,
|
||||
with one or two byte "type" preceding it that will be
|
||||
zero - we could mask the type byte off */
|
||||
__u8 Protocol[4];
|
||||
__u8 Command;
|
||||
union {
|
||||
|
||||
@@ -26,7 +26,6 @@ struct smb_version_values {
|
||||
__u32 exclusive_lock_type;
|
||||
__u32 shared_lock_type;
|
||||
__u32 unlock_lock_type;
|
||||
size_t header_preamble_size;
|
||||
size_t header_size;
|
||||
size_t max_header_size;
|
||||
size_t read_rsp_size;
|
||||
|
||||
Reference in New Issue
Block a user