From: Arnaldo Carvalho de Melo <acme@redhat.com>
To: "Rémi Denis-Courmont" <remi.denis-courmont@nokia.com>
Cc: netdev@vger.kernel.org
Subject: Re: [PATCH 07/14] Phonet: common socket glue
Date: Tue, 16 Sep 2008 13:50:17 -0300 [thread overview]
Message-ID: <20080916165017.GJ8702@ghostprotocols.net> (raw)
In-Reply-To: <1221577694-4513-7-git-send-email-remi.denis-courmont@nokia.com>
Em Tue, Sep 16, 2008 at 06:08:07PM +0300, Rémi Denis-Courmont escreveu:
> This provides the socket API for the Phonet protocols family.
>
> Signed-off-by: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
> ---
> include/linux/phonet.h | 3 +
> include/net/phonet/phonet.h | 20 +++
> net/phonet/Makefile | 1 +
> net/phonet/socket.c | 312 +++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 336 insertions(+), 0 deletions(-)
> create mode 100644 net/phonet/socket.c
>
> diff --git a/include/linux/phonet.h b/include/linux/phonet.h
> index 000b6d7..4510458 100644
> --- a/include/linux/phonet.h
> +++ b/include/linux/phonet.h
> @@ -32,6 +32,9 @@
> #define PNADDR_ANY 0
> #define PNPORT_RESOURCE_ROUTING 0
>
> +/* ioctls */
> +#define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0)
> +
> /* Phonet protocol header */
> struct phonethdr {
> uint8_t rdev;
> diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
> index d62883c..e0fa080 100644
> --- a/include/net/phonet/phonet.h
> +++ b/include/net/phonet/phonet.h
> @@ -29,6 +29,25 @@
> */
> #define MAX_PHONET_HEADER 8
>
> +/*
> + * Every Phonet* socket has this structure first in its
> + * protocol-specific structure under name c.
> + */
> +struct pn_sock {
> + struct sock sk;
> + u16 sobject;
> + u8 resource;
> +};
> +
> +#define pn_sk(sk) ((struct pn_sock *)(sk))
Why do this as a define and not like, say, tcp_sk(), that way you at
least guarantee that you will not end up using some non-sock pointer
as your pn_sock :)
> +extern const struct proto_ops phonet_dgram_ops;
> +
> +struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *sa);
> +void pn_sock_hash(struct sock *sk);
> +void pn_sock_unhash(struct sock *sk);
> +int pn_sock_get_port(struct sock *sk, unsigned short sport);
> +
> #define pn_hdr(skb) ((struct phonethdr *)skb_network_header(skb))
At least here skb_network_header() will do the typechecking for you.
> /*
> @@ -68,5 +87,6 @@ struct phonet_protocol {
> int phonet_proto_register(int protocol, struct phonet_protocol *pp);
> void phonet_proto_unregister(int protocol, struct phonet_protocol *pp);
>
> +void phonet_socket_init(void);
> void phonet_netlink_register(void);
> #endif
> diff --git a/net/phonet/Makefile b/net/phonet/Makefile
> index 4143c3e..c1d671d 100644
> --- a/net/phonet/Makefile
> +++ b/net/phonet/Makefile
> @@ -3,4 +3,5 @@ obj-$(CONFIG_PHONET) += phonet.o
> phonet-objs := \
> pn_dev.o \
> pn_netlink.o \
> + socket.o \
> af_phonet.o
> diff --git a/net/phonet/socket.c b/net/phonet/socket.c
> new file mode 100644
> index 0000000..0e28327
> --- /dev/null
> +++ b/net/phonet/socket.c
> @@ -0,0 +1,312 @@
> +/*
> + * File: socket.c
> + *
> + * Phonet sockets
> + *
> + * Copyright (C) 2008 Nokia Corporation.
> + *
> + * Contact: Remi Denis-Courmont <remi.denis-courmont@nokia.com>
> + * Original author: Sakari Ailus <sakari.ailus@nokia.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + *
> + * 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 St, Fifth Floor, Boston, MA
> + * 02110-1301 USA
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/net.h>
> +#include <net/sock.h>
> +#include <net/tcp_states.h>
> +
> +#include <linux/phonet.h>
> +#include <net/phonet/phonet.h>
> +#include <net/phonet/pn_dev.h>
> +
> +static int pn_socket_release(struct socket *sock)
> +{
> + struct sock *sk = sock->sk;
> +
> + if (sk) {
> + sock->sk = NULL;
> + sk->sk_prot->close(sk, 0);
> + }
> + return 0;
> +}
> +
> +static struct {
> + struct hlist_head hlist;
> + spinlock_t lock;
> +} pnsocks;
See tcp_death_row on how to initialize it right here and not at some
init function.
> +/*
> + * Find address based on socket address, match only certain fields.
> + * Also grab sock if it was found. Remember to sock_put it later.
> + */
> +struct sock *pn_find_sock_by_sa(const struct sockaddr_pn *spn)
> +{
> + struct hlist_node *node;
> + struct sock *sknode;
> + struct sock *rval = NULL;
> + uint16_t obj = pn_sockaddr_get_object(spn);
> + uint8_t res = spn->spn_resource;
> +
> + spin_lock_bh(&pnsocks.lock);
> +
> + sk_for_each(sknode, node, &pnsocks.hlist) {
> + struct pn_sock *pn = pn_sk(sknode);
> + BUG_ON(!pn->sobject); /* unbound socket */
> +
> + if (pn_port(obj)) {
> + /* Look up socket by port */
> + if (pn_port(pn->sobject) != pn_port(obj))
> + continue;
> + } else {
> + /* If port is zero, look up by resource */
> + if (pn->resource != res)
> + continue;
> + }
> + if (pn_addr(pn->sobject)
> + && pn_addr(pn->sobject) != pn_addr(obj))
Please && at the end of previous line
> + continue;
> +
> + rval = sknode;
> + sock_hold(sknode);
> + break;
> + }
> +
> + spin_unlock_bh(&pnsocks.lock);
> +
> + return rval;
> +
> +}
> +
> +void pn_sock_hash(struct sock *sk)
> +{
> + spin_lock_bh(&pnsocks.lock);
> + sk_add_node(sk, &pnsocks.hlist);
> + spin_unlock_bh(&pnsocks.lock);
> +}
> +EXPORT_SYMBOL(pn_sock_hash);
> +
> +void pn_sock_unhash(struct sock *sk)
> +{
> + spin_lock_bh(&pnsocks.lock);
> + sk_del_node_init(sk);
> + spin_unlock_bh(&pnsocks.lock);
> +}
> +EXPORT_SYMBOL(pn_sock_unhash);
> +
> +static int pn_socket_bind(struct socket *sock, struct sockaddr *addr, int len)
> +{
> + struct sock *sk = sock->sk;
> + struct pn_sock *pn = pn_sk(sk);
> + struct sockaddr_pn *spn = (struct sockaddr_pn *)addr;
> + int err;
> + uint16_t handle;
> + uint8_t saddr;
> +
> + if (sk->sk_prot->bind)
> + return sk->sk_prot->bind(sk, addr, len);
> +
> + if (len < sizeof(struct sockaddr_pn))
> + return -EINVAL;
> + if (spn->spn_family != AF_PHONET)
> + return -EAFNOSUPPORT;
> +
> + handle = pn_sockaddr_get_object((struct sockaddr_pn *)addr);
> + saddr = pn_addr(handle);
> + if (saddr) {
> + struct phonet_address *pna;
> +
> + spin_lock_bh(&pndevs.lock);
> + pna = phonet_addr2addr(pn_addr(handle), PN_FIND_EXACT);
> + spin_unlock_bh(&pndevs.lock);
> + if (pna == NULL)
> + return -EADDRNOTAVAIL;
> + }
> +
> + lock_sock(sk);
> + if (sk->sk_state != TCP_CLOSE || pn_port(pn->sobject)) {
> + err = -EINVAL; /* attempt to rebind */
> + goto out;
> + }
> + err = sk->sk_prot->get_port(sk, pn_port(handle));
> + if (err)
> + goto out;
> +
> + /* get_port() sets the port, bind() sets the address if applicable */
> + pn->sobject = pn_object(saddr, pn_port(pn->sobject));
> + pn->resource = spn->spn_resource;
> +
> + /* Enable RX on the socket */
> + sk->sk_prot->hash(sk);
> +out:
> + release_sock(sk);
> + return err;
> +}
> +
> +static int pn_socket_autobind(struct socket *sock)
> +{
> + struct sockaddr_pn sa;
> + int err;
> +
> + memset(&sa, 0, sizeof(sa));
> + sa.spn_family = AF_PHONET;
> + err = pn_socket_bind(sock, (struct sockaddr *)&sa,
> + sizeof(struct sockaddr_pn));
> + if (err != -EINVAL)
> + return err;
> + BUG_ON(!pn_port(pn_sk(sock->sk)->sobject));
> + return 0; /* socket was already bound */
> +}
> +
> +static int pn_socket_getname(struct socket *sock, struct sockaddr *addr,
> + int *sockaddr_len, int peer)
> +{
> + struct sock *sk = sock->sk;
> + struct pn_sock *pn = pn_sk(sk);
> +
> + memset(addr, 0, sizeof(struct sockaddr_pn));
> + addr->sa_family = AF_PHONET;
> + if (!peer) /* Race with bind() here is userland's problem. */
> + pn_sockaddr_set_object((struct sockaddr_pn *)addr,
> + pn->sobject);
> +
> + *sockaddr_len = sizeof(struct sockaddr_pn);
> + return 0;
> +}
> +
> +static int pn_socket_ioctl(struct socket *sock, unsigned int cmd,
> + unsigned long arg)
> +{
> + struct sock *sk = sock->sk;
> + struct pn_sock *pn = pn_sk(sk);
> +
> + if (cmd == SIOCPNGETOBJECT) {
> + struct phonet_address *pna;
> + uint16_t handle;
> + uint8_t rdev;
> +
> + if (get_user(handle, (uint16_t __user *)arg))
> + return -EFAULT;
> +
> + rdev = pn_dev(handle);
> + spin_lock_bh(&pndevs.lock);
> + pna = phonet_addr2addr(rdev, 0);
> + if (pna)
> + handle = pn_object(pna->addr, pn_port(pn->sobject));
> + spin_unlock_bh(&pndevs.lock);
> +
> + if (!pna)
> + return -EHOSTUNREACH;
> + return put_user(handle, (uint16_t __user *)arg);
> + }
> +
> + return sk->sk_prot->ioctl(sk, cmd, arg);
I guess it is a requirement that each protocol will provide an ioctl
handler.
> +}
> +
> +static int pn_socket_sendmsg(struct kiocb *iocb, struct socket *sock,
> + struct msghdr *m, size_t total_len)
> +{
> + struct sock *sk = sock->sk;
> +
> + if (pn_socket_autobind(sock))
> + return -EAGAIN;
> +
> + return sk->sk_prot->sendmsg(iocb, sk, m, total_len);
> +}
> +
> +const struct proto_ops phonet_dgram_ops = {
> + .family = AF_PHONET,
> + .owner = THIS_MODULE,
> + .release = pn_socket_release,
> + .bind = pn_socket_bind,
> + .connect = sock_no_connect,
> + .socketpair = sock_no_socketpair,
> + .accept = sock_no_accept,
> + .getname = pn_socket_getname,
> + .poll = datagram_poll,
> + .ioctl = pn_socket_ioctl,
> + .listen = sock_no_listen,
> + .shutdown = sock_no_shutdown,
> + .setsockopt = sock_no_setsockopt,
> + .getsockopt = sock_no_getsockopt,
> +#ifdef CONFIG_COMPAT
> + .compat_setsockopt = sock_no_setsockopt,
> + .compat_getsockopt = sock_no_getsockopt,
> +#endif
> + .sendmsg = pn_socket_sendmsg,
> + .recvmsg = sock_common_recvmsg,
> + .mmap = sock_no_mmap,
> + .sendpage = sock_no_sendpage,
> +};
> +
> +static DEFINE_MUTEX(port_mutex);
> +
> +/* allocate port for a socket */
> +int pn_sock_get_port(struct sock *sk, unsigned short sport)
> +{
> + static int port_cur;
> + struct pn_sock *pn = pn_sk(sk);
> + struct sockaddr_pn try_sa;
> + struct sock *tmpsk;
> +
> + memset(&try_sa, 0, sizeof(struct sockaddr_pn));
> + try_sa.spn_family = AF_PHONET;
> +
> + mutex_lock(&port_mutex);
> +
> + if (!sport) {
> + /* search free port */
> + int port, pmin = 0x40, pmax = 0x7f;
> +
> + for (port = pmin; port <= pmax; port++) {
> + port_cur++;
> + if (port_cur < pmin || port_cur > pmax)
> + port_cur = pmin;
> +
> + pn_sockaddr_set_port(&try_sa, port_cur);
> + tmpsk = pn_find_sock_by_sa(&try_sa);
> + if (tmpsk == NULL) {
> + sport = port_cur;
> + goto found;
> + } else
> + sock_put(tmpsk);
> + }
> + } else {
> + /* try to find specific port */
> + pn_sockaddr_set_port(&try_sa, sport);
> + tmpsk = pn_find_sock_by_sa(&try_sa);
> + if (tmpsk == NULL)
> + /* No sock there! We can use that port... */
> + goto found;
> + else
> + sock_put(tmpsk);
> + }
> + mutex_unlock(&port_mutex);
> +
> + /* the port must be in use already */
> + return -EADDRINUSE;
> +
> +found:
> + mutex_unlock(&port_mutex);
> + pn->sobject = pn_object(pn_addr(pn->sobject), sport);
> + return 0;
> +}
> +EXPORT_SYMBOL(pn_sock_get_port);
> +
> +void __init phonet_socket_init(void)
> +{
> + INIT_HLIST_HEAD(&pnsocks.hlist);
> + spin_lock_init(&pnsocks.lock);
> +}
> --
> 1.5.4.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2008-09-16 16:59 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-16 14:57 [PATCH 00/14] [RFC] Phonet protocol stack Rémi Denis-Courmont
2008-09-16 15:08 ` [PATCH 01/14] Phonet global definitions Rémi Denis-Courmont
2008-09-17 4:31 ` Simon Horman
2008-09-17 11:05 ` Rémi Denis-Courmont
2008-09-16 15:08 ` [PATCH 02/14] Phonet: add CONFIG_PHONET Rémi Denis-Courmont
2008-09-16 16:06 ` Arnaldo Carvalho de Melo
2008-09-16 15:08 ` [PATCH 03/14] Phonet: build the net/phonet/ directory Rémi Denis-Courmont
2008-09-16 16:06 ` Arnaldo Carvalho de Melo
2008-09-17 4:52 ` Simon Horman
2008-09-17 8:44 ` Rémi Denis-Courmont
2008-09-16 15:08 ` [PATCH 04/14] Phonet: PF_PHONET protocol family support Rémi Denis-Courmont
2008-09-16 16:17 ` Arnaldo Carvalho de Melo
2008-09-17 10:48 ` Rémi Denis-Courmont
2008-09-16 15:08 ` [PATCH 05/14] Phonet: network device and address handling Rémi Denis-Courmont
2008-09-16 16:41 ` Arnaldo Carvalho de Melo
2008-09-16 15:08 ` [PATCH 06/14] Phonet: Netlink interface Rémi Denis-Courmont
2008-09-16 15:08 ` [PATCH 07/14] Phonet: common socket glue Rémi Denis-Courmont
2008-09-16 16:50 ` Arnaldo Carvalho de Melo [this message]
2008-09-16 15:08 ` [PATCH 08/14] Phonet: receive path socket lookup Rémi Denis-Courmont
2008-09-16 16:52 ` Arnaldo Carvalho de Melo
2008-09-19 6:20 ` Rémi Denis-Courmont
2008-09-16 15:08 ` [PATCH 09/14] Phonet: allocate and initialize new sockets Rémi Denis-Courmont
2008-09-16 16:53 ` Arnaldo Carvalho de Melo
2008-09-16 18:42 ` Pavel Emelyanov
2008-09-17 8:30 ` Rémi Denis-Courmont
2008-09-19 10:14 ` Pavel Emelyanov
2008-09-16 15:08 ` [PATCH 10/14] Phonet: Phonet datagram transport protocol Rémi Denis-Courmont
2008-09-16 17:06 ` Arnaldo Carvalho de Melo
2008-09-19 6:33 ` Rémi Denis-Courmont
2008-09-19 15:24 ` [PATCH]: net: Use hton[sl]() was " Arnaldo Carvalho de Melo
2008-09-21 5:21 ` David Miller
2008-11-14 8:32 ` Piet Delaney
2008-09-16 15:08 ` [PATCH 11/14] Phonet: provide MAC header operations Rémi Denis-Courmont
2008-09-16 15:08 ` [PATCH 12/14] Phonet: proc interface for port range Rémi Denis-Courmont
2008-09-16 15:08 ` [PATCH 13/14] Phonet: emit errors when a packet cannot be delivered locally Rémi Denis-Courmont
2008-09-16 17:11 ` Arnaldo Carvalho de Melo
2008-09-16 15:08 ` [PATCH 14/14] Phonet: kernel documentation Rémi Denis-Courmont
2008-09-16 20:09 ` [PATCH 00/14] [RFC] Phonet protocol stack Marcel Holtmann
2008-09-17 13:52 ` Rémi Denis-Courmont
2008-09-17 4:15 ` Dan Williams
2008-09-19 7:25 ` Rémi Denis-Courmont
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080916165017.GJ8702@ghostprotocols.net \
--to=acme@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=remi.denis-courmont@nokia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).