@@ -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
SMB Trans commands (except WaitNamedPipe) From d11c8d19f9e1bf5d3ed615a38ce99e97dfe0b7dd Mon Sep 17 00:00:00 2001 From: Shirish Pargaonkar <shirishpargaonkar@gmail.com> 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(-)