From patchwork Sun Sep 27 16:50:28 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 34350 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 90B15B7BDE for ; Mon, 28 Sep 2009 02:57:32 +1000 (EST) Received: from fn.samba.org (localhost [127.0.0.1]) by lists.samba.org (Postfix) with ESMTP id A880AAD16B; Sun, 27 Sep 2009 10:57:03 -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.4 required=3.8 tests=AWL, BAYES_00, NO_MORE_FUNN, SPF_PASS autolearn=no version=3.2.5 X-Original-To: linux-cifs-client@lists.samba.org Delivered-To: linux-cifs-client@lists.samba.org Received: from cdptpa-omtalb.mail.rr.com (cdptpa-omtalb.mail.rr.com [75.180.132.122]) by lists.samba.org (Postfix) with ESMTP id E6F5CAD154 for ; Sun, 27 Sep 2009 10:56:48 -0600 (MDT) Received: from mail.poochiereds.net ([71.70.153.3]) by cdptpa-omta03.mail.rr.com with ESMTP id <20090927165715639.OSMF26368@cdptpa-omta03.mail.rr.com>; Sun, 27 Sep 2009 16:57:15 +0000 Received: by mail.poochiereds.net (Postfix, from userid 4447) id 445A95816F; Sun, 27 Sep 2009 12:50:31 -0400 (EDT) From: Jeff Layton To: linux-nfs@vger.kernel.org, linux-cifs-client@lists.samba.org Date: Sun, 27 Sep 2009 12:50:28 -0400 Message-Id: <1254070230-13125-8-git-send-email-jlayton@redhat.com> X-Mailer: git-send-email 1.6.0.6 In-Reply-To: <1254070230-13125-1-git-send-email-jlayton@redhat.com> References: <1254070230-13125-1-git-send-email-jlayton@redhat.com> Subject: [linux-cifs-client] [RFC PATCH 7/9] sunrpc: add encoding and decoding routines for SMB 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: , MIME-Version: 1.0 Sender: linux-cifs-client-bounces@lists.samba.org Errors-To: linux-cifs-client-bounces@lists.samba.org Add a new smb.c file to hold encode and decode routines for SMB packets. Signed-off-by: Jeff Layton --- include/linux/sunrpc/smb.h | 42 ++++++++++++++ include/linux/sunrpc/xprtsmb.h | 6 +- net/sunrpc/smb.c | 120 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 include/linux/sunrpc/smb.h create mode 100644 net/sunrpc/smb.c diff --git a/include/linux/sunrpc/smb.h b/include/linux/sunrpc/smb.h new file mode 100644 index 0000000..304ab8c --- /dev/null +++ b/include/linux/sunrpc/smb.h @@ -0,0 +1,42 @@ +/* + * net/sunrpc/smb.h -- SMB transport for sunrpc + * + * Copyright (c) 2009 Red Hat, Inc. + * Author(s): Jeff Layton (jlayton@redhat.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * xprtsmb.h + * + * This file contains the public interfaces for the SMB transport for + * the sunrpc layer. + */ + +#ifndef _LINUX_SUNRPC_SMB_H +#define _LINUX_SUNRPC_SMB_H + +/* + * This is the generic SMB function. rqstp is either a rpc_rqst (client + * side) or svc_rqst pointer (server side). + * Encode functions always assume there's enough room in the buffer. + */ +typedef int (*ksmbproc_t)(void *rqstp, __le32 *data, void *obj); + +void smb_encode(struct rpc_task *task); +int smb_decode(struct rpc_task *task); + +#endif /* _LINUX_SUNRPC_SMB_H */ diff --git a/include/linux/sunrpc/xprtsmb.h b/include/linux/sunrpc/xprtsmb.h index d55e85b..731cce2 100644 --- a/include/linux/sunrpc/xprtsmb.h +++ b/include/linux/sunrpc/xprtsmb.h @@ -34,9 +34,6 @@ */ #define XPRT_TRANSPORT_SMB 1024 -int init_smb_xprt(void); -void cleanup_smb_xprt(void); - /* standard SMB header */ struct smb_header { __u8 protocol[4]; @@ -56,4 +53,7 @@ struct smb_header { /* SMB Header Flags of interest */ #define SMBFLG_RESPONSE 0x80 /* response from server */ +int init_smb_xprt(void); +void cleanup_smb_xprt(void); + #endif /* _LINUX_SUNRPC_XPRTSMB_H */ diff --git a/net/sunrpc/smb.c b/net/sunrpc/smb.c new file mode 100644 index 0000000..5511bb2 --- /dev/null +++ b/net/sunrpc/smb.c @@ -0,0 +1,120 @@ +/* + * net/sunrpc/smb.c -- smb encode and decode routines + * + * Copyright (C) 2009 Red Hat, Inc -- Jeff Layton + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +static __le32 * +smb_verify_header(struct rpc_task *task) +{ + struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; + __le32 *p = iov->iov_base; + + if (task->tk_rqstp->rq_rcv_buf.len < sizeof(struct smb_header)) { + task->tk_action = call_bind; + task->tk_client->cl_stats->rpcretrans++; + return ERR_PTR(-EAGAIN); + } + + /* FIXME: check for errors and return them */ + + /* + * with SMB, we occasionally need to refer back to the SMB header for + * info (flags, etc). The header is fixed-length however, so just + * return a pointer to the start of the SMB header. + */ + return p; +} + +static __le32 * +smb_encode_header(struct rpc_task *task) +{ + struct rpc_rqst *req = task->tk_rqstp; + u32 *p = (u32 *) req->rq_svec[0].iov_base; + struct smb_header *h; + + /* transport header is always 32 bits */ + ++p; + memset(p, 0, sizeof(*h)); + + h = (struct smb_header *) p; + + h->protocol[0] = 0xFF; + h->protocol[1] = 'S'; + h->protocol[2] = 'M'; + h->protocol[3] = 'B'; + + h->command = task->tk_msg.rpc_proc->p_proc; + h->flags2 = SMB_FLAGS2_LONG_PATH_COMPONENTS; + h->pid = cpu_to_le16((u16) current->tgid); + h->pidhigh = cpu_to_le16((u16) (current->tgid >> 16)); + + /* + * SMB MID's are similar to XID's in RPC, but they're only 16 bits. + * For now we just use the xid field and mask off the upper bits. + */ + req->rq_xid &= 0x0000ffff; + h->mid = cpu_to_le16((u16) req->rq_xid); + + req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], (__be32 *) (h + 1)); + + return (__le32 *) (h + 1); +} + +void +smb_encode(struct rpc_task *task) +{ + struct rpc_rqst *req = task->tk_rqstp; + __le32 *p; + ksmbproc_t encode = (ksmbproc_t) task->tk_msg.rpc_proc->p_encode; + + rpc_xdr_buf_init(&req->rq_snd_buf, req->rq_buffer, req->rq_callsize); + rpc_xdr_buf_init(&req->rq_rcv_buf, + (char *)req->rq_buffer + req->rq_callsize, + req->rq_rcvsize); + + p = smb_encode_header(task); + + encode(req, p, NULL); + return; +} +EXPORT_SYMBOL_GPL(smb_encode); + +int +smb_decode(struct rpc_task *task) +{ + struct rpc_rqst *req = task->tk_rqstp; + kxdrproc_t decode = task->tk_msg.rpc_proc->p_decode; + __le32 *p; + + p = smb_verify_header(task); + if (IS_ERR(p)) + return PTR_ERR(p); + + if (decode) + task->tk_status = decode(req, p, task->tk_msg.rpc_resp); + + return 0; +} +EXPORT_SYMBOL_GPL(smb_decode);