[patch][2/3] SMBTrans functions for Named Pipes

Shirish Pargaonkar <[email protected]>
Newsgroups gmane.linux.file-systems.cifs,gmane.linux.file-systems
Message-ID <[email protected]>
SMB Trans commands (except WaitNamedPipe)

From d11c8d19f9e1bf5d3ed615a38ce99e97dfe0b7dd Mon Sep 17 00:00:00 2001
From: Shirish Pargaonkar <[email protected]>
Date: Thu, 15 Oct 2009 08:16:26 -0500
Subject: [PATCH] SMB Trans functions for Named Pipe support

---
 fs/cifs/cifssmb.c |  488 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 488 insertions(+), 0 deletions(-)

diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 941441d..9d6b77b 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -5675,4 +5675,492 @@ SetEARetry:
 	return rc;
 }

+int
+CIFSSMBTransQNmPipe(const int xid, struct cifsTconInfo *tcon,
+		unsigned long arg, __u16 netfid,
+		const struct nls_table *nls_codepage, int remap)
+{
+	TRANS_REQ *pSMB = NULL;
+	TRANS_RSP *pSMBr = NULL;
+	int rc = 0;
+	int name_len, param_len;
+	int pad;
+	int bytes_returned = 0;
+	__u16 offset;
+	__u16 byte_count = 0;
+	char *fileName = "\\PIPE\\";
+	char *bcc_ptr;
+	struct qnmp_info qnmpipeinfo;
+
+	cFYI(1, ("In CIFSSMBTransQNmPipe"));
+qnmpiperetry:
+	rc = smb_init(SMB_COM_TRANSACTION, 16, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	offset = offsetof(TRANS_REQ, Name) - 4;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	bcc_ptr = (char *)pSMB + offset + 4;
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifsConvertToUCS((__le16 *) bcc_ptr, fileName,
+				     PATH_MAX, nls_codepage, remap);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {	/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(bcc_ptr, fileName, name_len);
+	}
+	byte_count += (1 + pad + name_len);
+
+	offset += name_len;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	pSMB->ParameterCount = 2;
+	pSMB->TotalParameterCount = 2;
+	pSMB->ParameterOffset = offset;
+	bcc_ptr = (char *)pSMB + offset + 4;
+	*bcc_ptr++ = 0x1;
+	*bcc_ptr = 0x0;
+	param_len = 2;
+	byte_count += (pad + param_len);
+
+	offset += param_len;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	pSMB->DataOffset = 0;
+	pSMB->DataCount = 0;
+	pSMB->TotalDataCount = 0;
+
+	pSMB->MaxParameterCount = 0;
+	/* BB find max SMB PDU from sess */
+	pSMB->MaxDataCount = cpu_to_le16(4280);
+	pSMB->MaxSetupCount = 0;
+
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+
+	pSMB->SetupCount = 2;
+	pSMB->Function = cpu_to_le16(TRANS_QUERY_NMPIPE_INFO);
+	pSMB->Fid = cpu_to_le16(netfid);
+
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	pSMB->hdr.smb_buf_length += byte_count;
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("CIFSSMBTransQNmPipe returned %d", rc));
+	} else {
+		offset = le16_to_cpu(pSMBr->DataOffset);
+		bcc_ptr = (char *)pSMBr + offset + 4;
+		qnmpipeinfo.outbuf = le16_to_cpu(*(unsigned short *)bcc_ptr);
+		bcc_ptr += 2;
+		qnmpipeinfo.inbuf = le16_to_cpu(*(unsigned short *)bcc_ptr);
+		bcc_ptr += 2;
+		qnmpipeinfo.maxinst = le16_to_cpu(*(unsigned short *)bcc_ptr);
+		bcc_ptr += 2;
+		qnmpipeinfo.curinst = *bcc_ptr;
+		bcc_ptr += 2;
+		qnmpipeinfo.length = *bcc_ptr;
+		bcc_ptr += 2;
+		if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+			rc = cifs_from_ucs2(qnmpipeinfo.pipename,
+				(__le16 *)bcc_ptr,
+				(int)qnmpipeinfo.length,
+				(int)(qnmpipeinfo.length - 2),
+				nls_codepage, 0);
+		} else
+			strncpy(qnmpipeinfo.pipename, bcc_ptr,
+				qnmpipeinfo.length);
+		memcpy((char *)arg, &qnmpipeinfo, sizeof(struct qnmp_info));
+	}
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto qnmpiperetry;
+
+	return rc;
+}
+
+int
+CIFSSMBTransSetNmPHState(const int xid, struct cifsTconInfo *tcon,
+		unsigned long arg, __u16 netfid,
+		const struct nls_table *nls_codepage, int remap)
+{
+	TRANS_REQ *pSMB = NULL;
+	TRANS_RSP *pSMBr = NULL;
+	int rc = 0;
+	int name_len, param_len;
+	int pad;
+	int bytes_returned = 0;
+	__u16 offset;
+	__u16 byte_count = 0;
+	char *fileName = "\\PIPE\\";
+	char *bcc_ptr;
+	unsigned short mode;
+
+	cFYI(1, ("In CIFSSMBTransSetNmPHandState"));
+setnmaphandstateretry:
+	rc = smb_init(SMB_COM_TRANSACTION, 16, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	offset = offsetof(TRANS_REQ, Name) - 4;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	bcc_ptr = (char *)pSMB + offset + 4;
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifsConvertToUCS((__le16 *) bcc_ptr, fileName,
+				     PATH_MAX, nls_codepage, remap);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {	/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(bcc_ptr, fileName, name_len);
+	}
+	byte_count += (1 + pad + name_len);
+
+	offset += name_len;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	pSMB->ParameterCount = 2;
+	pSMB->TotalParameterCount = 2;
+	pSMB->ParameterOffset = offset;
+	bcc_ptr = (char *)pSMB + offset + 4;
+	mode = (*(unsigned short *)(arg));
+	*(unsigned short *)bcc_ptr = cpu_to_le16(mode);
+	bcc_ptr += 2;
+	param_len = 2;
+	byte_count += (pad + param_len);
+
+	offset += param_len;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	pSMB->DataOffset = 0;
+	pSMB->DataCount = 0;
+	pSMB->TotalDataCount = 0;
+
+	pSMB->MaxParameterCount = 0;
+	pSMB->MaxDataCount = 0;
+	pSMB->MaxSetupCount = 0;
+
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+
+	pSMB->SetupCount = 2;
+	pSMB->Function = cpu_to_le16(TRANS_SET_NMPIPE_STATE);
+	pSMB->Fid = cpu_to_le16(netfid);
+
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	pSMB->hdr.smb_buf_length += byte_count;
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc)
+		cFYI(1, ("CIFSSMBTranSetNmPHandState returned %d", rc));
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto setnmaphandstateretry;
+
+	return rc;
+}
+
+int
+CIFSSMBTransPeekNmPipe(const int xid, struct cifsTconInfo *tcon,
+		unsigned long arg, __u16 netfid,
+		const struct nls_table *nls_codepage, int remap)
+{
+	TRANS_REQ *pSMB = NULL;
+	TRANS_RSP *pSMBr = NULL;
+	int rc = 0;
+	int name_len;
+	int pad;
+	int bytes_returned = 0;
+	int size;
+	__u16 offset;
+	__u16 byte_count = 0;
+	char *fileName = "\\PIPE\\";
+	char *bcc_ptr;
+
+	cFYI(1, ("In CIFSSMBTransPeekNmPipe"));
+peeknmpiperetry:
+	rc = smb_init(SMB_COM_TRANSACTION, 16, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	offset = offsetof(TRANS_REQ, Name) - 4;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	bcc_ptr = (char *)pSMB + offset + 4;
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifsConvertToUCS((__le16 *) bcc_ptr, fileName,
+				     PATH_MAX, nls_codepage, remap);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {	/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(bcc_ptr, fileName, name_len);
+	}
+	byte_count += (1 + pad + name_len);
+
+	offset += name_len;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	pSMB->ParameterCount = 0;
+	pSMB->TotalParameterCount = 0;
+	pSMB->ParameterOffset = offset;
+	byte_count += pad;
+
+	pSMB->DataOffset = 0;
+	pSMB->DataCount = 0;
+	pSMB->TotalDataCount = 0;
+
+	pSMB->MaxParameterCount = 6;
+	/* BB find max SMB PDU from sess */
+	pSMB->MaxDataCount = cpu_to_le16(4280);
+	pSMB->MaxSetupCount = 0;
+
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+
+	pSMB->SetupCount = 2;
+	pSMB->Function = cpu_to_le16(TRANS_PEEK_NMPIPE);
+	pSMB->Fid = cpu_to_le16(netfid);
+
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	pSMB->hdr.smb_buf_length += byte_count;
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("CIFSSMBTranPeekNmPipe returned %d", rc));
+	} else {
+		offset = le16_to_cpu(pSMBr->ParameterOffset);
+		bcc_ptr = (char *)pSMBr + offset + 4;
+		((struct peeknmp_info *)arg)->bavail =
+				le16_to_cpu(*(unsigned short *)bcc_ptr);
+		bcc_ptr += 2;
+		((struct peeknmp_info *)arg)->bremain =
+			le16_to_cpu(*(unsigned short *)bcc_ptr);
+		bcc_ptr += 2;
+		((struct peeknmp_info *)arg)->conntype =
+			le16_to_cpu(*(unsigned short *)bcc_ptr);
+		bcc_ptr += 2;
+		if (((struct peeknmp_info *)arg)->size >
+				((struct peeknmp_info *)arg)->bavail)
+			size = ((struct peeknmp_info *)arg)->bavail;
+		else
+			size = ((struct peeknmp_info *)arg)->size;
+		memcpy(((struct peeknmp_info *)arg)->buffer, bcc_ptr, size);
+	}
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto peeknmpiperetry;
+
+	return rc;
+}
+
+int
+CIFSSMBTransGetNmPHState(const int xid, struct cifsTconInfo *tcon,
+		unsigned long arg, __u16 netfid,
+		const struct nls_table *nls_codepage, int remap)
+{
+	TRANS_REQ *pSMB = NULL;
+	TRANS_RSP *pSMBr = NULL;
+	int rc = 0;
+	int name_len;
+	int pad;
+	int bytes_returned = 0;
+	__u16 offset;
+	__u16 byte_count = 0;
+	char *fileName = "\\PIPE\\";
+	char *bcc_ptr;
+	struct qnmp_hinfo qnmpipehinfo;
+
+	cFYI(1, ("In CIFSSMBTransSetNmPHandState"));
+getnmaphandstateretry:
+	rc = smb_init(SMB_COM_TRANSACTION, 16, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	offset = offsetof(TRANS_REQ, Name) - 4;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	bcc_ptr = (char *)pSMB + offset + 4;
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifsConvertToUCS((__le16 *) bcc_ptr, fileName,
+				     PATH_MAX, nls_codepage, remap);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {	/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(bcc_ptr, fileName, name_len);
+	}
+	byte_count += (1 + pad + name_len);
+
+	offset += name_len;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	pSMB->ParameterCount = 0;
+	pSMB->TotalParameterCount = 0;
+	pSMB->ParameterOffset = offset;
+
+	pSMB->DataCount = 0;
+	pSMB->TotalDataCount = 0;
+	pSMB->DataOffset = offset;
+
+	pSMB->MaxParameterCount = 2;
+	pSMB->MaxDataCount = 0;
+	pSMB->MaxSetupCount = 0;
+
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+
+	pSMB->SetupCount = 2;
+	pSMB->Function = cpu_to_le16(TRANS_QUERY_NMPIPE_STATE);
+	pSMB->Fid = cpu_to_le16(netfid);
+
+	byte_count += pad;
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	pSMB->hdr.smb_buf_length += byte_count;
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("CIFSSMBTranGetNmPHandState returned %d", rc));
+	} else {
+		offset = le16_to_cpu(pSMBr->ParameterOffset);
+		bcc_ptr = (char *)pSMBr + offset + 4;
+		qnmpipehinfo.mode = le16_to_cpu(*(unsigned short *)bcc_ptr);
+		memcpy((char *)arg, &qnmpipehinfo, sizeof(struct qnmp_hinfo));
+	}
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto getnmaphandstateretry;
+
+	return rc;
+}
+
+int
+CIFSSMBTransNmPipe(const int xid, struct cifsTconInfo *tcon,
+		unsigned char *arg, __u16 netfid,
+		const struct nls_table *nls_codepage, int remap)
+{
+	TRANS_REQ *pSMB = NULL;
+	TRANS_RSP *pSMBr = NULL;
+	int rc = 0;
+	int name_len;
+	int pad;
+	int bytes_returned = 0;
+	__u16 offset;
+	__u16 byte_count = 0;
+	char *fileName = "\\PIPE\\";
+	char *bcc_ptr;
+
+	cFYI(1, ("In CIFSSMBTransNmPipe"));
+transnmpiperetry:
+	rc = smb_init(SMB_COM_TRANSACTION, 16, tcon, (void **) &pSMB,
+		      (void **) &pSMBr);
+	if (rc)
+		return rc;
+
+	offset = offsetof(TRANS_REQ, Name) - 4;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	bcc_ptr = (char *)pSMB + offset + 4;
+	if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+		name_len =
+		    cifsConvertToUCS((__le16 *) bcc_ptr, fileName,
+				     PATH_MAX, nls_codepage, remap);
+		name_len++;	/* trailing null */
+		name_len *= 2;
+	} else {	/* BB improve the check for buffer overruns BB */
+		name_len = strnlen(fileName, PATH_MAX);
+		name_len++;	/* trailing null */
+		strncpy(bcc_ptr, fileName, name_len);
+	}
+	byte_count += (1 + pad + name_len);
+
+	offset += name_len;
+	pad = offset % 4;
+	if (pad)
+		offset += pad;
+	pSMB->ParameterOffset = offset;
+	pSMB->ParameterCount = 0;
+	pSMB->TotalParameterCount = 0;
+
+	pSMB->DataOffset = offset;
+	pSMB->DataCount = ((struct transnmp_info *)arg)->wsize;
+	pSMB->TotalDataCount = pSMB->DataCount;
+	bcc_ptr = (char *)pSMB + offset + 4;
+	memcpy(bcc_ptr, ((struct transnmp_info *)arg)->sendbuf,
+					pSMB->DataCount);
+	byte_count += (pad + pSMB->DataCount);
+
+	pSMB->MaxParameterCount = 0;
+	/* BB find max SMB PDU from sess */
+	pSMB->MaxDataCount = cpu_to_le16(4280);
+	pSMB->MaxSetupCount = 0;
+
+	pSMB->Flags = 0;
+	pSMB->Timeout = 0;
+
+	pSMB->SetupCount = 2;
+	pSMB->Function = cpu_to_le16(TRANS_TRANSACT_NMPIPE);
+	pSMB->Fid = cpu_to_le16(netfid);
+
+	pSMB->ByteCount = cpu_to_le16(byte_count);
+
+	pSMB->hdr.smb_buf_length += byte_count;
+	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+	if (rc) {
+		cFYI(1, ("CIFSSMBTransQNmPipe returned %d", rc));
+	} else {
+		offset = le16_to_cpu(pSMBr->DataOffset);
+		bcc_ptr = ((char *)pSMBr + offset + 4);
+		byte_count = le16_to_cpu(pSMBr->DataCount);
+		((struct transnmp_info *)arg)->rsize = byte_count;
+		memcpy(((struct transnmp_info *)arg)->recvbuf, bcc_ptr,
+				byte_count);
+	}
+
+	cifs_buf_release(pSMB);
+
+	if (rc == -EAGAIN)
+		goto transnmpiperetry;
+
+	return rc;
+}
 #endif
-- 
1.5.2
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.