All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.