|
@@ -77,45 +77,42 @@ static const int smb2_req_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
|
|
|
/* SMB2_OPLOCK_BREAK */ 24 /* BB this is 36 for LEASE_BREAK variant */
|
|
|
};
|
|
|
|
|
|
+static int encryption_required(const struct cifs_tcon *tcon)
|
|
|
+{
|
|
|
+ if (!tcon)
|
|
|
+ return 0;
|
|
|
+ if ((tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) ||
|
|
|
+ (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA))
|
|
|
+ return 1;
|
|
|
+ if (tcon->seal &&
|
|
|
+ (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
|
|
|
+ return 1;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
static void
|
|
|
-smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
|
|
|
+smb2_hdr_assemble(struct smb2_sync_hdr *shdr, __le16 smb2_cmd,
|
|
|
const struct cifs_tcon *tcon)
|
|
|
{
|
|
|
- struct smb2_pdu *pdu = (struct smb2_pdu *)hdr;
|
|
|
- char *temp = (char *)hdr;
|
|
|
- /* lookup word count ie StructureSize from table */
|
|
|
- __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_cmd)];
|
|
|
-
|
|
|
- /*
|
|
|
- * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
|
|
|
- * largest operations (Create)
|
|
|
- */
|
|
|
- memset(temp, 0, 256);
|
|
|
-
|
|
|
- /* Note this is only network field converted to big endian */
|
|
|
- hdr->smb2_buf_length = cpu_to_be32(parmsize + sizeof(struct smb2_hdr)
|
|
|
- - 4 /* RFC 1001 length field itself not counted */);
|
|
|
-
|
|
|
- hdr->ProtocolId = SMB2_PROTO_NUMBER;
|
|
|
- hdr->StructureSize = cpu_to_le16(64);
|
|
|
- hdr->Command = smb2_cmd;
|
|
|
+ shdr->ProtocolId = SMB2_PROTO_NUMBER;
|
|
|
+ shdr->StructureSize = cpu_to_le16(64);
|
|
|
+ shdr->Command = smb2_cmd;
|
|
|
if (tcon && tcon->ses && tcon->ses->server) {
|
|
|
struct TCP_Server_Info *server = tcon->ses->server;
|
|
|
|
|
|
spin_lock(&server->req_lock);
|
|
|
/* Request up to 2 credits but don't go over the limit. */
|
|
|
if (server->credits >= server->max_credits)
|
|
|
- hdr->CreditRequest = cpu_to_le16(0);
|
|
|
+ shdr->CreditRequest = cpu_to_le16(0);
|
|
|
else
|
|
|
- hdr->CreditRequest = cpu_to_le16(
|
|
|
+ shdr->CreditRequest = cpu_to_le16(
|
|
|
min_t(int, server->max_credits -
|
|
|
server->credits, 2));
|
|
|
spin_unlock(&server->req_lock);
|
|
|
} 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)
|
|
|
goto out;
|
|
@@ -124,13 +121,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 */
|
|
|
if ((tcon->ses) && (tcon->ses->server) &&
|
|
|
(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU))
|
|
|
- hdr->CreditCharge = cpu_to_le16(1);
|
|
|
+ shdr->CreditCharge = cpu_to_le16(1);
|
|
|
/* else CreditCharge MBZ */
|
|
|
|
|
|
- hdr->TreeId = tcon->tid;
|
|
|
+ shdr->TreeId = tcon->tid;
|
|
|
/* Uid is not converted */
|
|
|
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
|
|
@@ -143,12 +140,12 @@ smb2_hdr_assemble(struct smb2_hdr *hdr, __le16 smb2_cmd /* command */ ,
|
|
|
* but it is safer to net set it for now.
|
|
|
*/
|
|
|
/* 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)
|
|
|
- hdr->Flags |= SMB2_FLAGS_SIGNED;
|
|
|
+ if (tcon->ses && tcon->ses->server && tcon->ses->server->sign &&
|
|
|
+ !encryption_required(tcon))
|
|
|
+ shdr->Flags |= SMB2_FLAGS_SIGNED;
|
|
|
out:
|
|
|
- pdu->StructureSize2 = cpu_to_le16(parmsize);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -289,16 +286,74 @@ out:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+fill_small_buf(__le16 smb2_command, struct cifs_tcon *tcon, void *buf,
|
|
|
+ unsigned int *total_len)
|
|
|
+{
|
|
|
+ struct smb2_sync_pdu *spdu = (struct smb2_sync_pdu *)buf;
|
|
|
+ /* lookup word count ie StructureSize from table */
|
|
|
+ __u16 parmsize = smb2_req_struct_sizes[le16_to_cpu(smb2_command)];
|
|
|
+
|
|
|
+ /*
|
|
|
+ * smaller than SMALL_BUFFER_SIZE but bigger than fixed area of
|
|
|
+ * largest operations (Create)
|
|
|
+ */
|
|
|
+ memset(buf, 0, 256);
|
|
|
+
|
|
|
+ smb2_hdr_assemble(&spdu->sync_hdr, smb2_command, tcon);
|
|
|
+ spdu->StructureSize2 = cpu_to_le16(parmsize);
|
|
|
+
|
|
|
+ *total_len = parmsize + sizeof(struct smb2_sync_hdr);
|
|
|
+}
|
|
|
+
|
|
|
+/* init request without RFC1001 length at the beginning */
|
|
|
+static int
|
|
|
+smb2_plain_req_init(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
|
+ void **request_buf, unsigned int *total_len)
|
|
|
+{
|
|
|
+ int rc;
|
|
|
+ struct smb2_sync_hdr *shdr;
|
|
|
+
|
|
|
+ rc = smb2_reconnect(smb2_command, tcon);
|
|
|
+ if (rc)
|
|
|
+ return rc;
|
|
|
+
|
|
|
+ /* BB eventually switch this to SMB2 specific small buf size */
|
|
|
+ *request_buf = cifs_small_buf_get();
|
|
|
+ if (*request_buf == NULL) {
|
|
|
+ /* BB should we add a retry in here if not a writepage? */
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ shdr = (struct smb2_sync_hdr *)(*request_buf);
|
|
|
+
|
|
|
+ fill_small_buf(smb2_command, tcon, shdr, total_len);
|
|
|
+
|
|
|
+ if (tcon != NULL) {
|
|
|
+#ifdef CONFIG_CIFS_STATS2
|
|
|
+ uint16_t com_code = le16_to_cpu(smb2_command);
|
|
|
+
|
|
|
+ cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
|
|
|
+#endif
|
|
|
+ cifs_stats_inc(&tcon->num_smbs_sent);
|
|
|
+ }
|
|
|
+
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Allocate and return pointer to an SMB request hdr, and set basic
|
|
|
* SMB information in the SMB header. If the return code is zero, this
|
|
|
- * function must have filled in request_buf pointer.
|
|
|
+ * function must have filled in request_buf pointer. The returned buffer
|
|
|
+ * has RFC1001 length at the beginning.
|
|
|
*/
|
|
|
static int
|
|
|
small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
|
void **request_buf)
|
|
|
{
|
|
|
- int rc = 0;
|
|
|
+ int rc;
|
|
|
+ unsigned int total_len;
|
|
|
+ struct smb2_pdu *pdu;
|
|
|
|
|
|
rc = smb2_reconnect(smb2_command, tcon);
|
|
|
if (rc)
|
|
@@ -311,7 +366,12 @@ small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- smb2_hdr_assemble((struct smb2_hdr *) *request_buf, smb2_command, tcon);
|
|
|
+ pdu = (struct smb2_pdu *)(*request_buf);
|
|
|
+
|
|
|
+ fill_small_buf(smb2_command, tcon, get_sync_hdr(pdu), &total_len);
|
|
|
+
|
|
|
+ /* Note this is only network field converted to big endian */
|
|
|
+ pdu->hdr.smb2_buf_length = cpu_to_be32(total_len);
|
|
|
|
|
|
if (tcon != NULL) {
|
|
|
#ifdef CONFIG_CIFS_STATS2
|
|
@@ -376,7 +436,6 @@ static void assemble_neg_contexts(struct smb2_negotiate_req *req)
|
|
|
}
|
|
|
#endif /* SMB311 */
|
|
|
|
|
|
-
|
|
|
/*
|
|
|
*
|
|
|
* SMB2 Worker functions follow:
|
|
@@ -398,6 +457,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
|
|
|
struct smb2_negotiate_req *req;
|
|
|
struct smb2_negotiate_rsp *rsp;
|
|
|
struct kvec iov[1];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int rc = 0;
|
|
|
int resp_buftype;
|
|
|
struct TCP_Server_Info *server = ses->server;
|
|
@@ -416,7 +476,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- req->hdr.SessionId = 0;
|
|
|
+ req->hdr.sync_hdr.SessionId = 0;
|
|
|
|
|
|
req->Dialects[0] = cpu_to_le16(ses->server->vals->protocol_id);
|
|
|
|
|
@@ -446,9 +506,9 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
|
|
|
/* 4 for rfc1002 length field */
|
|
|
iov[0].iov_len = get_rfc1002_length(req) + 4;
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags);
|
|
|
-
|
|
|
- rsp = (struct smb2_negotiate_rsp *)iov[0].iov_base;
|
|
|
+ rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base;
|
|
|
/*
|
|
|
* No tcon so can't do
|
|
|
* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
|
|
@@ -627,14 +687,15 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
|
|
|
if (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 */
|
|
|
req->PreviousSessionId = sess_data->previous_session;
|
|
|
|
|
|
req->Flags = 0; /* MBZ */
|
|
|
/* 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 */
|
|
|
if (server->sign)
|
|
@@ -671,6 +732,7 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
|
|
|
{
|
|
|
int rc;
|
|
|
struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base;
|
|
|
+ struct kvec rsp_iov = { NULL, 0 };
|
|
|
|
|
|
/* Testing shows that buffer offset must be at location of Buffer[0] */
|
|
|
req->SecurityBufferOffset =
|
|
@@ -685,7 +747,9 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
|
|
|
rc = SendReceive2(sess_data->xid, sess_data->ses,
|
|
|
sess_data->iov, 2,
|
|
|
&sess_data->buf0_type,
|
|
|
- CIFS_LOG_ERROR | CIFS_NEG_OP);
|
|
|
+ CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov);
|
|
|
+ cifs_small_buf_release(sess_data->iov[0].iov_base);
|
|
|
+ memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
|
|
|
|
|
|
return rc;
|
|
|
}
|
|
@@ -697,15 +761,13 @@ SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
|
|
|
struct cifs_ses *ses = sess_data->ses;
|
|
|
|
|
|
mutex_lock(&ses->server->srv_mutex);
|
|
|
- if (ses->server->sign && ses->server->ops->generate_signingkey) {
|
|
|
+ if (ses->server->ops->generate_signingkey) {
|
|
|
rc = ses->server->ops->generate_signingkey(ses);
|
|
|
- kfree(ses->auth_key.response);
|
|
|
- ses->auth_key.response = NULL;
|
|
|
if (rc) {
|
|
|
cifs_dbg(FYI,
|
|
|
"SMB3 session key generation failed\n");
|
|
|
mutex_unlock(&ses->server->srv_mutex);
|
|
|
- goto keygen_exit;
|
|
|
+ return rc;
|
|
|
}
|
|
|
}
|
|
|
if (!ses->server->session_estab) {
|
|
@@ -719,12 +781,6 @@ SMB2_sess_establish_session(struct SMB2_sess_data *sess_data)
|
|
|
ses->status = CifsGood;
|
|
|
ses->need_reconnect = false;
|
|
|
spin_unlock(&GlobalMid_Lock);
|
|
|
-
|
|
|
-keygen_exit:
|
|
|
- if (!ses->server->sign) {
|
|
|
- kfree(ses->auth_key.response);
|
|
|
- ses->auth_key.response = NULL;
|
|
|
- }
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -781,11 +837,9 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
|
|
|
goto out_put_spnego_key;
|
|
|
|
|
|
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);
|
|
|
- if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
|
|
|
- cifs_dbg(VFS, "SMB3 encryption not supported yet\n");
|
|
|
|
|
|
rc = SMB2_sess_establish_session(sess_data);
|
|
|
out_put_spnego_key:
|
|
@@ -859,7 +913,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
|
|
|
|
|
|
/* If true, rc here is expected and not an error */
|
|
|
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;
|
|
|
|
|
|
if (rc)
|
|
@@ -880,10 +934,8 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
|
|
|
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);
|
|
|
- if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
|
|
|
- cifs_dbg(VFS, "SMB3 encryption not supported yet\n");
|
|
|
|
|
|
out:
|
|
|
kfree(ntlmssp_blob);
|
|
@@ -916,7 +968,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
|
|
|
goto out;
|
|
|
|
|
|
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,
|
|
|
sess_data->nls_cp);
|
|
@@ -940,10 +992,8 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
|
|
|
|
|
|
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);
|
|
|
- if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
|
|
|
- cifs_dbg(VFS, "SMB3 encryption not supported yet\n");
|
|
|
|
|
|
rc = SMB2_sess_establish_session(sess_data);
|
|
|
out:
|
|
@@ -1018,6 +1068,7 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
|
|
|
struct smb2_logoff_req *req; /* response is also trivial struct */
|
|
|
int rc = 0;
|
|
|
struct TCP_Server_Info *server;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
cifs_dbg(FYI, "disconnect session %p\n", ses);
|
|
|
|
|
@@ -1035,11 +1086,15 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
|
|
|
return rc;
|
|
|
|
|
|
/* since no tcon, smb2_init can not do this, so do here */
|
|
|
- req->hdr.SessionId = ses->Suid;
|
|
|
- if (server->sign)
|
|
|
- req->hdr.Flags |= SMB2_FLAGS_SIGNED;
|
|
|
+ req->hdr.sync_hdr.SessionId = ses->Suid;
|
|
|
+
|
|
|
+ if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA)
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+ else if (server->sign)
|
|
|
+ req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
|
|
|
|
|
|
- rc = SendReceiveNoRsp(xid, ses, (char *) &req->hdr, 0);
|
|
|
+ rc = SendReceiveNoRsp(xid, ses, (char *) req, flags);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
/*
|
|
|
* No tcon so can't do
|
|
|
* cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
|
|
@@ -1071,11 +1126,13 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
|
|
struct smb2_tree_connect_req *req;
|
|
|
struct smb2_tree_connect_rsp *rsp = NULL;
|
|
|
struct kvec iov[2];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int rc = 0;
|
|
|
int resp_buftype;
|
|
|
int unc_path_len;
|
|
|
struct TCP_Server_Info *server;
|
|
|
__le16 *unc_path = NULL;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
cifs_dbg(FYI, "TCON\n");
|
|
|
|
|
@@ -1087,12 +1144,6 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
|
|
if (tcon && tcon->bad_network_name)
|
|
|
return -ENOENT;
|
|
|
|
|
|
- if ((tcon && tcon->seal) &&
|
|
|
- ((ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) == 0)) {
|
|
|
- cifs_dbg(VFS, "encryption requested but no server support");
|
|
|
- return -EOPNOTSUPP;
|
|
|
- }
|
|
|
-
|
|
|
unc_path = kmalloc(MAX_SHARENAME_LENGTH * 2, GFP_KERNEL);
|
|
|
if (unc_path == NULL)
|
|
|
return -ENOMEM;
|
|
@@ -1111,11 +1162,15 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
|
|
}
|
|
|
|
|
|
if (tcon == NULL) {
|
|
|
+ if ((ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
/* 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)
|
|
|
req->hdr.Flags |= SMB2_FLAGS_SIGNED; */
|
|
|
- }
|
|
|
+ } else if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
|
|
|
iov[0].iov_base = (char *)req;
|
|
|
/* 4 for rfc1002 length field and 1 for pad */
|
|
@@ -1130,8 +1185,9 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
|
|
|
|
|
inc_rfc1001_len(req, unc_path_len - 1 /* pad */);
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, 0);
|
|
|
- rsp = (struct smb2_tree_connect_rsp *)iov[0].iov_base;
|
|
|
+ rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
if (rc != 0) {
|
|
|
if (tcon) {
|
|
@@ -1142,7 +1198,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
|
|
}
|
|
|
|
|
|
if (tcon == NULL) {
|
|
|
- ses->ipc_tid = rsp->hdr.TreeId;
|
|
|
+ ses->ipc_tid = rsp->hdr.sync_hdr.TreeId;
|
|
|
goto tcon_exit;
|
|
|
}
|
|
|
|
|
@@ -1165,15 +1221,18 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
|
|
|
tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
|
|
|
tcon->tidStatus = CifsGood;
|
|
|
tcon->need_reconnect = false;
|
|
|
- tcon->tid = rsp->hdr.TreeId;
|
|
|
+ tcon->tid = rsp->hdr.sync_hdr.TreeId;
|
|
|
strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
|
|
|
|
|
|
if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
|
|
|
((tcon->share_flags & SHI1005_FLAGS_DFS) == 0))
|
|
|
cifs_dbg(VFS, "DFS capability contradicts DFS flag\n");
|
|
|
+
|
|
|
+ if (tcon->seal &&
|
|
|
+ !(tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
|
|
|
+ cifs_dbg(VFS, "Encryption is requested but not supported\n");
|
|
|
+
|
|
|
init_copy_chunk_defaults(tcon);
|
|
|
- if (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)
|
|
|
- cifs_dbg(VFS, "Encrypted shares not supported");
|
|
|
if (tcon->ses->server->ops->validate_negotiate)
|
|
|
rc = tcon->ses->server->ops->validate_negotiate(xid, tcon);
|
|
|
tcon_exit:
|
|
@@ -1182,7 +1241,7 @@ tcon_exit:
|
|
|
return rc;
|
|
|
|
|
|
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);
|
|
|
if (tcon)
|
|
|
tcon->bad_network_name = true;
|
|
@@ -1197,6 +1256,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
|
|
|
int rc = 0;
|
|
|
struct TCP_Server_Info *server;
|
|
|
struct cifs_ses *ses = tcon->ses;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
cifs_dbg(FYI, "Tree Disconnect\n");
|
|
|
|
|
@@ -1212,7 +1272,11 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- rc = SendReceiveNoRsp(xid, ses, (char *)&req->hdr, 0);
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ rc = SendReceiveNoRsp(xid, ses, (char *)req, flags);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
if (rc)
|
|
|
cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE);
|
|
|
|
|
@@ -1474,14 +1538,16 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
|
|
struct cifs_tcon *tcon = oparms->tcon;
|
|
|
struct cifs_ses *ses = tcon->ses;
|
|
|
struct kvec iov[4];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int resp_buftype;
|
|
|
int uni_path_len;
|
|
|
__le16 *copy_path = NULL;
|
|
|
int copy_size;
|
|
|
int rc = 0;
|
|
|
- unsigned int num_iovecs = 2;
|
|
|
+ unsigned int n_iov = 2;
|
|
|
__u32 file_attributes = 0;
|
|
|
char *dhc_buf = NULL, *lc_buf = NULL;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
cifs_dbg(FYI, "create/open\n");
|
|
|
|
|
@@ -1494,6 +1560,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
if (oparms->create_options & CREATE_OPTION_READONLY)
|
|
|
file_attributes |= ATTR_READONLY;
|
|
|
if (oparms->create_options & CREATE_OPTION_SPECIAL)
|
|
@@ -1544,25 +1613,25 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
|
|
*oplock == SMB2_OPLOCK_LEVEL_NONE)
|
|
|
req->RequestedOplockLevel = *oplock;
|
|
|
else {
|
|
|
- rc = add_lease_context(server, iov, &num_iovecs, oplock);
|
|
|
+ rc = add_lease_context(server, iov, &n_iov, oplock);
|
|
|
if (rc) {
|
|
|
cifs_small_buf_release(req);
|
|
|
kfree(copy_path);
|
|
|
return rc;
|
|
|
}
|
|
|
- lc_buf = iov[num_iovecs-1].iov_base;
|
|
|
+ lc_buf = iov[n_iov-1].iov_base;
|
|
|
}
|
|
|
|
|
|
if (*oplock == SMB2_OPLOCK_LEVEL_BATCH) {
|
|
|
/* need to set Next field of lease context if we request it */
|
|
|
if (server->capabilities & SMB2_GLOBAL_CAP_LEASING) {
|
|
|
struct create_context *ccontext =
|
|
|
- (struct create_context *)iov[num_iovecs-1].iov_base;
|
|
|
+ (struct create_context *)iov[n_iov-1].iov_base;
|
|
|
ccontext->Next =
|
|
|
cpu_to_le32(server->vals->create_lease_size);
|
|
|
}
|
|
|
|
|
|
- rc = add_durable_context(iov, &num_iovecs, oparms,
|
|
|
+ rc = add_durable_context(iov, &n_iov, oparms,
|
|
|
tcon->use_persistent);
|
|
|
if (rc) {
|
|
|
cifs_small_buf_release(req);
|
|
@@ -1570,11 +1639,12 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
|
|
|
kfree(lc_buf);
|
|
|
return rc;
|
|
|
}
|
|
|
- dhc_buf = iov[num_iovecs-1].iov_base;
|
|
|
+ dhc_buf = iov[n_iov-1].iov_base;
|
|
|
}
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
|
|
|
- rsp = (struct smb2_create_rsp *)iov[0].iov_base;
|
|
|
+ rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
if (rc != 0) {
|
|
|
cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
|
|
@@ -1618,12 +1688,15 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
{
|
|
|
struct smb2_ioctl_req *req;
|
|
|
struct smb2_ioctl_rsp *rsp;
|
|
|
+ struct smb2_sync_hdr *shdr;
|
|
|
struct TCP_Server_Info *server;
|
|
|
struct cifs_ses *ses;
|
|
|
struct kvec iov[2];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int resp_buftype;
|
|
|
- int num_iovecs;
|
|
|
+ int n_iov;
|
|
|
int rc = 0;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
cifs_dbg(FYI, "SMB2 IOCTL\n");
|
|
|
|
|
@@ -1648,6 +1721,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
req->CtlCode = cpu_to_le32(opcode);
|
|
|
req->PersistentFileId = persistent_fid;
|
|
|
req->VolatileFileId = volatile_fid;
|
|
@@ -1659,9 +1735,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer) - 4);
|
|
|
iov[1].iov_base = in_data;
|
|
|
iov[1].iov_len = indatalen;
|
|
|
- num_iovecs = 2;
|
|
|
+ n_iov = 2;
|
|
|
} else
|
|
|
- num_iovecs = 1;
|
|
|
+ n_iov = 1;
|
|
|
|
|
|
req->OutputOffset = 0;
|
|
|
req->OutputCount = 0; /* MBZ */
|
|
@@ -1698,8 +1774,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
iov[0].iov_len = get_rfc1002_length(req) + 4;
|
|
|
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buftype, 0);
|
|
|
- rsp = (struct smb2_ioctl_rsp *)iov[0].iov_base;
|
|
|
+ rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
if ((rc != 0) && (rc != -EINVAL)) {
|
|
|
cifs_stats_fail_inc(tcon, SMB2_IOCTL_HE);
|
|
@@ -1742,9 +1819,8 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
goto ioctl_exit;
|
|
|
}
|
|
|
|
|
|
- memcpy(*out_data,
|
|
|
- (char *)&rsp->hdr.ProtocolId + le32_to_cpu(rsp->OutputOffset),
|
|
|
- *plen);
|
|
|
+ shdr = get_sync_hdr(rsp);
|
|
|
+ memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen);
|
|
|
ioctl_exit:
|
|
|
free_rsp_buf(resp_buftype, rsp);
|
|
|
return rc;
|
|
@@ -1784,8 +1860,10 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
struct TCP_Server_Info *server;
|
|
|
struct cifs_ses *ses = tcon->ses;
|
|
|
struct kvec iov[1];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int resp_buftype;
|
|
|
int rc = 0;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
cifs_dbg(FYI, "Close\n");
|
|
|
|
|
@@ -1798,6 +1876,9 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
req->PersistentFileId = persistent_fid;
|
|
|
req->VolatileFileId = volatile_fid;
|
|
|
|
|
@@ -1805,8 +1886,9 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
/* 4 for rfc1002 length field */
|
|
|
iov[0].iov_len = get_rfc1002_length(req) + 4;
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0);
|
|
|
- rsp = (struct smb2_close_rsp *)iov[0].iov_base;
|
|
|
+ rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_close_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
if (rc != 0) {
|
|
|
cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
|
|
@@ -1885,10 +1967,12 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
struct smb2_query_info_req *req;
|
|
|
struct smb2_query_info_rsp *rsp = NULL;
|
|
|
struct kvec iov[2];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int rc = 0;
|
|
|
int resp_buftype;
|
|
|
struct TCP_Server_Info *server;
|
|
|
struct cifs_ses *ses = tcon->ses;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
cifs_dbg(FYI, "Query Info\n");
|
|
|
|
|
@@ -1901,6 +1985,9 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
req->InfoType = SMB2_O_INFO_FILE;
|
|
|
req->FileInfoClass = info_class;
|
|
|
req->PersistentFileId = persistent_fid;
|
|
@@ -1914,8 +2001,9 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
/* 4 for rfc1002 length field */
|
|
|
iov[0].iov_len = get_rfc1002_length(req) + 4;
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0);
|
|
|
- rsp = (struct smb2_query_info_rsp *)iov[0].iov_base;
|
|
|
+ rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
if (rc) {
|
|
|
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
|
|
@@ -1963,11 +2051,11 @@ static void
|
|
|
smb2_echo_callback(struct mid_q_entry *mid)
|
|
|
{
|
|
|
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;
|
|
|
|
|
|
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);
|
|
|
DeleteMidQEntry(mid);
|
|
@@ -2029,9 +2117,9 @@ SMB2_echo(struct TCP_Server_Info *server)
|
|
|
{
|
|
|
struct smb2_echo_req *req;
|
|
|
int rc = 0;
|
|
|
- struct kvec iov;
|
|
|
- struct smb_rqst rqst = { .rq_iov = &iov,
|
|
|
- .rq_nvec = 1 };
|
|
|
+ struct kvec iov[2];
|
|
|
+ struct smb_rqst rqst = { .rq_iov = iov,
|
|
|
+ .rq_nvec = 2 };
|
|
|
|
|
|
cifs_dbg(FYI, "In echo request\n");
|
|
|
|
|
@@ -2045,14 +2133,16 @@ SMB2_echo(struct TCP_Server_Info *server)
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- req->hdr.CreditRequest = cpu_to_le16(1);
|
|
|
+ req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1);
|
|
|
|
|
|
- iov.iov_base = (char *)req;
|
|
|
/* 4 for rfc1002 length field */
|
|
|
- iov.iov_len = get_rfc1002_length(req) + 4;
|
|
|
+ iov[0].iov_len = 4;
|
|
|
+ iov[0].iov_base = (char *)req;
|
|
|
+ iov[1].iov_len = get_rfc1002_length(req);
|
|
|
+ iov[1].iov_base = (char *)req + 4;
|
|
|
|
|
|
- rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, server,
|
|
|
- CIFS_ECHO_OP);
|
|
|
+ rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL,
|
|
|
+ server, CIFS_ECHO_OP);
|
|
|
if (rc)
|
|
|
cifs_dbg(FYI, "Echo request failed: %d\n", rc);
|
|
|
|
|
@@ -2068,8 +2158,10 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
struct TCP_Server_Info *server;
|
|
|
struct cifs_ses *ses = tcon->ses;
|
|
|
struct kvec iov[1];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int resp_buftype;
|
|
|
int rc = 0;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
cifs_dbg(FYI, "Flush\n");
|
|
|
|
|
@@ -2082,6 +2174,9 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
req->PersistentFileId = persistent_fid;
|
|
|
req->VolatileFileId = volatile_fid;
|
|
|
|
|
@@ -2089,12 +2184,13 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
/* 4 for rfc1002 length field */
|
|
|
iov[0].iov_len = get_rfc1002_length(req) + 4;
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, 0);
|
|
|
+ rc = SendReceive2(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
|
|
|
if (rc != 0)
|
|
|
cifs_stats_fail_inc(tcon, SMB2_FLUSH_HE);
|
|
|
|
|
|
- free_rsp_buf(resp_buftype, iov[0].iov_base);
|
|
|
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -2103,19 +2199,23 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
|
|
* have the end_of_chain boolean set to true.
|
|
|
*/
|
|
|
static int
|
|
|
-smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms,
|
|
|
- unsigned int remaining_bytes, int request_type)
|
|
|
+smb2_new_read_req(void **buf, unsigned int *total_len,
|
|
|
+ struct cifs_io_parms *io_parms, unsigned int remaining_bytes,
|
|
|
+ int request_type)
|
|
|
{
|
|
|
int rc = -EACCES;
|
|
|
- struct smb2_read_req *req = NULL;
|
|
|
+ struct smb2_read_plain_req *req = NULL;
|
|
|
+ struct smb2_sync_hdr *shdr;
|
|
|
|
|
|
- rc = small_smb2_init(SMB2_READ, io_parms->tcon, (void **) &req);
|
|
|
+ rc = smb2_plain_req_init(SMB2_READ, io_parms->tcon, (void **) &req,
|
|
|
+ total_len);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
if (io_parms->tcon->ses->server == NULL)
|
|
|
return -ECONNABORTED;
|
|
|
|
|
|
- req->hdr.ProcessId = cpu_to_le32(io_parms->pid);
|
|
|
+ shdr = &req->sync_hdr;
|
|
|
+ shdr->ProcessId = cpu_to_le32(io_parms->pid);
|
|
|
|
|
|
req->PersistentFileId = io_parms->persistent_fid;
|
|
|
req->VolatileFileId = io_parms->volatile_fid;
|
|
@@ -2128,19 +2228,19 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms,
|
|
|
|
|
|
if (request_type & CHAINED_REQUEST) {
|
|
|
if (!(request_type & END_OF_CHAIN)) {
|
|
|
- /* 4 for rfc1002 length field */
|
|
|
- req->hdr.NextCommand =
|
|
|
- cpu_to_le32(get_rfc1002_length(req) + 4);
|
|
|
+ /* next 8-byte aligned request */
|
|
|
+ *total_len = DIV_ROUND_UP(*total_len, 8) * 8;
|
|
|
+ shdr->NextCommand = cpu_to_le32(*total_len);
|
|
|
} else /* END_OF_CHAIN */
|
|
|
- req->hdr.NextCommand = 0;
|
|
|
+ shdr->NextCommand = 0;
|
|
|
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
|
|
|
* in chain.
|
|
|
*/
|
|
|
- req->hdr.SessionId = 0xFFFFFFFF;
|
|
|
- req->hdr.TreeId = 0xFFFFFFFF;
|
|
|
+ shdr->SessionId = 0xFFFFFFFF;
|
|
|
+ shdr->TreeId = 0xFFFFFFFF;
|
|
|
req->PersistentFileId = 0xFFFFFFFF;
|
|
|
req->VolatileFileId = 0xFFFFFFFF;
|
|
|
}
|
|
@@ -2150,9 +2250,7 @@ smb2_new_read_req(struct kvec *iov, struct cifs_io_parms *io_parms,
|
|
|
else
|
|
|
req->RemainingBytes = 0;
|
|
|
|
|
|
- iov[0].iov_base = (char *)req;
|
|
|
- /* 4 for rfc1002 length field */
|
|
|
- iov[0].iov_len = get_rfc1002_length(req) + 4;
|
|
|
+ *buf = req;
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -2162,10 +2260,11 @@ smb2_readv_callback(struct mid_q_entry *mid)
|
|
|
struct cifs_readdata *rdata = mid->callback_data;
|
|
|
struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink);
|
|
|
struct TCP_Server_Info *server = tcon->ses->server;
|
|
|
- struct smb2_hdr *buf = (struct smb2_hdr *)rdata->iov.iov_base;
|
|
|
+ struct smb2_sync_hdr *shdr =
|
|
|
+ (struct smb2_sync_hdr *)rdata->iov[1].iov_base;
|
|
|
unsigned int credits_received = 1;
|
|
|
- struct smb_rqst rqst = { .rq_iov = &rdata->iov,
|
|
|
- .rq_nvec = 1,
|
|
|
+ struct smb_rqst rqst = { .rq_iov = rdata->iov,
|
|
|
+ .rq_nvec = 2,
|
|
|
.rq_pages = rdata->pages,
|
|
|
.rq_npages = rdata->nr_pages,
|
|
|
.rq_pagesz = rdata->pagesz,
|
|
@@ -2177,9 +2276,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
|
|
|
|
|
|
switch (mid->mid_state) {
|
|
|
case MID_RESPONSE_RECEIVED:
|
|
|
- credits_received = le16_to_cpu(buf->CreditRequest);
|
|
|
+ credits_received = le16_to_cpu(shdr->CreditRequest);
|
|
|
/* result already set, check signature */
|
|
|
- if (server->sign) {
|
|
|
+ if (server->sign && !mid->decrypted) {
|
|
|
int rc;
|
|
|
|
|
|
rc = smb2_verify_signature(&rqst, server);
|
|
@@ -2216,16 +2315,19 @@ smb2_readv_callback(struct mid_q_entry *mid)
|
|
|
add_credits(server, credits_received, 0);
|
|
|
}
|
|
|
|
|
|
-/* smb2_async_readv - send an async write, and set up mid to handle result */
|
|
|
+/* smb2_async_readv - send an async read, and set up mid to handle result */
|
|
|
int
|
|
|
smb2_async_readv(struct cifs_readdata *rdata)
|
|
|
{
|
|
|
int rc, flags = 0;
|
|
|
- struct smb2_hdr *buf;
|
|
|
+ char *buf;
|
|
|
+ struct smb2_sync_hdr *shdr;
|
|
|
struct cifs_io_parms io_parms;
|
|
|
- struct smb_rqst rqst = { .rq_iov = &rdata->iov,
|
|
|
- .rq_nvec = 1 };
|
|
|
+ struct smb_rqst rqst = { .rq_iov = rdata->iov,
|
|
|
+ .rq_nvec = 2 };
|
|
|
struct TCP_Server_Info *server;
|
|
|
+ unsigned int total_len;
|
|
|
+ __be32 req_len;
|
|
|
|
|
|
cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
|
|
|
__func__, rdata->offset, rdata->bytes);
|
|
@@ -2239,7 +2341,7 @@ smb2_async_readv(struct cifs_readdata *rdata)
|
|
|
|
|
|
server = io_parms.tcon->ses->server;
|
|
|
|
|
|
- rc = smb2_new_read_req(&rdata->iov, &io_parms, 0, 0);
|
|
|
+ rc = smb2_new_read_req((void **) &buf, &total_len, &io_parms, 0, 0);
|
|
|
if (rc) {
|
|
|
if (rc == -EAGAIN && rdata->credits) {
|
|
|
/* credits was reset by reconnect */
|
|
@@ -2252,26 +2354,34 @@ smb2_async_readv(struct cifs_readdata *rdata)
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
- buf = (struct smb2_hdr *)rdata->iov.iov_base;
|
|
|
- /* 4 for rfc1002 length field */
|
|
|
- rdata->iov.iov_len = get_rfc1002_length(rdata->iov.iov_base) + 4;
|
|
|
+ if (encryption_required(io_parms.tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ req_len = cpu_to_be32(total_len);
|
|
|
+
|
|
|
+ rdata->iov[0].iov_base = &req_len;
|
|
|
+ rdata->iov[0].iov_len = sizeof(__be32);
|
|
|
+ rdata->iov[1].iov_base = buf;
|
|
|
+ rdata->iov[1].iov_len = total_len;
|
|
|
+
|
|
|
+ shdr = (struct smb2_sync_hdr *)buf;
|
|
|
|
|
|
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));
|
|
|
- buf->CreditRequest = buf->CreditCharge;
|
|
|
+ shdr->CreditRequest = shdr->CreditCharge;
|
|
|
spin_lock(&server->req_lock);
|
|
|
server->credits += rdata->credits -
|
|
|
- le16_to_cpu(buf->CreditCharge);
|
|
|
+ le16_to_cpu(shdr->CreditCharge);
|
|
|
spin_unlock(&server->req_lock);
|
|
|
wake_up(&server->request_q);
|
|
|
- flags = CIFS_HAS_CREDITS;
|
|
|
+ flags |= CIFS_HAS_CREDITS;
|
|
|
}
|
|
|
|
|
|
kref_get(&rdata->refcount);
|
|
|
rc = cifs_call_async(io_parms.tcon->ses->server, &rqst,
|
|
|
cifs_readv_receive, smb2_readv_callback,
|
|
|
- rdata, flags);
|
|
|
+ smb3_handle_read_data, rdata, flags);
|
|
|
if (rc) {
|
|
|
kref_put(&rdata->refcount, cifs_readdata_release);
|
|
|
cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
|
|
@@ -2286,21 +2396,41 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
|
|
|
unsigned int *nbytes, char **buf, int *buf_type)
|
|
|
{
|
|
|
int resp_buftype, rc = -EACCES;
|
|
|
+ struct smb2_read_plain_req *req = NULL;
|
|
|
struct smb2_read_rsp *rsp = NULL;
|
|
|
- struct kvec iov[1];
|
|
|
+ struct smb2_sync_hdr *shdr;
|
|
|
+ struct kvec iov[2];
|
|
|
+ struct kvec rsp_iov;
|
|
|
+ unsigned int total_len;
|
|
|
+ __be32 req_len;
|
|
|
+ struct smb_rqst rqst = { .rq_iov = iov,
|
|
|
+ .rq_nvec = 2 };
|
|
|
+ int flags = CIFS_LOG_ERROR;
|
|
|
+ struct cifs_ses *ses = io_parms->tcon->ses;
|
|
|
|
|
|
*nbytes = 0;
|
|
|
- rc = smb2_new_read_req(iov, io_parms, 0, 0);
|
|
|
+ rc = smb2_new_read_req((void **)&req, &total_len, io_parms, 0, 0);
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- rc = SendReceive2(xid, io_parms->tcon->ses, iov, 1,
|
|
|
- &resp_buftype, CIFS_LOG_ERROR);
|
|
|
+ if (encryption_required(io_parms->tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
|
|
|
- rsp = (struct smb2_read_rsp *)iov[0].iov_base;
|
|
|
+ req_len = cpu_to_be32(total_len);
|
|
|
|
|
|
- if (rsp->hdr.Status == STATUS_END_OF_FILE) {
|
|
|
- free_rsp_buf(resp_buftype, iov[0].iov_base);
|
|
|
+ iov[0].iov_base = &req_len;
|
|
|
+ iov[0].iov_len = sizeof(__be32);
|
|
|
+ iov[1].iov_base = req;
|
|
|
+ iov[1].iov_len = total_len;
|
|
|
+
|
|
|
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+
|
|
|
+ rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
|
|
|
+ shdr = get_sync_hdr(rsp);
|
|
|
+
|
|
|
+ if (shdr->Status == STATUS_END_OF_FILE) {
|
|
|
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2319,11 +2449,10 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
|
|
|
}
|
|
|
|
|
|
if (*buf) {
|
|
|
- memcpy(*buf, (char *)&rsp->hdr.ProtocolId + rsp->DataOffset,
|
|
|
- *nbytes);
|
|
|
- free_rsp_buf(resp_buftype, iov[0].iov_base);
|
|
|
+ memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes);
|
|
|
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
|
|
|
} else if (resp_buftype != CIFS_NO_BUFFER) {
|
|
|
- *buf = iov[0].iov_base;
|
|
|
+ *buf = rsp_iov.iov_base;
|
|
|
if (resp_buftype == CIFS_SMALL_BUFFER)
|
|
|
*buf_type = CIFS_SMALL_BUFFER;
|
|
|
else if (resp_buftype == CIFS_LARGE_BUFFER)
|
|
@@ -2348,7 +2477,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
|
|
|
|
|
|
switch (mid->mid_state) {
|
|
|
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);
|
|
|
if (wdata->result != 0)
|
|
|
break;
|
|
@@ -2394,10 +2523,11 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
|
|
{
|
|
|
int rc = -EACCES, flags = 0;
|
|
|
struct smb2_write_req *req = NULL;
|
|
|
+ struct smb2_sync_hdr *shdr;
|
|
|
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
|
|
|
struct TCP_Server_Info *server = tcon->ses->server;
|
|
|
- struct kvec iov;
|
|
|
- struct smb_rqst rqst;
|
|
|
+ struct kvec iov[2];
|
|
|
+ struct smb_rqst rqst = { };
|
|
|
|
|
|
rc = small_smb2_init(SMB2_WRITE, tcon, (void **) &req);
|
|
|
if (rc) {
|
|
@@ -2412,7 +2542,11 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
|
|
goto async_writev_out;
|
|
|
}
|
|
|
|
|
|
- req->hdr.ProcessId = cpu_to_le32(wdata->cfile->pid);
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ shdr = get_sync_hdr(req);
|
|
|
+ shdr->ProcessId = cpu_to_le32(wdata->cfile->pid);
|
|
|
|
|
|
req->PersistentFileId = wdata->cfile->fid.persistent_fid;
|
|
|
req->VolatileFileId = wdata->cfile->fid.volatile_fid;
|
|
@@ -2426,11 +2560,13 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
|
|
req->RemainingBytes = 0;
|
|
|
|
|
|
/* 4 for rfc1002 length field and 1 for Buffer */
|
|
|
- iov.iov_len = get_rfc1002_length(req) + 4 - 1;
|
|
|
- iov.iov_base = req;
|
|
|
+ iov[0].iov_len = 4;
|
|
|
+ iov[0].iov_base = req;
|
|
|
+ iov[1].iov_len = get_rfc1002_length(req) - 1;
|
|
|
+ iov[1].iov_base = (char *)req + 4;
|
|
|
|
|
|
- rqst.rq_iov = &iov;
|
|
|
- rqst.rq_nvec = 1;
|
|
|
+ rqst.rq_iov = iov;
|
|
|
+ rqst.rq_nvec = 2;
|
|
|
rqst.rq_pages = wdata->pages;
|
|
|
rqst.rq_npages = wdata->nr_pages;
|
|
|
rqst.rq_pagesz = wdata->pagesz;
|
|
@@ -2444,20 +2580,20 @@ smb2_async_writev(struct cifs_writedata *wdata,
|
|
|
inc_rfc1001_len(&req->hdr, wdata->bytes - 1 /* Buffer */);
|
|
|
|
|
|
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));
|
|
|
- req->hdr.CreditRequest = req->hdr.CreditCharge;
|
|
|
+ shdr->CreditRequest = shdr->CreditCharge;
|
|
|
spin_lock(&server->req_lock);
|
|
|
server->credits += wdata->credits -
|
|
|
- le16_to_cpu(req->hdr.CreditCharge);
|
|
|
+ le16_to_cpu(shdr->CreditCharge);
|
|
|
spin_unlock(&server->req_lock);
|
|
|
wake_up(&server->request_q);
|
|
|
- flags = CIFS_HAS_CREDITS;
|
|
|
+ flags |= CIFS_HAS_CREDITS;
|
|
|
}
|
|
|
|
|
|
kref_get(&wdata->refcount);
|
|
|
- rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, wdata,
|
|
|
- flags);
|
|
|
+ rc = cifs_call_async(server, &rqst, NULL, smb2_writev_callback, NULL,
|
|
|
+ wdata, flags);
|
|
|
|
|
|
if (rc) {
|
|
|
kref_put(&wdata->refcount, release);
|
|
@@ -2483,6 +2619,9 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
|
|
|
struct smb2_write_req *req = NULL;
|
|
|
struct smb2_write_rsp *rsp = NULL;
|
|
|
int resp_buftype;
|
|
|
+ struct kvec rsp_iov;
|
|
|
+ int flags = 0;
|
|
|
+
|
|
|
*nbytes = 0;
|
|
|
|
|
|
if (n_vec < 1)
|
|
@@ -2495,7 +2634,10 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
|
|
|
if (io_parms->tcon->ses->server == NULL)
|
|
|
return -ECONNABORTED;
|
|
|
|
|
|
- req->hdr.ProcessId = cpu_to_le32(io_parms->pid);
|
|
|
+ if (encryption_required(io_parms->tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ req->hdr.sync_hdr.ProcessId = cpu_to_le32(io_parms->pid);
|
|
|
|
|
|
req->PersistentFileId = io_parms->persistent_fid;
|
|
|
req->VolatileFileId = io_parms->volatile_fid;
|
|
@@ -2517,8 +2659,9 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
|
|
|
inc_rfc1001_len(req, io_parms->length - 1 /* Buffer */);
|
|
|
|
|
|
rc = SendReceive2(xid, io_parms->tcon->ses, iov, n_vec + 1,
|
|
|
- &resp_buftype, 0);
|
|
|
- rsp = (struct smb2_write_rsp *)iov[0].iov_base;
|
|
|
+ &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_write_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
if (rc) {
|
|
|
cifs_stats_fail_inc(io_parms->tcon, SMB2_WRITE_HE);
|
|
@@ -2581,6 +2724,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
struct smb2_query_directory_req *req;
|
|
|
struct smb2_query_directory_rsp *rsp = NULL;
|
|
|
struct kvec iov[2];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int rc = 0;
|
|
|
int len;
|
|
|
int resp_buftype = CIFS_NO_BUFFER;
|
|
@@ -2591,6 +2735,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
char *end_of_smb;
|
|
|
unsigned int output_size = CIFSMaxBufSize;
|
|
|
size_t info_buf_size;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
if (ses && (ses->server))
|
|
|
server = ses->server;
|
|
@@ -2601,6 +2746,9 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
switch (srch_inf->info_level) {
|
|
|
case SMB_FIND_FILE_DIRECTORY_INFO:
|
|
|
req->FileInformationClass = FILE_DIRECTORY_INFORMATION;
|
|
@@ -2645,11 +2793,13 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
|
|
|
inc_rfc1001_len(req, len - 1 /* Buffer */);
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, 0);
|
|
|
- rsp = (struct smb2_query_directory_rsp *)iov[0].iov_base;
|
|
|
+ rc = SendReceive2(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
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;
|
|
|
rc = 0;
|
|
|
}
|
|
@@ -2705,11 +2855,13 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
struct smb2_set_info_req *req;
|
|
|
struct smb2_set_info_rsp *rsp = NULL;
|
|
|
struct kvec *iov;
|
|
|
+ struct kvec rsp_iov;
|
|
|
int rc = 0;
|
|
|
int resp_buftype;
|
|
|
unsigned int i;
|
|
|
struct TCP_Server_Info *server;
|
|
|
struct cifs_ses *ses = tcon->ses;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
if (ses && (ses->server))
|
|
|
server = ses->server;
|
|
@@ -2729,7 +2881,10 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
- req->hdr.ProcessId = cpu_to_le32(pid);
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ req->hdr.sync_hdr.ProcessId = cpu_to_le32(pid);
|
|
|
|
|
|
req->InfoType = SMB2_O_INFO_FILE;
|
|
|
req->FileInfoClass = info_class;
|
|
@@ -2756,8 +2911,9 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
iov[i].iov_len = size[i];
|
|
|
}
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, iov, num, &resp_buftype, 0);
|
|
|
- rsp = (struct smb2_set_info_rsp *)iov[0].iov_base;
|
|
|
+ rc = SendReceive2(xid, ses, iov, num, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
+ rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
if (rc != 0)
|
|
|
cifs_stats_fail_inc(tcon, SMB2_SET_INFO_HE);
|
|
@@ -2885,20 +3041,23 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
{
|
|
|
int rc;
|
|
|
struct smb2_oplock_break *req = NULL;
|
|
|
+ int flags = CIFS_OBREAK_OP;
|
|
|
|
|
|
cifs_dbg(FYI, "SMB2_oplock_break\n");
|
|
|
rc = small_smb2_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req);
|
|
|
-
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
req->VolatileFid = volatile_fid;
|
|
|
req->PersistentFid = persistent_fid;
|
|
|
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);
|
|
|
- /* SMB2 buffer freed by function above */
|
|
|
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, flags);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
|
|
|
if (rc) {
|
|
|
cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
|
|
@@ -2958,10 +3117,12 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
{
|
|
|
struct smb2_query_info_rsp *rsp = NULL;
|
|
|
struct kvec iov;
|
|
|
+ struct kvec rsp_iov;
|
|
|
int rc = 0;
|
|
|
int resp_buftype;
|
|
|
struct cifs_ses *ses = tcon->ses;
|
|
|
struct smb2_fs_full_size_info *info = NULL;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
rc = build_qfs_info_req(&iov, tcon, FS_FULL_SIZE_INFORMATION,
|
|
|
sizeof(struct smb2_fs_full_size_info),
|
|
@@ -2969,12 +3130,16 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0);
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(iov.iov_base);
|
|
|
if (rc) {
|
|
|
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
|
|
|
goto qfsinf_exit;
|
|
|
}
|
|
|
- rsp = (struct smb2_query_info_rsp *)iov.iov_base;
|
|
|
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
info = (struct smb2_fs_full_size_info *)(4 /* RFC1001 len */ +
|
|
|
le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
|
|
@@ -2985,7 +3150,7 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
copy_fs_info_to_kstatfs(info, fsdata);
|
|
|
|
|
|
qfsinf_exit:
|
|
|
- free_rsp_buf(resp_buftype, iov.iov_base);
|
|
|
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -2995,10 +3160,12 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
{
|
|
|
struct smb2_query_info_rsp *rsp = NULL;
|
|
|
struct kvec iov;
|
|
|
+ struct kvec rsp_iov;
|
|
|
int rc = 0;
|
|
|
int resp_buftype, max_len, min_len;
|
|
|
struct cifs_ses *ses = tcon->ses;
|
|
|
unsigned int rsp_len, offset;
|
|
|
+ int flags = 0;
|
|
|
|
|
|
if (level == FS_DEVICE_INFORMATION) {
|
|
|
max_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
|
|
@@ -3019,12 +3186,16 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, 0);
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ rc = SendReceive2(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov);
|
|
|
+ cifs_small_buf_release(iov.iov_base);
|
|
|
if (rc) {
|
|
|
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
|
|
|
goto qfsattr_exit;
|
|
|
}
|
|
|
- rsp = (struct smb2_query_info_rsp *)iov.iov_base;
|
|
|
+ rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
|
|
|
|
|
|
rsp_len = le32_to_cpu(rsp->OutputBufferLength);
|
|
|
offset = le16_to_cpu(rsp->OutputBufferOffset);
|
|
@@ -3048,7 +3219,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
}
|
|
|
|
|
|
qfsattr_exit:
|
|
|
- free_rsp_buf(resp_buftype, iov.iov_base);
|
|
|
+ free_rsp_buf(resp_buftype, rsp_iov.iov_base);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -3060,8 +3231,10 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
int rc = 0;
|
|
|
struct smb2_lock_req *req = NULL;
|
|
|
struct kvec iov[2];
|
|
|
+ struct kvec rsp_iov;
|
|
|
int resp_buf_type;
|
|
|
unsigned int count;
|
|
|
+ int flags = CIFS_NO_RESP;
|
|
|
|
|
|
cifs_dbg(FYI, "smb2_lockv num lock %d\n", num_lock);
|
|
|
|
|
@@ -3069,7 +3242,10 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- req->hdr.ProcessId = cpu_to_le32(pid);
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ req->hdr.sync_hdr.ProcessId = cpu_to_le32(pid);
|
|
|
req->LockCount = cpu_to_le16(num_lock);
|
|
|
|
|
|
req->PersistentFileId = persist_fid;
|
|
@@ -3085,7 +3261,9 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
iov[1].iov_len = count;
|
|
|
|
|
|
cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
|
|
|
- rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP);
|
|
|
+ rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, flags,
|
|
|
+ &rsp_iov);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
if (rc) {
|
|
|
cifs_dbg(FYI, "Send error in smb2_lockv = %d\n", rc);
|
|
|
cifs_stats_fail_inc(tcon, SMB2_LOCK_HE);
|
|
@@ -3117,22 +3295,25 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
|
|
|
{
|
|
|
int rc;
|
|
|
struct smb2_lease_ack *req = NULL;
|
|
|
+ int flags = CIFS_OBREAK_OP;
|
|
|
|
|
|
cifs_dbg(FYI, "SMB2_lease_break\n");
|
|
|
rc = small_smb2_init(SMB2_OPLOCK_BREAK, tcon, (void **) &req);
|
|
|
-
|
|
|
if (rc)
|
|
|
return rc;
|
|
|
|
|
|
- req->hdr.CreditRequest = cpu_to_le16(1);
|
|
|
+ if (encryption_required(tcon))
|
|
|
+ flags |= CIFS_TRANSFORM_REQ;
|
|
|
+
|
|
|
+ req->hdr.sync_hdr.CreditRequest = cpu_to_le16(1);
|
|
|
req->StructureSize = cpu_to_le16(36);
|
|
|
inc_rfc1001_len(req, 12);
|
|
|
|
|
|
memcpy(req->LeaseKey, lease_key, 16);
|
|
|
req->LeaseState = lease_state;
|
|
|
|
|
|
- rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, CIFS_OBREAK_OP);
|
|
|
- /* SMB2 buffer freed by function above */
|
|
|
+ rc = SendReceiveNoRsp(xid, tcon->ses, (char *) req, flags);
|
|
|
+ cifs_small_buf_release(req);
|
|
|
|
|
|
if (rc) {
|
|
|
cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
|