mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-24 10:39:52 +00:00
cifs: add SMB2_ioctl_init/free helpers to be used with compounding
Define an _init() and a _free() function for SMB2_init so that we will be able to use it with compounds. Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
8191576a12
commit
ccdc77a305
2 changed files with 80 additions and 57 deletions
|
@ -2468,65 +2468,46 @@ creat_exit:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* SMB2 IOCTL is used for both IOCTLs and FSCTLs
|
|
||||||
*/
|
|
||||||
int
|
int
|
||||||
SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
|
||||||
u64 volatile_fid, u32 opcode, bool is_fsctl,
|
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
||||||
char *in_data, u32 indatalen,
|
bool is_fsctl, char *in_data, u32 indatalen)
|
||||||
char **out_data, u32 *plen /* returned data len */)
|
|
||||||
{
|
{
|
||||||
struct smb_rqst rqst;
|
|
||||||
struct smb2_ioctl_req *req;
|
struct smb2_ioctl_req *req;
|
||||||
struct smb2_ioctl_rsp *rsp;
|
struct kvec *iov = rqst->rq_iov;
|
||||||
struct cifs_ses *ses;
|
|
||||||
struct kvec iov[2];
|
|
||||||
struct kvec rsp_iov;
|
|
||||||
int resp_buftype;
|
|
||||||
int n_iov;
|
|
||||||
int rc = 0;
|
|
||||||
int flags = 0;
|
|
||||||
unsigned int total_len;
|
unsigned int total_len;
|
||||||
|
int rc;
|
||||||
cifs_dbg(FYI, "SMB2 IOCTL\n");
|
|
||||||
|
|
||||||
if (out_data != NULL)
|
|
||||||
*out_data = NULL;
|
|
||||||
|
|
||||||
/* zero out returned data len, in case of error */
|
|
||||||
if (plen)
|
|
||||||
*plen = 0;
|
|
||||||
|
|
||||||
if (tcon)
|
|
||||||
ses = tcon->ses;
|
|
||||||
else
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
if (!ses || !(ses->server))
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len);
|
rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (smb3_encryption_required(tcon))
|
|
||||||
flags |= CIFS_TRANSFORM_REQ;
|
|
||||||
|
|
||||||
req->CtlCode = cpu_to_le32(opcode);
|
req->CtlCode = cpu_to_le32(opcode);
|
||||||
req->PersistentFileId = persistent_fid;
|
req->PersistentFileId = persistent_fid;
|
||||||
req->VolatileFileId = volatile_fid;
|
req->VolatileFileId = volatile_fid;
|
||||||
|
|
||||||
|
iov[0].iov_base = (char *)req;
|
||||||
|
/*
|
||||||
|
* If no input data, the size of ioctl struct in
|
||||||
|
* protocol spec still includes a 1 byte data buffer,
|
||||||
|
* but if input data passed to ioctl, we do not
|
||||||
|
* want to double count this, so we do not send
|
||||||
|
* the dummy one byte of data in iovec[0] if sending
|
||||||
|
* input data (in iovec[1]).
|
||||||
|
*/
|
||||||
if (indatalen) {
|
if (indatalen) {
|
||||||
req->InputCount = cpu_to_le32(indatalen);
|
req->InputCount = cpu_to_le32(indatalen);
|
||||||
/* do not set InputOffset if no input data */
|
/* do not set InputOffset if no input data */
|
||||||
req->InputOffset =
|
req->InputOffset =
|
||||||
cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer));
|
cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer));
|
||||||
|
rqst->rq_nvec = 2;
|
||||||
|
iov[0].iov_len = total_len - 1;
|
||||||
iov[1].iov_base = in_data;
|
iov[1].iov_base = in_data;
|
||||||
iov[1].iov_len = indatalen;
|
iov[1].iov_len = indatalen;
|
||||||
n_iov = 2;
|
} else {
|
||||||
} else
|
rqst->rq_nvec = 1;
|
||||||
n_iov = 1;
|
iov[0].iov_len = total_len;
|
||||||
|
}
|
||||||
|
|
||||||
req->OutputOffset = 0;
|
req->OutputOffset = 0;
|
||||||
req->OutputCount = 0; /* MBZ */
|
req->OutputCount = 0; /* MBZ */
|
||||||
|
@ -2548,33 +2529,70 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
||||||
else
|
else
|
||||||
req->Flags = 0;
|
req->Flags = 0;
|
||||||
|
|
||||||
iov[0].iov_base = (char *)req;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If no input data, the size of ioctl struct in
|
|
||||||
* protocol spec still includes a 1 byte data buffer,
|
|
||||||
* but if input data passed to ioctl, we do not
|
|
||||||
* want to double count this, so we do not send
|
|
||||||
* the dummy one byte of data in iovec[0] if sending
|
|
||||||
* input data (in iovec[1]).
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (indatalen) {
|
|
||||||
iov[0].iov_len = total_len - 1;
|
|
||||||
} else
|
|
||||||
iov[0].iov_len = total_len;
|
|
||||||
|
|
||||||
/* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
|
/* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
|
||||||
if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
|
if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
|
||||||
req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
|
req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SMB2_ioctl_free(struct smb_rqst *rqst)
|
||||||
|
{
|
||||||
|
if (rqst && rqst->rq_iov)
|
||||||
|
cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SMB2 IOCTL is used for both IOCTLs and FSCTLs
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
||||||
|
u64 volatile_fid, u32 opcode, bool is_fsctl,
|
||||||
|
char *in_data, u32 indatalen,
|
||||||
|
char **out_data, u32 *plen /* returned data len */)
|
||||||
|
{
|
||||||
|
struct smb_rqst rqst;
|
||||||
|
struct smb2_ioctl_rsp *rsp = NULL;
|
||||||
|
struct cifs_ses *ses;
|
||||||
|
struct kvec iov[2];
|
||||||
|
struct kvec rsp_iov = {NULL, 0};
|
||||||
|
int resp_buftype = CIFS_NO_BUFFER;
|
||||||
|
int rc = 0;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
cifs_dbg(FYI, "SMB2 IOCTL\n");
|
||||||
|
|
||||||
|
if (out_data != NULL)
|
||||||
|
*out_data = NULL;
|
||||||
|
|
||||||
|
/* zero out returned data len, in case of error */
|
||||||
|
if (plen)
|
||||||
|
*plen = 0;
|
||||||
|
|
||||||
|
if (tcon)
|
||||||
|
ses = tcon->ses;
|
||||||
|
else
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (!ses || !(ses->server))
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
if (smb3_encryption_required(tcon))
|
||||||
|
flags |= CIFS_TRANSFORM_REQ;
|
||||||
|
|
||||||
memset(&rqst, 0, sizeof(struct smb_rqst));
|
memset(&rqst, 0, sizeof(struct smb_rqst));
|
||||||
|
memset(&iov, 0, sizeof(iov));
|
||||||
rqst.rq_iov = iov;
|
rqst.rq_iov = iov;
|
||||||
rqst.rq_nvec = n_iov;
|
rqst.rq_nvec = 2;
|
||||||
|
|
||||||
|
rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid,
|
||||||
|
opcode, is_fsctl, in_data, indatalen);
|
||||||
|
if (rc)
|
||||||
|
goto ioctl_exit;
|
||||||
|
|
||||||
rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
|
rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
|
||||||
&rsp_iov);
|
&rsp_iov);
|
||||||
cifs_small_buf_release(req);
|
|
||||||
rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base;
|
rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base;
|
||||||
|
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
|
@ -2624,6 +2642,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
|
||||||
}
|
}
|
||||||
|
|
||||||
ioctl_exit:
|
ioctl_exit:
|
||||||
|
SMB2_ioctl_free(&rqst);
|
||||||
free_rsp_buf(resp_buftype, rsp);
|
free_rsp_buf(resp_buftype, rsp);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,10 @@ extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
||||||
bool is_fsctl, char *in_data, u32 indatalen,
|
bool is_fsctl, char *in_data, u32 indatalen,
|
||||||
char **out_data, u32 *plen /* returned data len */);
|
char **out_data, u32 *plen /* returned data len */);
|
||||||
|
extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
|
||||||
|
u64 persistent_fid, u64 volatile_fid, u32 opcode,
|
||||||
|
bool is_fsctl, char *in_data, u32 indatalen);
|
||||||
|
extern void SMB2_ioctl_free(struct smb_rqst *rqst);
|
||||||
extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
u64 persistent_file_id, u64 volatile_file_id);
|
u64 persistent_file_id, u64 volatile_file_id);
|
||||||
extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
|
Loading…
Add table
Reference in a new issue