Commit ccdc77a3 authored by Ronnie Sahlberg's avatar Ronnie Sahlberg Committed by Steve French
Browse files

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: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 8191576a
Loading
Loading
Loading
Loading
+76 −57
Original line number Original line Diff line number Diff line
@@ -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;
	/* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
	if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
		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 */
}


/*
/*
	 * If no input data, the size of ioctl struct in
 *	SMB2 IOCTL is used for both IOCTLs and FSCTLs
	 * 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]).
 */
 */
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;


	if (indatalen) {
	cifs_dbg(FYI, "SMB2 IOCTL\n");
		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 */
	if (out_data != NULL)
	if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
		*out_data = NULL;
		req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;

	/* 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;
}
}
+4 −0
Original line number Original line Diff line number Diff line
@@ -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,