Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/886/?format=api
{ "id": 886, "url": "http://patchwork.ozlabs.org/api/patches/886/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/1222098445-26175-6-git-send-email-remi.denis-courmont@nokia.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1222098445-26175-6-git-send-email-remi.denis-courmont@nokia.com>", "list_archive_url": null, "date": "2008-09-22T15:47:20", "name": "[06/11] Phonet: common socket glue", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": true, "hash": "b94c98517c0c8109e7e5cbbecfa91c6659de75d5", "submitter": { "id": 204, "url": "http://patchwork.ozlabs.org/api/people/204/?format=api", "name": "Rémi Denis-Courmont", "email": "remi.denis-courmont@nokia.com" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/1222098445-26175-6-git-send-email-remi.denis-courmont@nokia.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/886/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/886/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.176.167])\n\tby ozlabs.org (Postfix) with ESMTP id 0F865DDF25\n\tfor <patchwork-incoming@ozlabs.org>;\n\tTue, 23 Sep 2008 01:48:31 +1000 (EST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1753724AbYIVPrv (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tMon, 22 Sep 2008 11:47:51 -0400", "(majordomo@vger.kernel.org) by vger.kernel.org id S1753631AbYIVPru\n\t(ORCPT <rfc822; netdev-outgoing>); Mon, 22 Sep 2008 11:47:50 -0400", "from smtp.nokia.com ([192.100.122.233]:53004 \"EHLO\n\tmgw-mx06.nokia.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1753462AbYIVPrp (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Mon, 22 Sep 2008 11:47:45 -0400", "from vaebh105.NOE.Nokia.com (vaebh105.europe.nokia.com\n\t[10.160.244.31])\n\tby mgw-mx06.nokia.com (Switch-3.2.6/Switch-3.2.6) with ESMTP id\n\tm8MFlZFZ027641\n\tfor <netdev@vger.kernel.org>; Mon, 22 Sep 2008 18:47:42 +0300", "from vaebh102.NOE.Nokia.com ([10.160.244.23]) by\n\tvaebh105.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); \n\tMon, 22 Sep 2008 18:47:35 +0300", "from localhost.localdomain ([172.21.41.115]) by\n\tvaebh102.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); \n\tMon, 22 Sep 2008 18:47:26 +0300" ], "From": "=?utf-8?q?R=C3=A9mi=20Denis-Courmont?= <remi.denis-courmont@nokia.com>", "To": "netdev@vger.kernel.org", "Subject": "[PATCH 06/11] Phonet: common socket glue", "Date": "Mon, 22 Sep 2008 18:47:20 +0300", "Message-Id": "<1222098445-26175-6-git-send-email-remi.denis-courmont@nokia.com>", "X-Mailer": "git-send-email 1.5.4.3", "In-Reply-To": "<200809221845.54736.remi.denis-courmont@nokia.com>", "References": "<200809221845.54736.remi.denis-courmont@nokia.com>", "X-OriginalArrivalTime": "22 Sep 2008 15:47:26.0663 (UTC)\n\tFILETIME=[832EE570:01C91CCA]", "X-Nokia-AV": "Clean", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "This provides the socket API for the Phonet protocols family.\n\nSigned-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>\n---\n include/linux/phonet.h | 3 +\n include/net/phonet/phonet.h | 23 +++\n net/phonet/Makefile | 1 +\n net/phonet/af_phonet.c | 28 ++++-\n net/phonet/socket.c | 311 +++++++++++++++++++++++++++++++++++++++++++\n 5 files changed, 363 insertions(+), 3 deletions(-)\n create mode 100644 net/phonet/socket.c", "diff": "diff --git a/include/linux/phonet.h b/include/linux/phonet.h\nindex 6a764f8..001c0e6 100644\n--- a/include/linux/phonet.h\n+++ b/include/linux/phonet.h\n@@ -32,6 +32,9 @@\n #define PNADDR_ANY\t\t0\n #define PNPORT_RESOURCE_ROUTING\t0\n \n+/* ioctls */\n+#define SIOCPNGETOBJECT\t\t(SIOCPROTOPRIVATE + 0)\n+\n /* Phonet protocol header */\n struct phonethdr {\n \t__u8\tpn_rdev;\ndiff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h\nindex 8b77794..2ae5cbb 100644\n--- a/include/net/phonet/phonet.h\n+++ b/include/net/phonet/phonet.h\n@@ -29,6 +29,28 @@\n */\n #define MAX_PHONET_HEADER\t8\n \n+/*\n+ * Every Phonet* socket has this structure first in its\n+ * protocol-specific structure under name c.\n+ */\n+struct pn_sock {\n+\tstruct sock\tsk;\n+\tu16\t\tsobject;\n+\tu8\t\tresource;\n+};\n+\n+static inline struct pn_sock *pn_sk(struct sock *sk)\n+{\n+\treturn (struct pn_sock *)sk;\n+}\n+\n+extern const struct proto_ops phonet_dgram_ops;\n+\n+struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa);\n+void pn_sock_hash(struct sock *sk);\n+void pn_sock_unhash(struct sock *sk);\n+int pn_sock_get_port(struct sock *sk, unsigned short sport);\n+\n static inline struct phonethdr *pn_hdr(struct sk_buff *skb)\n {\n \treturn (struct phonethdr *)skb_network_header(skb);\n@@ -64,6 +86,7 @@ void pn_skb_get_dst_sockaddr(struct sk_buff *skb, struct sockaddr_pn *sa)\n \n /* Protocols in Phonet protocol family. */\n struct phonet_protocol {\n+\tconst struct proto_ops\t*ops;\n \tstruct proto\t\t*prot;\n \tint\t\t\tsock_type;\n };\ndiff --git a/net/phonet/Makefile b/net/phonet/Makefile\nindex 4143c3e..c1d671d 100644\n--- a/net/phonet/Makefile\n+++ b/net/phonet/Makefile\n@@ -3,4 +3,5 @@ obj-$(CONFIG_PHONET) += phonet.o\n phonet-objs := \\\n \tpn_dev.o \\\n \tpn_netlink.o \\\n+\tsocket.o \\\n \taf_phonet.o\ndiff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c\nindex 5c729ba..ba54d53 100644\n--- a/net/phonet/af_phonet.c\n+++ b/net/phonet/af_phonet.c\n@@ -41,6 +41,8 @@ static inline void phonet_proto_put(struct phonet_protocol *pp);\n \n static int pn_socket_create(struct net *net, struct socket *sock, int protocol)\n {\n+\tstruct sock *sk;\n+\tstruct pn_sock *pn;\n \tstruct phonet_protocol *pnp;\n \tint err;\n \n@@ -69,8 +71,22 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol)\n \t\tgoto out;\n \t}\n \n-\t/* TODO: create and init the struct sock */\n-\terr = -EPROTONOSUPPORT;\n+\tsk = sk_alloc(net, PF_PHONET, GFP_KERNEL, pnp->prot);\n+\tif (sk == NULL) {\n+\t\terr = -ENOMEM;\n+\t\tgoto out;\n+\t}\n+\n+\tsock_init_data(sock, sk);\n+\tsock->state = SS_UNCONNECTED;\n+\tsock->ops = pnp->ops;\n+\tsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;\n+\tsk->sk_protocol = protocol;\n+\tpn = pn_sk(sk);\n+\tpn->sobject = 0;\n+\tpn->resource = 0;\n+\tsk->sk_prot->init(sk);\n+\terr = 0;\n \n out:\n \tphonet_proto_put(pnp);\n@@ -94,6 +110,7 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,\n \t\t\tstruct net_device *orig_dev)\n {\n \tstruct phonethdr *ph;\n+\tstruct sock *sk;\n \tstruct sockaddr_pn sa;\n \tu16 len;\n \n@@ -118,7 +135,12 @@ static int phonet_rcv(struct sk_buff *skb, struct net_device *dev,\n \tif (pn_sockaddr_get_addr(&sa) == 0)\n \t\tgoto out; /* currently, we cannot be device 0 */\n \n-\t/* TODO: put packets to sockets backlog */\n+\tsk = pn_find_sock_by_sa(&sa);\n+\tif (sk == NULL)\n+\t\tgoto out;\n+\n+\t/* Push data to the socket (or other sockets connected to it). */\n+\treturn sk_receive_skb(sk, skb, 0);\n \n out:\n \tkfree_skb(skb);\ndiff --git a/net/phonet/socket.c b/net/phonet/socket.c\nnew file mode 100644\nindex 0000000..99a4945\n--- /dev/null\n+++ b/net/phonet/socket.c\n@@ -0,0 +1,311 @@\n+/*\n+ * File: socket.c\n+ *\n+ * Phonet sockets\n+ *\n+ * Copyright (C) 2008 Nokia Corporation.\n+ *\n+ * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>\n+ * Original author: Sakari Ailus <sakari.ailus@nokia.com>\n+ *\n+ * This program is free software; you can redistribute it and/or\n+ * modify it under the terms of the GNU General Public License\n+ * version 2 as published by the Free Software Foundation.\n+ *\n+ * This program is distributed in the hope that it will be useful, but\n+ * WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n+ * General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA\n+ * 02110-1301 USA\n+ */\n+\n+#include <linux/kernel.h>\n+#include <linux/net.h>\n+#include <net/sock.h>\n+#include <net/tcp_states.h>\n+\n+#include <linux/phonet.h>\n+#include <net/phonet/phonet.h>\n+#include <net/phonet/pn_dev.h>\n+\n+static int pn_socket_release(struct socket *sock)\n+{\n+\tstruct sock *sk = sock->sk;\n+\n+\tif (sk) {\n+\t\tsock->sk = NULL;\n+\t\tsk->sk_prot->close(sk, 0);\n+\t}\n+\treturn 0;\n+}\n+\n+static struct {\n+\tstruct hlist_head hlist;\n+\tspinlock_t lock;\n+} pnsocks = {\n+\t.hlist = HLIST_HEAD_INIT,\n+\t.lock = __SPIN_LOCK_UNLOCKED(pnsocks.lock),\n+};\n+\n+/*\n+ * Find address based on socket address, match only certain fields.\n+ * Also grab sock if it was found. Remember to sock_put it later.\n+ */\n+struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *spn)\n+{\n+\tstruct hlist_node *node;\n+\tstruct sock *sknode;\n+\tstruct sock *rval = NULL;\n+\tu16 obj = pn_sockaddr_get_object(spn);\n+\tu8 res = spn->spn_resource;\n+\n+\tspin_lock_bh(&pnsocks.lock);\n+\n+\tsk_for_each(sknode, node, &pnsocks.hlist) {\n+\t\tstruct pn_sock *pn = pn_sk(sknode);\n+\t\tBUG_ON(!pn->sobject); /* unbound socket */\n+\n+\t\tif (pn_port(obj)) {\n+\t\t\t/* Look up socket by port */\n+\t\t\tif (pn_port(pn->sobject) != pn_port(obj))\n+\t\t\t\tcontinue;\n+\t\t} else {\n+\t\t\t/* If port is zero, look up by resource */\n+\t\t\tif (pn->resource != res)\n+\t\t\t\tcontinue;\n+\t\t}\n+\t\tif (pn_addr(pn->sobject)\n+\t\t && pn_addr(pn->sobject) != pn_addr(obj))\n+\t\t\tcontinue;\n+\n+\t\trval = sknode;\n+\t\tsock_hold(sknode);\n+\t\tbreak;\n+\t}\n+\n+\tspin_unlock_bh(&pnsocks.lock);\n+\n+\treturn rval;\n+\n+}\n+\n+void pn_sock_hash(struct sock *sk)\n+{\n+\tspin_lock_bh(&pnsocks.lock);\n+\tsk_add_node(sk, &pnsocks.hlist);\n+\tspin_unlock_bh(&pnsocks.lock);\n+}\n+EXPORT_SYMBOL(pn_sock_hash);\n+\n+void pn_sock_unhash(struct sock *sk)\n+{\n+\tspin_lock_bh(&pnsocks.lock);\n+\tsk_del_node_init(sk);\n+\tspin_unlock_bh(&pnsocks.lock);\n+}\n+EXPORT_SYMBOL(pn_sock_unhash);\n+\n+static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)\n+{\n+\tstruct sock *sk = sock->sk;\n+\tstruct pn_sock *pn = pn_sk(sk);\n+\tstruct sockaddr_pn *spn = (struct sockaddr_pn *)addr;\n+\tint err;\n+\tu16 handle;\n+\tu8 saddr;\n+\n+\tif (sk->sk_prot->bind)\n+\t\treturn sk->sk_prot->bind(sk, addr, len);\n+\n+\tif (len < sizeof(struct sockaddr_pn))\n+\t\treturn -EINVAL;\n+\tif (spn->spn_family != AF_PHONET)\n+\t\treturn -EAFNOSUPPORT;\n+\n+\thandle = pn_sockaddr_get_object((struct sockaddr_pn *)addr);\n+\tsaddr = pn_addr(handle);\n+\tif (saddr && phonet_address_lookup(saddr))\n+\t\treturn -EADDRNOTAVAIL;\n+\n+\tlock_sock(sk);\n+\tif (sk->sk_state != TCP_CLOSE || pn_port(pn->sobject)) {\n+\t\terr = -EINVAL; /* attempt to rebind */\n+\t\tgoto out;\n+\t}\n+\terr = sk->sk_prot->get_port(sk, pn_port(handle));\n+\tif (err)\n+\t\tgoto out;\n+\n+\t/* get_port() sets the port, bind() sets the address if applicable */\n+\tpn->sobject = pn_object(saddr, pn_port(pn->sobject));\n+\tpn->resource = spn->spn_resource;\n+\n+\t/* Enable RX on the socket */\n+\tsk->sk_prot->hash(sk);\n+out:\n+\trelease_sock(sk);\n+\treturn err;\n+}\n+\n+static int pn_socket_autobind(struct socket *sock)\n+{\n+\tstruct sockaddr_pn sa;\n+\tint err;\n+\n+\tmemset(&sa, 0, sizeof(sa));\n+\tsa.spn_family = AF_PHONET;\n+\terr = pn_socket_bind(sock, (struct sockaddr *)&sa,\n+\t\t\t\tsizeof(struct sockaddr_pn));\n+\tif (err != -EINVAL)\n+\t\treturn err;\n+\tBUG_ON(!pn_port(pn_sk(sock->sk)->sobject));\n+\treturn 0; /* socket was already bound */\n+}\n+\n+static int pn_socket_getname(struct socket *sock, struct sockaddr *addr,\n+\t\t\t\tint *sockaddr_len, int peer)\n+{\n+\tstruct sock *sk = sock->sk;\n+\tstruct pn_sock *pn = pn_sk(sk);\n+\n+\tmemset(addr, 0, sizeof(struct sockaddr_pn));\n+\taddr->sa_family = AF_PHONET;\n+\tif (!peer) /* Race with bind() here is userland's problem. */\n+\t\tpn_sockaddr_set_object((struct sockaddr_pn *)addr,\n+\t\t\t\t\tpn->sobject);\n+\n+\t*sockaddr_len = sizeof(struct sockaddr_pn);\n+\treturn 0;\n+}\n+\n+static int pn_socket_ioctl(struct socket *sock, unsigned int cmd,\n+\t\t\t\tunsigned long arg)\n+{\n+\tstruct sock *sk = sock->sk;\n+\tstruct pn_sock *pn = pn_sk(sk);\n+\n+\tif (cmd == SIOCPNGETOBJECT) {\n+\t\tstruct net_device *dev;\n+\t\tu16 handle;\n+\t\tu8 saddr;\n+\n+\t\tif (get_user(handle, (__u16 __user *)arg))\n+\t\t\treturn -EFAULT;\n+\n+\t\tlock_sock(sk);\n+\t\tif (sk->sk_bound_dev_if)\n+\t\t\tdev = dev_get_by_index(sock_net(sk),\n+\t\t\t\t\t\tsk->sk_bound_dev_if);\n+\t\telse\n+\t\t\tdev = phonet_device_get(sock_net(sk));\n+\t\tif (dev && (dev->flags & IFF_UP))\n+\t\t\tsaddr = phonet_address_get(dev, pn_addr(handle));\n+\t\telse\n+\t\t\tsaddr = PN_NO_ADDR;\n+\t\trelease_sock(sk);\n+\n+\t\tif (dev)\n+\t\t\tdev_put(dev);\n+\t\tif (saddr == PN_NO_ADDR)\n+\t\t\treturn -EHOSTUNREACH;\n+\n+\t\thandle = pn_object(saddr, pn_port(pn->sobject));\n+\t\treturn put_user(handle, (__u16 __user *)arg);\n+\t}\n+\n+\treturn sk->sk_prot->ioctl(sk, cmd, arg);\n+}\n+\n+static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock,\n+\t\t\t\tstruct msghdr *m, size_t total_len)\n+{\n+\tstruct sock *sk = sock->sk;\n+\n+\tif (pn_socket_autobind(sock))\n+\t\treturn -EAGAIN;\n+\n+\treturn sk->sk_prot->sendmsg(iocb, sk, m, total_len);\n+}\n+\n+const struct proto_ops phonet_dgram_ops = {\n+\t.family\t\t= AF_PHONET,\n+\t.owner\t\t= THIS_MODULE,\n+\t.release\t= pn_socket_release,\n+\t.bind\t\t= pn_socket_bind,\n+\t.connect\t= sock_no_connect,\n+\t.socketpair\t= sock_no_socketpair,\n+\t.accept\t\t= sock_no_accept,\n+\t.getname\t= pn_socket_getname,\n+\t.poll\t\t= datagram_poll,\n+\t.ioctl\t\t= pn_socket_ioctl,\n+\t.listen\t\t= sock_no_listen,\n+\t.shutdown\t= sock_no_shutdown,\n+\t.setsockopt\t= sock_no_setsockopt,\n+\t.getsockopt\t= sock_no_getsockopt,\n+#ifdef CONFIG_COMPAT\n+\t.compat_setsockopt = sock_no_setsockopt,\n+\t.compat_getsockopt = sock_no_getsockopt,\n+#endif\n+\t.sendmsg\t= pn_socket_sendmsg,\n+\t.recvmsg\t= sock_common_recvmsg,\n+\t.mmap\t\t= sock_no_mmap,\n+\t.sendpage\t= sock_no_sendpage,\n+};\n+\n+static DEFINE_MUTEX(port_mutex);\n+\n+/* allocate port for a socket */\n+int pn_sock_get_port(struct sock *sk, unsigned short sport)\n+{\n+\tstatic int port_cur;\n+\tstruct pn_sock *pn = pn_sk(sk);\n+\tstruct sockaddr_pn try_sa;\n+\tstruct sock *tmpsk;\n+\n+\tmemset(&try_sa, 0, sizeof(struct sockaddr_pn));\n+\ttry_sa.spn_family = AF_PHONET;\n+\n+\tmutex_lock(&port_mutex);\n+\n+\tif (!sport) {\n+\t\t/* search free port */\n+\t\tint port, pmin = 0x40, pmax = 0x7f;\n+\n+\t\tfor (port = pmin; port <= pmax; port++) {\n+\t\t\tport_cur++;\n+\t\t\tif (port_cur < pmin || port_cur > pmax)\n+\t\t\t\tport_cur = pmin;\n+\n+\t\t\tpn_sockaddr_set_port(&try_sa, port_cur);\n+\t\t\ttmpsk = pn_find_sock_by_sa(&try_sa);\n+\t\t\tif (tmpsk == NULL) {\n+\t\t\t\tsport = port_cur;\n+\t\t\t\tgoto found;\n+\t\t\t} else\n+\t\t\t\tsock_put(tmpsk);\n+\t\t}\n+\t} else {\n+\t\t/* try to find specific port */\n+\t\tpn_sockaddr_set_port(&try_sa, sport);\n+\t\ttmpsk = pn_find_sock_by_sa(&try_sa);\n+\t\tif (tmpsk == NULL)\n+\t\t\t/* No sock there! We can use that port... */\n+\t\t\tgoto found;\n+\t\telse\n+\t\t\tsock_put(tmpsk);\n+\t}\n+\tmutex_unlock(&port_mutex);\n+\n+\t/* the port must be in use already */\n+\treturn -EADDRINUSE;\n+\n+found:\n+\tmutex_unlock(&port_mutex);\n+\tpn->sobject = pn_object(pn_addr(pn->sobject), sport);\n+\treturn 0;\n+}\n+EXPORT_SYMBOL(pn_sock_get_port);\n", "prefixes": [ "06/11" ] }