From patchwork Thu Oct 15 17:41:51 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shirish Pargaonkar X-Patchwork-Id: 36134 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.samba.org (fn.samba.org [216.83.154.106]) by ozlabs.org (Postfix) with ESMTP id 1F05DB7088 for ; Fri, 16 Oct 2009 04:41:59 +1100 (EST) Received: from fn.samba.org (localhost [127.0.0.1]) by lists.samba.org (Postfix) with ESMTP id D45D8AD20D; Thu, 15 Oct 2009 11:40:47 -0600 (MDT) X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on fn.samba.org X-Spam-Level: X-Spam-Status: No, score=-3.8 required=3.8 tests=AWL,BAYES_00,SPF_PASS autolearn=ham version=3.2.5 X-Original-To: linux-cifs-client@lists.samba.org Delivered-To: linux-cifs-client@lists.samba.org Received: from mail-gx0-f222.google.com (mail-gx0-f222.google.com [209.85.217.222]) by lists.samba.org (Postfix) with ESMTP id 95E7FAD186 for ; Thu, 15 Oct 2009 11:40:41 -0600 (MDT) Received: by gxk22 with SMTP id 22so1175262gxk.0 for ; Thu, 15 Oct 2009 10:41:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:date:message-id:subject :from:to:content-type; bh=UrYXilCYeX7nTPWNh+V116Y7/qu7FQAY1ZlbekwrLf4=; b=A3lG/F4Yu8LyPg5R5zVbsmg3WGlalbHhl3Z0mShQ/+fWLEM6gwsJ7jdgHfrvAUnkjE W6Rz0vErtcQvzBsMzWf6gPZC/lAHtKsUNxMhyXckIiDlrfrZ3MWPOjN/m8ebXd8E2O+6 LoiVZDQ8ZAqie3kYLdzovEgw4vlFGPztmcxoQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=A6eQ1k+I9/igwsIZZm4lBXXxpx6fuFMcI9b31361Bvr5N82x5G/icKNjQLD6PeE1wY Dty6R9Cvy4h9mGw26cmkRTaMUXR39cLt4VAilrZeIpQdo3/LU8l8WYlgFAAdFssexxSA wm1Eqc5RELZAR+d2woyzPnvFQuItCu4MJLx/8= MIME-Version: 1.0 Received: by 10.101.213.5 with SMTP id p5mr564549anq.1.1255628511503; Thu, 15 Oct 2009 10:41:51 -0700 (PDT) Date: Thu, 15 Oct 2009 12:41:51 -0500 Message-ID: <4a4634330910151041i33a3036ft8d7f729b5ec77618@mail.gmail.com> From: Shirish Pargaonkar To: linux-cifs-client@lists.samba.org, linux-fsdevel Subject: [linux-cifs-client] [patch][2/3] SMBTrans functions for Named Pipes X-BeenThere: linux-cifs-client@lists.samba.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: The Linux CIFS VFS client List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-cifs-client-bounces@lists.samba.org Errors-To: linux-cifs-client-bounces@lists.samba.org SMB Trans commands (except WaitNamedPipe) From d11c8d19f9e1bf5d3ed615a38ce99e97dfe0b7dd Mon Sep 17 00:00:00 2001 From: Shirish Pargaonkar 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