xref: /openbmc/linux/net/ieee802154/socket.c (revision dc97391e)
11802d0beSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
271e36b1bSAlexander Aring /*
371e36b1bSAlexander Aring  * IEEE802154.4 socket interface
471e36b1bSAlexander Aring  *
571e36b1bSAlexander Aring  * Copyright 2007, 2008 Siemens AG
671e36b1bSAlexander Aring  *
771e36b1bSAlexander Aring  * Written by:
871e36b1bSAlexander Aring  * Sergey Lapin <slapin@ossfans.org>
971e36b1bSAlexander Aring  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
1071e36b1bSAlexander Aring  */
1171e36b1bSAlexander Aring 
1271e36b1bSAlexander Aring #include <linux/net.h>
1371e36b1bSAlexander Aring #include <linux/capability.h>
1471e36b1bSAlexander Aring #include <linux/module.h>
1571e36b1bSAlexander Aring #include <linux/if_arp.h>
1671e36b1bSAlexander Aring #include <linux/if.h>
1771e36b1bSAlexander Aring #include <linux/termios.h>	/* For TIOCOUTQ/INQ */
1871e36b1bSAlexander Aring #include <linux/list.h>
1971e36b1bSAlexander Aring #include <linux/slab.h>
20811e299fSRomuald CARI #include <linux/socket.h>
2171e36b1bSAlexander Aring #include <net/datalink.h>
2271e36b1bSAlexander Aring #include <net/psnap.h>
2371e36b1bSAlexander Aring #include <net/sock.h>
2471e36b1bSAlexander Aring #include <net/tcp_states.h>
2571e36b1bSAlexander Aring #include <net/route.h>
2671e36b1bSAlexander Aring 
2771e36b1bSAlexander Aring #include <net/af_ieee802154.h>
2871e36b1bSAlexander Aring #include <net/ieee802154_netdev.h>
2971e36b1bSAlexander Aring 
3071e36b1bSAlexander Aring /* Utility function for families */
3171e36b1bSAlexander Aring static struct net_device*
ieee802154_get_dev(struct net * net,const struct ieee802154_addr * addr)3271e36b1bSAlexander Aring ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr)
3371e36b1bSAlexander Aring {
3471e36b1bSAlexander Aring 	struct net_device *dev = NULL;
3571e36b1bSAlexander Aring 	struct net_device *tmp;
3671e36b1bSAlexander Aring 	__le16 pan_id, short_addr;
3771e36b1bSAlexander Aring 	u8 hwaddr[IEEE802154_ADDR_LEN];
3871e36b1bSAlexander Aring 
3971e36b1bSAlexander Aring 	switch (addr->mode) {
4071e36b1bSAlexander Aring 	case IEEE802154_ADDR_LONG:
4171e36b1bSAlexander Aring 		ieee802154_devaddr_to_raw(hwaddr, addr->extended_addr);
4271e36b1bSAlexander Aring 		rcu_read_lock();
4371e36b1bSAlexander Aring 		dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, hwaddr);
4471e36b1bSAlexander Aring 		dev_hold(dev);
4571e36b1bSAlexander Aring 		rcu_read_unlock();
4671e36b1bSAlexander Aring 		break;
4771e36b1bSAlexander Aring 	case IEEE802154_ADDR_SHORT:
4871e36b1bSAlexander Aring 		if (addr->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST) ||
4971e36b1bSAlexander Aring 		    addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
5071e36b1bSAlexander Aring 		    addr->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST))
5171e36b1bSAlexander Aring 			break;
5271e36b1bSAlexander Aring 
5371e36b1bSAlexander Aring 		rtnl_lock();
5471e36b1bSAlexander Aring 
5571e36b1bSAlexander Aring 		for_each_netdev(net, tmp) {
5671e36b1bSAlexander Aring 			if (tmp->type != ARPHRD_IEEE802154)
5771e36b1bSAlexander Aring 				continue;
5871e36b1bSAlexander Aring 
59c947f7e1SAlexander Aring 			pan_id = tmp->ieee802154_ptr->pan_id;
60c947f7e1SAlexander Aring 			short_addr = tmp->ieee802154_ptr->short_addr;
6171e36b1bSAlexander Aring 			if (pan_id == addr->pan_id &&
6271e36b1bSAlexander Aring 			    short_addr == addr->short_addr) {
6371e36b1bSAlexander Aring 				dev = tmp;
6471e36b1bSAlexander Aring 				dev_hold(dev);
6571e36b1bSAlexander Aring 				break;
6671e36b1bSAlexander Aring 			}
6771e36b1bSAlexander Aring 		}
6871e36b1bSAlexander Aring 
6971e36b1bSAlexander Aring 		rtnl_unlock();
7071e36b1bSAlexander Aring 		break;
7171e36b1bSAlexander Aring 	default:
7271e36b1bSAlexander Aring 		pr_warn("Unsupported ieee802154 address type: %d\n",
7371e36b1bSAlexander Aring 			addr->mode);
7471e36b1bSAlexander Aring 		break;
7571e36b1bSAlexander Aring 	}
7671e36b1bSAlexander Aring 
7771e36b1bSAlexander Aring 	return dev;
7871e36b1bSAlexander Aring }
7971e36b1bSAlexander Aring 
ieee802154_sock_release(struct socket * sock)8071e36b1bSAlexander Aring static int ieee802154_sock_release(struct socket *sock)
8171e36b1bSAlexander Aring {
8271e36b1bSAlexander Aring 	struct sock *sk = sock->sk;
8371e36b1bSAlexander Aring 
8471e36b1bSAlexander Aring 	if (sk) {
8571e36b1bSAlexander Aring 		sock->sk = NULL;
8671e36b1bSAlexander Aring 		sk->sk_prot->close(sk, 0);
8771e36b1bSAlexander Aring 	}
8871e36b1bSAlexander Aring 	return 0;
8971e36b1bSAlexander Aring }
9071e36b1bSAlexander Aring 
ieee802154_sock_sendmsg(struct socket * sock,struct msghdr * msg,size_t len)911b784140SYing Xue static int ieee802154_sock_sendmsg(struct socket *sock, struct msghdr *msg,
921b784140SYing Xue 				   size_t len)
9371e36b1bSAlexander Aring {
9471e36b1bSAlexander Aring 	struct sock *sk = sock->sk;
9571e36b1bSAlexander Aring 
961b784140SYing Xue 	return sk->sk_prot->sendmsg(sk, msg, len);
9771e36b1bSAlexander Aring }
9871e36b1bSAlexander Aring 
ieee802154_sock_bind(struct socket * sock,struct sockaddr * uaddr,int addr_len)9971e36b1bSAlexander Aring static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr,
10071e36b1bSAlexander Aring 				int addr_len)
10171e36b1bSAlexander Aring {
10271e36b1bSAlexander Aring 	struct sock *sk = sock->sk;
10371e36b1bSAlexander Aring 
10471e36b1bSAlexander Aring 	if (sk->sk_prot->bind)
10571e36b1bSAlexander Aring 		return sk->sk_prot->bind(sk, uaddr, addr_len);
10671e36b1bSAlexander Aring 
10771e36b1bSAlexander Aring 	return sock_no_bind(sock, uaddr, addr_len);
10871e36b1bSAlexander Aring }
10971e36b1bSAlexander Aring 
ieee802154_sock_connect(struct socket * sock,struct sockaddr * uaddr,int addr_len,int flags)11071e36b1bSAlexander Aring static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr,
11171e36b1bSAlexander Aring 				   int addr_len, int flags)
11271e36b1bSAlexander Aring {
11371e36b1bSAlexander Aring 	struct sock *sk = sock->sk;
11471e36b1bSAlexander Aring 
11571e36b1bSAlexander Aring 	if (addr_len < sizeof(uaddr->sa_family))
11671e36b1bSAlexander Aring 		return -EINVAL;
11771e36b1bSAlexander Aring 
11871e36b1bSAlexander Aring 	if (uaddr->sa_family == AF_UNSPEC)
11971e36b1bSAlexander Aring 		return sk->sk_prot->disconnect(sk, flags);
12071e36b1bSAlexander Aring 
12171e36b1bSAlexander Aring 	return sk->sk_prot->connect(sk, uaddr, addr_len);
12271e36b1bSAlexander Aring }
12371e36b1bSAlexander Aring 
ieee802154_dev_ioctl(struct sock * sk,struct ifreq __user * arg,unsigned int cmd)12471e36b1bSAlexander Aring static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg,
12571e36b1bSAlexander Aring 				unsigned int cmd)
12671e36b1bSAlexander Aring {
12771e36b1bSAlexander Aring 	struct ifreq ifr;
12871e36b1bSAlexander Aring 	int ret = -ENOIOCTLCMD;
12971e36b1bSAlexander Aring 	struct net_device *dev;
13071e36b1bSAlexander Aring 
13129c49648SArnd Bergmann 	if (get_user_ifreq(&ifr, NULL, arg))
13271e36b1bSAlexander Aring 		return -EFAULT;
13371e36b1bSAlexander Aring 
13471e36b1bSAlexander Aring 	ifr.ifr_name[IFNAMSIZ-1] = 0;
13571e36b1bSAlexander Aring 
13671e36b1bSAlexander Aring 	dev_load(sock_net(sk), ifr.ifr_name);
13771e36b1bSAlexander Aring 	dev = dev_get_by_name(sock_net(sk), ifr.ifr_name);
13871e36b1bSAlexander Aring 
13971e36b1bSAlexander Aring 	if (!dev)
14071e36b1bSAlexander Aring 		return -ENODEV;
14171e36b1bSAlexander Aring 
14271e36b1bSAlexander Aring 	if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl)
14371e36b1bSAlexander Aring 		ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd);
14471e36b1bSAlexander Aring 
14529c49648SArnd Bergmann 	if (!ret && put_user_ifreq(&ifr, arg))
14671e36b1bSAlexander Aring 		ret = -EFAULT;
14771e36b1bSAlexander Aring 	dev_put(dev);
14871e36b1bSAlexander Aring 
14971e36b1bSAlexander Aring 	return ret;
15071e36b1bSAlexander Aring }
15171e36b1bSAlexander Aring 
ieee802154_sock_ioctl(struct socket * sock,unsigned int cmd,unsigned long arg)15271e36b1bSAlexander Aring static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd,
15371e36b1bSAlexander Aring 				 unsigned long arg)
15471e36b1bSAlexander Aring {
15571e36b1bSAlexander Aring 	struct sock *sk = sock->sk;
15671e36b1bSAlexander Aring 
15771e36b1bSAlexander Aring 	switch (cmd) {
15871e36b1bSAlexander Aring 	case SIOCGIFADDR:
15971e36b1bSAlexander Aring 	case SIOCSIFADDR:
16071e36b1bSAlexander Aring 		return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg,
16171e36b1bSAlexander Aring 				cmd);
16271e36b1bSAlexander Aring 	default:
16371e36b1bSAlexander Aring 		if (!sk->sk_prot->ioctl)
16471e36b1bSAlexander Aring 			return -ENOIOCTLCMD;
165*e1d001faSBreno Leitao 		return sk_ioctl(sk, cmd, (void __user *)arg);
16671e36b1bSAlexander Aring 	}
16771e36b1bSAlexander Aring }
16871e36b1bSAlexander Aring 
16971e36b1bSAlexander Aring /* RAW Sockets (802.15.4 created in userspace) */
17071e36b1bSAlexander Aring static HLIST_HEAD(raw_head);
17171e36b1bSAlexander Aring static DEFINE_RWLOCK(raw_lock);
17271e36b1bSAlexander Aring 
raw_hash(struct sock * sk)173086c653fSCraig Gallek static int raw_hash(struct sock *sk)
17471e36b1bSAlexander Aring {
17571e36b1bSAlexander Aring 	write_lock_bh(&raw_lock);
17671e36b1bSAlexander Aring 	sk_add_node(sk, &raw_head);
17771e36b1bSAlexander Aring 	write_unlock_bh(&raw_lock);
178b3cb764aSEric Dumazet 	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
179086c653fSCraig Gallek 
180086c653fSCraig Gallek 	return 0;
18171e36b1bSAlexander Aring }
18271e36b1bSAlexander Aring 
raw_unhash(struct sock * sk)18371e36b1bSAlexander Aring static void raw_unhash(struct sock *sk)
18471e36b1bSAlexander Aring {
18571e36b1bSAlexander Aring 	write_lock_bh(&raw_lock);
18671e36b1bSAlexander Aring 	if (sk_del_node_init(sk))
18771e36b1bSAlexander Aring 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
18871e36b1bSAlexander Aring 	write_unlock_bh(&raw_lock);
18971e36b1bSAlexander Aring }
19071e36b1bSAlexander Aring 
raw_close(struct sock * sk,long timeout)19171e36b1bSAlexander Aring static void raw_close(struct sock *sk, long timeout)
19271e36b1bSAlexander Aring {
19371e36b1bSAlexander Aring 	sk_common_release(sk);
19471e36b1bSAlexander Aring }
19571e36b1bSAlexander Aring 
raw_bind(struct sock * sk,struct sockaddr * _uaddr,int len)19671e36b1bSAlexander Aring static int raw_bind(struct sock *sk, struct sockaddr *_uaddr, int len)
19771e36b1bSAlexander Aring {
19871e36b1bSAlexander Aring 	struct ieee802154_addr addr;
19971e36b1bSAlexander Aring 	struct sockaddr_ieee802154 *uaddr = (struct sockaddr_ieee802154 *)_uaddr;
20071e36b1bSAlexander Aring 	int err = 0;
20171e36b1bSAlexander Aring 	struct net_device *dev = NULL;
20271e36b1bSAlexander Aring 
20394160108SHaimin Zhang 	err = ieee802154_sockaddr_check_size(uaddr, len);
20494160108SHaimin Zhang 	if (err < 0)
20594160108SHaimin Zhang 		return err;
20671e36b1bSAlexander Aring 
20771e36b1bSAlexander Aring 	uaddr = (struct sockaddr_ieee802154 *)_uaddr;
20871e36b1bSAlexander Aring 	if (uaddr->family != AF_IEEE802154)
20971e36b1bSAlexander Aring 		return -EINVAL;
21071e36b1bSAlexander Aring 
21171e36b1bSAlexander Aring 	lock_sock(sk);
21271e36b1bSAlexander Aring 
21371e36b1bSAlexander Aring 	ieee802154_addr_from_sa(&addr, &uaddr->addr);
21471e36b1bSAlexander Aring 	dev = ieee802154_get_dev(sock_net(sk), &addr);
21571e36b1bSAlexander Aring 	if (!dev) {
21671e36b1bSAlexander Aring 		err = -ENODEV;
21771e36b1bSAlexander Aring 		goto out;
21871e36b1bSAlexander Aring 	}
21971e36b1bSAlexander Aring 
22071e36b1bSAlexander Aring 	sk->sk_bound_dev_if = dev->ifindex;
22171e36b1bSAlexander Aring 	sk_dst_reset(sk);
22271e36b1bSAlexander Aring 
22371e36b1bSAlexander Aring 	dev_put(dev);
22471e36b1bSAlexander Aring out:
22571e36b1bSAlexander Aring 	release_sock(sk);
22671e36b1bSAlexander Aring 
22771e36b1bSAlexander Aring 	return err;
22871e36b1bSAlexander Aring }
22971e36b1bSAlexander Aring 
raw_connect(struct sock * sk,struct sockaddr * uaddr,int addr_len)23071e36b1bSAlexander Aring static int raw_connect(struct sock *sk, struct sockaddr *uaddr,
23171e36b1bSAlexander Aring 		       int addr_len)
23271e36b1bSAlexander Aring {
23371e36b1bSAlexander Aring 	return -ENOTSUPP;
23471e36b1bSAlexander Aring }
23571e36b1bSAlexander Aring 
raw_disconnect(struct sock * sk,int flags)23671e36b1bSAlexander Aring static int raw_disconnect(struct sock *sk, int flags)
23771e36b1bSAlexander Aring {
23871e36b1bSAlexander Aring 	return 0;
23971e36b1bSAlexander Aring }
24071e36b1bSAlexander Aring 
raw_sendmsg(struct sock * sk,struct msghdr * msg,size_t size)2411b784140SYing Xue static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
24271e36b1bSAlexander Aring {
24371e36b1bSAlexander Aring 	struct net_device *dev;
24471e36b1bSAlexander Aring 	unsigned int mtu;
24571e36b1bSAlexander Aring 	struct sk_buff *skb;
24671e36b1bSAlexander Aring 	int hlen, tlen;
24771e36b1bSAlexander Aring 	int err;
24871e36b1bSAlexander Aring 
24971e36b1bSAlexander Aring 	if (msg->msg_flags & MSG_OOB) {
25071e36b1bSAlexander Aring 		pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags);
25171e36b1bSAlexander Aring 		return -EOPNOTSUPP;
25271e36b1bSAlexander Aring 	}
25371e36b1bSAlexander Aring 
25471e36b1bSAlexander Aring 	lock_sock(sk);
25571e36b1bSAlexander Aring 	if (!sk->sk_bound_dev_if)
25671e36b1bSAlexander Aring 		dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154);
25771e36b1bSAlexander Aring 	else
25871e36b1bSAlexander Aring 		dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if);
25971e36b1bSAlexander Aring 	release_sock(sk);
26071e36b1bSAlexander Aring 
26171e36b1bSAlexander Aring 	if (!dev) {
26271e36b1bSAlexander Aring 		pr_debug("no dev\n");
26371e36b1bSAlexander Aring 		err = -ENXIO;
26471e36b1bSAlexander Aring 		goto out;
26571e36b1bSAlexander Aring 	}
26671e36b1bSAlexander Aring 
267b40988c4SAlexander Aring 	mtu = IEEE802154_MTU;
26871e36b1bSAlexander Aring 	pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
26971e36b1bSAlexander Aring 
27071e36b1bSAlexander Aring 	if (size > mtu) {
2715b5e0928SAlexey Dobriyan 		pr_debug("size = %zu, mtu = %u\n", size, mtu);
272c032705eSLennert Buytenhek 		err = -EMSGSIZE;
27371e36b1bSAlexander Aring 		goto out_dev;
27471e36b1bSAlexander Aring 	}
275b12e924aSTetsuo Handa 	if (!size) {
276b12e924aSTetsuo Handa 		err = 0;
277b12e924aSTetsuo Handa 		goto out_dev;
278b12e924aSTetsuo Handa 	}
27971e36b1bSAlexander Aring 
28071e36b1bSAlexander Aring 	hlen = LL_RESERVED_SPACE(dev);
28171e36b1bSAlexander Aring 	tlen = dev->needed_tailroom;
28271e36b1bSAlexander Aring 	skb = sock_alloc_send_skb(sk, hlen + tlen + size,
28371e36b1bSAlexander Aring 				  msg->msg_flags & MSG_DONTWAIT, &err);
28471e36b1bSAlexander Aring 	if (!skb)
28571e36b1bSAlexander Aring 		goto out_dev;
28671e36b1bSAlexander Aring 
28771e36b1bSAlexander Aring 	skb_reserve(skb, hlen);
28871e36b1bSAlexander Aring 
28971e36b1bSAlexander Aring 	skb_reset_mac_header(skb);
29071e36b1bSAlexander Aring 	skb_reset_network_header(skb);
29171e36b1bSAlexander Aring 
29271e36b1bSAlexander Aring 	err = memcpy_from_msg(skb_put(skb, size), msg, size);
29371e36b1bSAlexander Aring 	if (err < 0)
29471e36b1bSAlexander Aring 		goto out_skb;
29571e36b1bSAlexander Aring 
29671e36b1bSAlexander Aring 	skb->dev = dev;
29771e36b1bSAlexander Aring 	skb->protocol = htons(ETH_P_IEEE802154);
29871e36b1bSAlexander Aring 
29971e36b1bSAlexander Aring 	err = dev_queue_xmit(skb);
30071e36b1bSAlexander Aring 	if (err > 0)
30171e36b1bSAlexander Aring 		err = net_xmit_errno(err);
30271e36b1bSAlexander Aring 
303a611c58bSLin Zhang 	dev_put(dev);
304a611c58bSLin Zhang 
30571e36b1bSAlexander Aring 	return err ?: size;
30671e36b1bSAlexander Aring 
30771e36b1bSAlexander Aring out_skb:
30871e36b1bSAlexander Aring 	kfree_skb(skb);
30971e36b1bSAlexander Aring out_dev:
31071e36b1bSAlexander Aring 	dev_put(dev);
31171e36b1bSAlexander Aring out:
31271e36b1bSAlexander Aring 	return err;
31371e36b1bSAlexander Aring }
31471e36b1bSAlexander Aring 
raw_recvmsg(struct sock * sk,struct msghdr * msg,size_t len,int flags,int * addr_len)3151b784140SYing Xue static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
316ec095263SOliver Hartkopp 		       int flags, int *addr_len)
31771e36b1bSAlexander Aring {
31871e36b1bSAlexander Aring 	size_t copied = 0;
31971e36b1bSAlexander Aring 	int err = -EOPNOTSUPP;
32071e36b1bSAlexander Aring 	struct sk_buff *skb;
32171e36b1bSAlexander Aring 
322f4b41f06SOliver Hartkopp 	skb = skb_recv_datagram(sk, flags, &err);
32371e36b1bSAlexander Aring 	if (!skb)
32471e36b1bSAlexander Aring 		goto out;
32571e36b1bSAlexander Aring 
32671e36b1bSAlexander Aring 	copied = skb->len;
32771e36b1bSAlexander Aring 	if (len < copied) {
32871e36b1bSAlexander Aring 		msg->msg_flags |= MSG_TRUNC;
32971e36b1bSAlexander Aring 		copied = len;
33071e36b1bSAlexander Aring 	}
33171e36b1bSAlexander Aring 
33271e36b1bSAlexander Aring 	err = skb_copy_datagram_msg(skb, 0, msg, copied);
33371e36b1bSAlexander Aring 	if (err)
33471e36b1bSAlexander Aring 		goto done;
33571e36b1bSAlexander Aring 
3366fd1d51cSErin MacNeil 	sock_recv_cmsgs(msg, sk, skb);
33771e36b1bSAlexander Aring 
33871e36b1bSAlexander Aring 	if (flags & MSG_TRUNC)
33971e36b1bSAlexander Aring 		copied = skb->len;
34071e36b1bSAlexander Aring done:
34171e36b1bSAlexander Aring 	skb_free_datagram(sk, skb);
34271e36b1bSAlexander Aring out:
34371e36b1bSAlexander Aring 	if (err)
34471e36b1bSAlexander Aring 		return err;
34571e36b1bSAlexander Aring 	return copied;
34671e36b1bSAlexander Aring }
34771e36b1bSAlexander Aring 
raw_rcv_skb(struct sock * sk,struct sk_buff * skb)34871e36b1bSAlexander Aring static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb)
34971e36b1bSAlexander Aring {
35071e36b1bSAlexander Aring 	skb = skb_share_check(skb, GFP_ATOMIC);
35171e36b1bSAlexander Aring 	if (!skb)
35271e36b1bSAlexander Aring 		return NET_RX_DROP;
35371e36b1bSAlexander Aring 
35471e36b1bSAlexander Aring 	if (sock_queue_rcv_skb(sk, skb) < 0) {
35571e36b1bSAlexander Aring 		kfree_skb(skb);
35671e36b1bSAlexander Aring 		return NET_RX_DROP;
35771e36b1bSAlexander Aring 	}
35871e36b1bSAlexander Aring 
35971e36b1bSAlexander Aring 	return NET_RX_SUCCESS;
36071e36b1bSAlexander Aring }
36171e36b1bSAlexander Aring 
ieee802154_raw_deliver(struct net_device * dev,struct sk_buff * skb)36271e36b1bSAlexander Aring static void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb)
36371e36b1bSAlexander Aring {
36471e36b1bSAlexander Aring 	struct sock *sk;
36571e36b1bSAlexander Aring 
36671e36b1bSAlexander Aring 	read_lock(&raw_lock);
36771e36b1bSAlexander Aring 	sk_for_each(sk, &raw_head) {
36871e36b1bSAlexander Aring 		bh_lock_sock(sk);
36971e36b1bSAlexander Aring 		if (!sk->sk_bound_dev_if ||
37071e36b1bSAlexander Aring 		    sk->sk_bound_dev_if == dev->ifindex) {
37171e36b1bSAlexander Aring 			struct sk_buff *clone;
37271e36b1bSAlexander Aring 
37371e36b1bSAlexander Aring 			clone = skb_clone(skb, GFP_ATOMIC);
37471e36b1bSAlexander Aring 			if (clone)
37571e36b1bSAlexander Aring 				raw_rcv_skb(sk, clone);
37671e36b1bSAlexander Aring 		}
37771e36b1bSAlexander Aring 		bh_unlock_sock(sk);
37871e36b1bSAlexander Aring 	}
37971e36b1bSAlexander Aring 	read_unlock(&raw_lock);
38071e36b1bSAlexander Aring }
38171e36b1bSAlexander Aring 
raw_getsockopt(struct sock * sk,int level,int optname,char __user * optval,int __user * optlen)38271e36b1bSAlexander Aring static int raw_getsockopt(struct sock *sk, int level, int optname,
38371e36b1bSAlexander Aring 			  char __user *optval, int __user *optlen)
38471e36b1bSAlexander Aring {
38571e36b1bSAlexander Aring 	return -EOPNOTSUPP;
38671e36b1bSAlexander Aring }
38771e36b1bSAlexander Aring 
raw_setsockopt(struct sock * sk,int level,int optname,sockptr_t optval,unsigned int optlen)38871e36b1bSAlexander Aring static int raw_setsockopt(struct sock *sk, int level, int optname,
389a7b75c5aSChristoph Hellwig 			  sockptr_t optval, unsigned int optlen)
39071e36b1bSAlexander Aring {
39171e36b1bSAlexander Aring 	return -EOPNOTSUPP;
39271e36b1bSAlexander Aring }
39371e36b1bSAlexander Aring 
39471e36b1bSAlexander Aring static struct proto ieee802154_raw_prot = {
39571e36b1bSAlexander Aring 	.name		= "IEEE-802.15.4-RAW",
39671e36b1bSAlexander Aring 	.owner		= THIS_MODULE,
39771e36b1bSAlexander Aring 	.obj_size	= sizeof(struct sock),
39871e36b1bSAlexander Aring 	.close		= raw_close,
39971e36b1bSAlexander Aring 	.bind		= raw_bind,
40071e36b1bSAlexander Aring 	.sendmsg	= raw_sendmsg,
40171e36b1bSAlexander Aring 	.recvmsg	= raw_recvmsg,
40271e36b1bSAlexander Aring 	.hash		= raw_hash,
40371e36b1bSAlexander Aring 	.unhash		= raw_unhash,
40471e36b1bSAlexander Aring 	.connect	= raw_connect,
40571e36b1bSAlexander Aring 	.disconnect	= raw_disconnect,
40671e36b1bSAlexander Aring 	.getsockopt	= raw_getsockopt,
40771e36b1bSAlexander Aring 	.setsockopt	= raw_setsockopt,
40871e36b1bSAlexander Aring };
40971e36b1bSAlexander Aring 
41071e36b1bSAlexander Aring static const struct proto_ops ieee802154_raw_ops = {
41171e36b1bSAlexander Aring 	.family		   = PF_IEEE802154,
41271e36b1bSAlexander Aring 	.owner		   = THIS_MODULE,
41371e36b1bSAlexander Aring 	.release	   = ieee802154_sock_release,
41471e36b1bSAlexander Aring 	.bind		   = ieee802154_sock_bind,
41571e36b1bSAlexander Aring 	.connect	   = ieee802154_sock_connect,
41671e36b1bSAlexander Aring 	.socketpair	   = sock_no_socketpair,
41771e36b1bSAlexander Aring 	.accept		   = sock_no_accept,
41871e36b1bSAlexander Aring 	.getname	   = sock_no_getname,
419a11e1d43SLinus Torvalds 	.poll		   = datagram_poll,
42071e36b1bSAlexander Aring 	.ioctl		   = ieee802154_sock_ioctl,
421c7cbdbf2SArnd Bergmann 	.gettstamp	   = sock_gettstamp,
42271e36b1bSAlexander Aring 	.listen		   = sock_no_listen,
42371e36b1bSAlexander Aring 	.shutdown	   = sock_no_shutdown,
42471e36b1bSAlexander Aring 	.setsockopt	   = sock_common_setsockopt,
42571e36b1bSAlexander Aring 	.getsockopt	   = sock_common_getsockopt,
42671e36b1bSAlexander Aring 	.sendmsg	   = ieee802154_sock_sendmsg,
42771e36b1bSAlexander Aring 	.recvmsg	   = sock_common_recvmsg,
42871e36b1bSAlexander Aring 	.mmap		   = sock_no_mmap,
42971e36b1bSAlexander Aring };
43071e36b1bSAlexander Aring 
43171e36b1bSAlexander Aring /* DGRAM Sockets (802.15.4 dataframes) */
43271e36b1bSAlexander Aring static HLIST_HEAD(dgram_head);
43371e36b1bSAlexander Aring static DEFINE_RWLOCK(dgram_lock);
43471e36b1bSAlexander Aring 
43571e36b1bSAlexander Aring struct dgram_sock {
43671e36b1bSAlexander Aring 	struct sock sk;
43771e36b1bSAlexander Aring 
43871e36b1bSAlexander Aring 	struct ieee802154_addr src_addr;
43971e36b1bSAlexander Aring 	struct ieee802154_addr dst_addr;
44071e36b1bSAlexander Aring 
44171e36b1bSAlexander Aring 	unsigned int bound:1;
44271e36b1bSAlexander Aring 	unsigned int connected:1;
44371e36b1bSAlexander Aring 	unsigned int want_ack:1;
444811e299fSRomuald CARI 	unsigned int want_lqi:1;
44571e36b1bSAlexander Aring 	unsigned int secen:1;
44671e36b1bSAlexander Aring 	unsigned int secen_override:1;
44771e36b1bSAlexander Aring 	unsigned int seclevel:3;
44871e36b1bSAlexander Aring 	unsigned int seclevel_override:1;
44971e36b1bSAlexander Aring };
45071e36b1bSAlexander Aring 
dgram_sk(const struct sock * sk)45171e36b1bSAlexander Aring static inline struct dgram_sock *dgram_sk(const struct sock *sk)
45271e36b1bSAlexander Aring {
45371e36b1bSAlexander Aring 	return container_of(sk, struct dgram_sock, sk);
45471e36b1bSAlexander Aring }
45571e36b1bSAlexander Aring 
dgram_hash(struct sock * sk)456086c653fSCraig Gallek static int dgram_hash(struct sock *sk)
45771e36b1bSAlexander Aring {
45871e36b1bSAlexander Aring 	write_lock_bh(&dgram_lock);
45971e36b1bSAlexander Aring 	sk_add_node(sk, &dgram_head);
46071e36b1bSAlexander Aring 	write_unlock_bh(&dgram_lock);
461b3cb764aSEric Dumazet 	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
462086c653fSCraig Gallek 
463086c653fSCraig Gallek 	return 0;
46471e36b1bSAlexander Aring }
46571e36b1bSAlexander Aring 
dgram_unhash(struct sock * sk)46671e36b1bSAlexander Aring static void dgram_unhash(struct sock *sk)
46771e36b1bSAlexander Aring {
46871e36b1bSAlexander Aring 	write_lock_bh(&dgram_lock);
46971e36b1bSAlexander Aring 	if (sk_del_node_init(sk))
47071e36b1bSAlexander Aring 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
47171e36b1bSAlexander Aring 	write_unlock_bh(&dgram_lock);
47271e36b1bSAlexander Aring }
47371e36b1bSAlexander Aring 
dgram_init(struct sock * sk)47471e36b1bSAlexander Aring static int dgram_init(struct sock *sk)
47571e36b1bSAlexander Aring {
47671e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
47771e36b1bSAlexander Aring 
47871e36b1bSAlexander Aring 	ro->want_ack = 1;
479811e299fSRomuald CARI 	ro->want_lqi = 0;
48071e36b1bSAlexander Aring 	return 0;
48171e36b1bSAlexander Aring }
48271e36b1bSAlexander Aring 
dgram_close(struct sock * sk,long timeout)48371e36b1bSAlexander Aring static void dgram_close(struct sock *sk, long timeout)
48471e36b1bSAlexander Aring {
48571e36b1bSAlexander Aring 	sk_common_release(sk);
48671e36b1bSAlexander Aring }
48771e36b1bSAlexander Aring 
dgram_bind(struct sock * sk,struct sockaddr * uaddr,int len)48871e36b1bSAlexander Aring static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
48971e36b1bSAlexander Aring {
49071e36b1bSAlexander Aring 	struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
49171e36b1bSAlexander Aring 	struct ieee802154_addr haddr;
49271e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
49371e36b1bSAlexander Aring 	int err = -EINVAL;
49471e36b1bSAlexander Aring 	struct net_device *dev;
49571e36b1bSAlexander Aring 
49671e36b1bSAlexander Aring 	lock_sock(sk);
49771e36b1bSAlexander Aring 
49871e36b1bSAlexander Aring 	ro->bound = 0;
49971e36b1bSAlexander Aring 
50094160108SHaimin Zhang 	err = ieee802154_sockaddr_check_size(addr, len);
50194160108SHaimin Zhang 	if (err < 0)
50271e36b1bSAlexander Aring 		goto out;
50371e36b1bSAlexander Aring 
504444d8ad4SWei Yongjun 	if (addr->family != AF_IEEE802154) {
505444d8ad4SWei Yongjun 		err = -EINVAL;
50671e36b1bSAlexander Aring 		goto out;
507444d8ad4SWei Yongjun 	}
50871e36b1bSAlexander Aring 
50971e36b1bSAlexander Aring 	ieee802154_addr_from_sa(&haddr, &addr->addr);
51071e36b1bSAlexander Aring 	dev = ieee802154_get_dev(sock_net(sk), &haddr);
51171e36b1bSAlexander Aring 	if (!dev) {
51271e36b1bSAlexander Aring 		err = -ENODEV;
51371e36b1bSAlexander Aring 		goto out;
51471e36b1bSAlexander Aring 	}
51571e36b1bSAlexander Aring 
51671e36b1bSAlexander Aring 	if (dev->type != ARPHRD_IEEE802154) {
51771e36b1bSAlexander Aring 		err = -ENODEV;
51871e36b1bSAlexander Aring 		goto out_put;
51971e36b1bSAlexander Aring 	}
52071e36b1bSAlexander Aring 
52171e36b1bSAlexander Aring 	ro->src_addr = haddr;
52271e36b1bSAlexander Aring 
52371e36b1bSAlexander Aring 	ro->bound = 1;
52471e36b1bSAlexander Aring 	err = 0;
52571e36b1bSAlexander Aring out_put:
52671e36b1bSAlexander Aring 	dev_put(dev);
52771e36b1bSAlexander Aring out:
52871e36b1bSAlexander Aring 	release_sock(sk);
52971e36b1bSAlexander Aring 
53071e36b1bSAlexander Aring 	return err;
53171e36b1bSAlexander Aring }
53271e36b1bSAlexander Aring 
dgram_ioctl(struct sock * sk,int cmd,int * karg)533*e1d001faSBreno Leitao static int dgram_ioctl(struct sock *sk, int cmd, int *karg)
53471e36b1bSAlexander Aring {
53571e36b1bSAlexander Aring 	switch (cmd) {
53671e36b1bSAlexander Aring 	case SIOCOUTQ:
53771e36b1bSAlexander Aring 	{
538*e1d001faSBreno Leitao 		*karg = sk_wmem_alloc_get(sk);
53971e36b1bSAlexander Aring 
540*e1d001faSBreno Leitao 		return 0;
54171e36b1bSAlexander Aring 	}
54271e36b1bSAlexander Aring 
54371e36b1bSAlexander Aring 	case SIOCINQ:
54471e36b1bSAlexander Aring 	{
54571e36b1bSAlexander Aring 		struct sk_buff *skb;
54671e36b1bSAlexander Aring 
547*e1d001faSBreno Leitao 		*karg = 0;
54871e36b1bSAlexander Aring 		spin_lock_bh(&sk->sk_receive_queue.lock);
54971e36b1bSAlexander Aring 		skb = skb_peek(&sk->sk_receive_queue);
55071e36b1bSAlexander Aring 		if (skb) {
55171e36b1bSAlexander Aring 			/* We will only return the amount
55271e36b1bSAlexander Aring 			 * of this packet since that is all
55371e36b1bSAlexander Aring 			 * that will be read.
55471e36b1bSAlexander Aring 			 */
555*e1d001faSBreno Leitao 			*karg = skb->len - ieee802154_hdr_length(skb);
55671e36b1bSAlexander Aring 		}
55771e36b1bSAlexander Aring 		spin_unlock_bh(&sk->sk_receive_queue.lock);
558*e1d001faSBreno Leitao 		return 0;
55971e36b1bSAlexander Aring 	}
56071e36b1bSAlexander Aring 	}
56171e36b1bSAlexander Aring 
56271e36b1bSAlexander Aring 	return -ENOIOCTLCMD;
56371e36b1bSAlexander Aring }
56471e36b1bSAlexander Aring 
56571e36b1bSAlexander Aring /* FIXME: autobind */
dgram_connect(struct sock * sk,struct sockaddr * uaddr,int len)56671e36b1bSAlexander Aring static int dgram_connect(struct sock *sk, struct sockaddr *uaddr,
56771e36b1bSAlexander Aring 			 int len)
56871e36b1bSAlexander Aring {
56971e36b1bSAlexander Aring 	struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
57071e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
57171e36b1bSAlexander Aring 	int err = 0;
57271e36b1bSAlexander Aring 
57394160108SHaimin Zhang 	err = ieee802154_sockaddr_check_size(addr, len);
57494160108SHaimin Zhang 	if (err < 0)
57594160108SHaimin Zhang 		return err;
57671e36b1bSAlexander Aring 
57771e36b1bSAlexander Aring 	if (addr->family != AF_IEEE802154)
57871e36b1bSAlexander Aring 		return -EINVAL;
57971e36b1bSAlexander Aring 
58071e36b1bSAlexander Aring 	lock_sock(sk);
58171e36b1bSAlexander Aring 
58271e36b1bSAlexander Aring 	if (!ro->bound) {
58371e36b1bSAlexander Aring 		err = -ENETUNREACH;
58471e36b1bSAlexander Aring 		goto out;
58571e36b1bSAlexander Aring 	}
58671e36b1bSAlexander Aring 
58771e36b1bSAlexander Aring 	ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr);
58871e36b1bSAlexander Aring 	ro->connected = 1;
58971e36b1bSAlexander Aring 
59071e36b1bSAlexander Aring out:
59171e36b1bSAlexander Aring 	release_sock(sk);
59271e36b1bSAlexander Aring 	return err;
59371e36b1bSAlexander Aring }
59471e36b1bSAlexander Aring 
dgram_disconnect(struct sock * sk,int flags)59571e36b1bSAlexander Aring static int dgram_disconnect(struct sock *sk, int flags)
59671e36b1bSAlexander Aring {
59771e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
59871e36b1bSAlexander Aring 
59971e36b1bSAlexander Aring 	lock_sock(sk);
60071e36b1bSAlexander Aring 	ro->connected = 0;
60171e36b1bSAlexander Aring 	release_sock(sk);
60271e36b1bSAlexander Aring 
60371e36b1bSAlexander Aring 	return 0;
60471e36b1bSAlexander Aring }
60571e36b1bSAlexander Aring 
dgram_sendmsg(struct sock * sk,struct msghdr * msg,size_t size)6061b784140SYing Xue static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
60771e36b1bSAlexander Aring {
60871e36b1bSAlexander Aring 	struct net_device *dev;
60971e36b1bSAlexander Aring 	unsigned int mtu;
61071e36b1bSAlexander Aring 	struct sk_buff *skb;
61171e36b1bSAlexander Aring 	struct ieee802154_mac_cb *cb;
61271e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
61371e36b1bSAlexander Aring 	struct ieee802154_addr dst_addr;
61494160108SHaimin Zhang 	DECLARE_SOCKADDR(struct sockaddr_ieee802154*, daddr, msg->msg_name);
61571e36b1bSAlexander Aring 	int hlen, tlen;
61671e36b1bSAlexander Aring 	int err;
61771e36b1bSAlexander Aring 
61871e36b1bSAlexander Aring 	if (msg->msg_flags & MSG_OOB) {
61971e36b1bSAlexander Aring 		pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags);
62071e36b1bSAlexander Aring 		return -EOPNOTSUPP;
62171e36b1bSAlexander Aring 	}
62271e36b1bSAlexander Aring 
62394160108SHaimin Zhang 	if (msg->msg_name) {
62494160108SHaimin Zhang 		if (ro->connected)
62571e36b1bSAlexander Aring 			return -EISCONN;
62694160108SHaimin Zhang 		if (msg->msg_namelen < IEEE802154_MIN_NAMELEN)
62794160108SHaimin Zhang 			return -EINVAL;
62894160108SHaimin Zhang 		err = ieee802154_sockaddr_check_size(daddr, msg->msg_namelen);
62994160108SHaimin Zhang 		if (err < 0)
63094160108SHaimin Zhang 			return err;
63194160108SHaimin Zhang 		ieee802154_addr_from_sa(&dst_addr, &daddr->addr);
63294160108SHaimin Zhang 	} else {
63394160108SHaimin Zhang 		if (!ro->connected)
63494160108SHaimin Zhang 			return -EDESTADDRREQ;
63594160108SHaimin Zhang 		dst_addr = ro->dst_addr;
63694160108SHaimin Zhang 	}
63771e36b1bSAlexander Aring 
63871e36b1bSAlexander Aring 	if (!ro->bound)
63971e36b1bSAlexander Aring 		dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154);
64071e36b1bSAlexander Aring 	else
64171e36b1bSAlexander Aring 		dev = ieee802154_get_dev(sock_net(sk), &ro->src_addr);
64271e36b1bSAlexander Aring 
64371e36b1bSAlexander Aring 	if (!dev) {
64471e36b1bSAlexander Aring 		pr_debug("no dev\n");
64571e36b1bSAlexander Aring 		err = -ENXIO;
64671e36b1bSAlexander Aring 		goto out;
64771e36b1bSAlexander Aring 	}
648b40988c4SAlexander Aring 	mtu = IEEE802154_MTU;
64971e36b1bSAlexander Aring 	pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
65071e36b1bSAlexander Aring 
65171e36b1bSAlexander Aring 	if (size > mtu) {
6525b5e0928SAlexey Dobriyan 		pr_debug("size = %zu, mtu = %u\n", size, mtu);
65371e36b1bSAlexander Aring 		err = -EMSGSIZE;
65471e36b1bSAlexander Aring 		goto out_dev;
65571e36b1bSAlexander Aring 	}
65671e36b1bSAlexander Aring 
65771e36b1bSAlexander Aring 	hlen = LL_RESERVED_SPACE(dev);
65871e36b1bSAlexander Aring 	tlen = dev->needed_tailroom;
65971e36b1bSAlexander Aring 	skb = sock_alloc_send_skb(sk, hlen + tlen + size,
66071e36b1bSAlexander Aring 				  msg->msg_flags & MSG_DONTWAIT,
66171e36b1bSAlexander Aring 				  &err);
66271e36b1bSAlexander Aring 	if (!skb)
66371e36b1bSAlexander Aring 		goto out_dev;
66471e36b1bSAlexander Aring 
66571e36b1bSAlexander Aring 	skb_reserve(skb, hlen);
66671e36b1bSAlexander Aring 
66771e36b1bSAlexander Aring 	skb_reset_network_header(skb);
66871e36b1bSAlexander Aring 
66971e36b1bSAlexander Aring 	cb = mac_cb_init(skb);
67071e36b1bSAlexander Aring 	cb->type = IEEE802154_FC_TYPE_DATA;
67171e36b1bSAlexander Aring 	cb->ackreq = ro->want_ack;
67271e36b1bSAlexander Aring 	cb->secen = ro->secen;
67371e36b1bSAlexander Aring 	cb->secen_override = ro->secen_override;
67471e36b1bSAlexander Aring 	cb->seclevel = ro->seclevel;
67571e36b1bSAlexander Aring 	cb->seclevel_override = ro->seclevel_override;
67671e36b1bSAlexander Aring 
677838b83d6SAlexander Aring 	err = wpan_dev_hard_header(skb, dev, &dst_addr,
67871e36b1bSAlexander Aring 				   ro->bound ? &ro->src_addr : NULL, size);
67971e36b1bSAlexander Aring 	if (err < 0)
68071e36b1bSAlexander Aring 		goto out_skb;
68171e36b1bSAlexander Aring 
68271e36b1bSAlexander Aring 	err = memcpy_from_msg(skb_put(skb, size), msg, size);
68371e36b1bSAlexander Aring 	if (err < 0)
68471e36b1bSAlexander Aring 		goto out_skb;
68571e36b1bSAlexander Aring 
68671e36b1bSAlexander Aring 	skb->dev = dev;
68771e36b1bSAlexander Aring 	skb->protocol = htons(ETH_P_IEEE802154);
68871e36b1bSAlexander Aring 
68971e36b1bSAlexander Aring 	err = dev_queue_xmit(skb);
69071e36b1bSAlexander Aring 	if (err > 0)
69171e36b1bSAlexander Aring 		err = net_xmit_errno(err);
69271e36b1bSAlexander Aring 
693a611c58bSLin Zhang 	dev_put(dev);
694a611c58bSLin Zhang 
69571e36b1bSAlexander Aring 	return err ?: size;
69671e36b1bSAlexander Aring 
69771e36b1bSAlexander Aring out_skb:
69871e36b1bSAlexander Aring 	kfree_skb(skb);
69971e36b1bSAlexander Aring out_dev:
70071e36b1bSAlexander Aring 	dev_put(dev);
70171e36b1bSAlexander Aring out:
70271e36b1bSAlexander Aring 	return err;
70371e36b1bSAlexander Aring }
70471e36b1bSAlexander Aring 
dgram_recvmsg(struct sock * sk,struct msghdr * msg,size_t len,int flags,int * addr_len)7051b784140SYing Xue static int dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
706ec095263SOliver Hartkopp 			 int flags, int *addr_len)
70771e36b1bSAlexander Aring {
70871e36b1bSAlexander Aring 	size_t copied = 0;
70971e36b1bSAlexander Aring 	int err = -EOPNOTSUPP;
71071e36b1bSAlexander Aring 	struct sk_buff *skb;
711811e299fSRomuald CARI 	struct dgram_sock *ro = dgram_sk(sk);
71271e36b1bSAlexander Aring 	DECLARE_SOCKADDR(struct sockaddr_ieee802154 *, saddr, msg->msg_name);
71371e36b1bSAlexander Aring 
714f4b41f06SOliver Hartkopp 	skb = skb_recv_datagram(sk, flags, &err);
71571e36b1bSAlexander Aring 	if (!skb)
71671e36b1bSAlexander Aring 		goto out;
71771e36b1bSAlexander Aring 
71871e36b1bSAlexander Aring 	copied = skb->len;
71971e36b1bSAlexander Aring 	if (len < copied) {
72071e36b1bSAlexander Aring 		msg->msg_flags |= MSG_TRUNC;
72171e36b1bSAlexander Aring 		copied = len;
72271e36b1bSAlexander Aring 	}
72371e36b1bSAlexander Aring 
72471e36b1bSAlexander Aring 	/* FIXME: skip headers if necessary ?! */
72571e36b1bSAlexander Aring 	err = skb_copy_datagram_msg(skb, 0, msg, copied);
72671e36b1bSAlexander Aring 	if (err)
72771e36b1bSAlexander Aring 		goto done;
72871e36b1bSAlexander Aring 
7296fd1d51cSErin MacNeil 	sock_recv_cmsgs(msg, sk, skb);
73071e36b1bSAlexander Aring 
73171e36b1bSAlexander Aring 	if (saddr) {
7328a70cefaSLennert Buytenhek 		/* Clear the implicit padding in struct sockaddr_ieee802154
7338a70cefaSLennert Buytenhek 		 * (16 bits between 'family' and 'addr') and in struct
7348a70cefaSLennert Buytenhek 		 * ieee802154_addr_sa (16 bits at the end of the structure).
7358a70cefaSLennert Buytenhek 		 */
7368a70cefaSLennert Buytenhek 		memset(saddr, 0, sizeof(*saddr));
7378a70cefaSLennert Buytenhek 
73871e36b1bSAlexander Aring 		saddr->family = AF_IEEE802154;
73971e36b1bSAlexander Aring 		ieee802154_addr_to_sa(&saddr->addr, &mac_cb(skb)->source);
74071e36b1bSAlexander Aring 		*addr_len = sizeof(*saddr);
74171e36b1bSAlexander Aring 	}
74271e36b1bSAlexander Aring 
743811e299fSRomuald CARI 	if (ro->want_lqi) {
744811e299fSRomuald CARI 		err = put_cmsg(msg, SOL_IEEE802154, WPAN_WANTLQI,
745811e299fSRomuald CARI 			       sizeof(uint8_t), &(mac_cb(skb)->lqi));
746811e299fSRomuald CARI 		if (err)
747811e299fSRomuald CARI 			goto done;
748811e299fSRomuald CARI 	}
749811e299fSRomuald CARI 
75071e36b1bSAlexander Aring 	if (flags & MSG_TRUNC)
75171e36b1bSAlexander Aring 		copied = skb->len;
75271e36b1bSAlexander Aring done:
75371e36b1bSAlexander Aring 	skb_free_datagram(sk, skb);
75471e36b1bSAlexander Aring out:
75571e36b1bSAlexander Aring 	if (err)
75671e36b1bSAlexander Aring 		return err;
75771e36b1bSAlexander Aring 	return copied;
75871e36b1bSAlexander Aring }
75971e36b1bSAlexander Aring 
dgram_rcv_skb(struct sock * sk,struct sk_buff * skb)76071e36b1bSAlexander Aring static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb)
76171e36b1bSAlexander Aring {
76271e36b1bSAlexander Aring 	skb = skb_share_check(skb, GFP_ATOMIC);
76371e36b1bSAlexander Aring 	if (!skb)
76471e36b1bSAlexander Aring 		return NET_RX_DROP;
76571e36b1bSAlexander Aring 
76671e36b1bSAlexander Aring 	if (sock_queue_rcv_skb(sk, skb) < 0) {
76771e36b1bSAlexander Aring 		kfree_skb(skb);
76871e36b1bSAlexander Aring 		return NET_RX_DROP;
76971e36b1bSAlexander Aring 	}
77071e36b1bSAlexander Aring 
77171e36b1bSAlexander Aring 	return NET_RX_SUCCESS;
77271e36b1bSAlexander Aring }
77371e36b1bSAlexander Aring 
77471e36b1bSAlexander Aring static inline bool
ieee802154_match_sock(__le64 hw_addr,__le16 pan_id,__le16 short_addr,struct dgram_sock * ro)77571e36b1bSAlexander Aring ieee802154_match_sock(__le64 hw_addr, __le16 pan_id, __le16 short_addr,
77671e36b1bSAlexander Aring 		      struct dgram_sock *ro)
77771e36b1bSAlexander Aring {
77871e36b1bSAlexander Aring 	if (!ro->bound)
77971e36b1bSAlexander Aring 		return true;
78071e36b1bSAlexander Aring 
78171e36b1bSAlexander Aring 	if (ro->src_addr.mode == IEEE802154_ADDR_LONG &&
78271e36b1bSAlexander Aring 	    hw_addr == ro->src_addr.extended_addr)
78371e36b1bSAlexander Aring 		return true;
78471e36b1bSAlexander Aring 
78571e36b1bSAlexander Aring 	if (ro->src_addr.mode == IEEE802154_ADDR_SHORT &&
78671e36b1bSAlexander Aring 	    pan_id == ro->src_addr.pan_id &&
78771e36b1bSAlexander Aring 	    short_addr == ro->src_addr.short_addr)
78871e36b1bSAlexander Aring 		return true;
78971e36b1bSAlexander Aring 
79071e36b1bSAlexander Aring 	return false;
79171e36b1bSAlexander Aring }
79271e36b1bSAlexander Aring 
ieee802154_dgram_deliver(struct net_device * dev,struct sk_buff * skb)79371e36b1bSAlexander Aring static int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
79471e36b1bSAlexander Aring {
79571e36b1bSAlexander Aring 	struct sock *sk, *prev = NULL;
79671e36b1bSAlexander Aring 	int ret = NET_RX_SUCCESS;
79771e36b1bSAlexander Aring 	__le16 pan_id, short_addr;
79871e36b1bSAlexander Aring 	__le64 hw_addr;
79971e36b1bSAlexander Aring 
80071e36b1bSAlexander Aring 	/* Data frame processing */
80171e36b1bSAlexander Aring 	BUG_ON(dev->type != ARPHRD_IEEE802154);
80271e36b1bSAlexander Aring 
803c947f7e1SAlexander Aring 	pan_id = dev->ieee802154_ptr->pan_id;
804c947f7e1SAlexander Aring 	short_addr = dev->ieee802154_ptr->short_addr;
805c947f7e1SAlexander Aring 	hw_addr = dev->ieee802154_ptr->extended_addr;
80671e36b1bSAlexander Aring 
80771e36b1bSAlexander Aring 	read_lock(&dgram_lock);
80871e36b1bSAlexander Aring 	sk_for_each(sk, &dgram_head) {
80971e36b1bSAlexander Aring 		if (ieee802154_match_sock(hw_addr, pan_id, short_addr,
81071e36b1bSAlexander Aring 					  dgram_sk(sk))) {
81171e36b1bSAlexander Aring 			if (prev) {
81271e36b1bSAlexander Aring 				struct sk_buff *clone;
81371e36b1bSAlexander Aring 
81471e36b1bSAlexander Aring 				clone = skb_clone(skb, GFP_ATOMIC);
81571e36b1bSAlexander Aring 				if (clone)
81671e36b1bSAlexander Aring 					dgram_rcv_skb(prev, clone);
81771e36b1bSAlexander Aring 			}
81871e36b1bSAlexander Aring 
81971e36b1bSAlexander Aring 			prev = sk;
82071e36b1bSAlexander Aring 		}
82171e36b1bSAlexander Aring 	}
82271e36b1bSAlexander Aring 
82371e36b1bSAlexander Aring 	if (prev) {
82471e36b1bSAlexander Aring 		dgram_rcv_skb(prev, skb);
82571e36b1bSAlexander Aring 	} else {
82671e36b1bSAlexander Aring 		kfree_skb(skb);
82771e36b1bSAlexander Aring 		ret = NET_RX_DROP;
82871e36b1bSAlexander Aring 	}
82971e36b1bSAlexander Aring 	read_unlock(&dgram_lock);
83071e36b1bSAlexander Aring 
83171e36b1bSAlexander Aring 	return ret;
83271e36b1bSAlexander Aring }
83371e36b1bSAlexander Aring 
dgram_getsockopt(struct sock * sk,int level,int optname,char __user * optval,int __user * optlen)83471e36b1bSAlexander Aring static int dgram_getsockopt(struct sock *sk, int level, int optname,
83571e36b1bSAlexander Aring 			    char __user *optval, int __user *optlen)
83671e36b1bSAlexander Aring {
83771e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
83871e36b1bSAlexander Aring 
83971e36b1bSAlexander Aring 	int val, len;
84071e36b1bSAlexander Aring 
84171e36b1bSAlexander Aring 	if (level != SOL_IEEE802154)
84271e36b1bSAlexander Aring 		return -EOPNOTSUPP;
84371e36b1bSAlexander Aring 
84471e36b1bSAlexander Aring 	if (get_user(len, optlen))
84571e36b1bSAlexander Aring 		return -EFAULT;
84671e36b1bSAlexander Aring 
84771e36b1bSAlexander Aring 	len = min_t(unsigned int, len, sizeof(int));
84871e36b1bSAlexander Aring 
84971e36b1bSAlexander Aring 	switch (optname) {
85071e36b1bSAlexander Aring 	case WPAN_WANTACK:
85171e36b1bSAlexander Aring 		val = ro->want_ack;
85271e36b1bSAlexander Aring 		break;
853811e299fSRomuald CARI 	case WPAN_WANTLQI:
854811e299fSRomuald CARI 		val = ro->want_lqi;
855811e299fSRomuald CARI 		break;
85671e36b1bSAlexander Aring 	case WPAN_SECURITY:
85771e36b1bSAlexander Aring 		if (!ro->secen_override)
85871e36b1bSAlexander Aring 			val = WPAN_SECURITY_DEFAULT;
85971e36b1bSAlexander Aring 		else if (ro->secen)
86071e36b1bSAlexander Aring 			val = WPAN_SECURITY_ON;
86171e36b1bSAlexander Aring 		else
86271e36b1bSAlexander Aring 			val = WPAN_SECURITY_OFF;
86371e36b1bSAlexander Aring 		break;
86471e36b1bSAlexander Aring 	case WPAN_SECURITY_LEVEL:
86571e36b1bSAlexander Aring 		if (!ro->seclevel_override)
86671e36b1bSAlexander Aring 			val = WPAN_SECURITY_LEVEL_DEFAULT;
86771e36b1bSAlexander Aring 		else
86871e36b1bSAlexander Aring 			val = ro->seclevel;
86971e36b1bSAlexander Aring 		break;
87071e36b1bSAlexander Aring 	default:
87171e36b1bSAlexander Aring 		return -ENOPROTOOPT;
87271e36b1bSAlexander Aring 	}
87371e36b1bSAlexander Aring 
87471e36b1bSAlexander Aring 	if (put_user(len, optlen))
87571e36b1bSAlexander Aring 		return -EFAULT;
87671e36b1bSAlexander Aring 	if (copy_to_user(optval, &val, len))
87771e36b1bSAlexander Aring 		return -EFAULT;
87871e36b1bSAlexander Aring 	return 0;
87971e36b1bSAlexander Aring }
88071e36b1bSAlexander Aring 
dgram_setsockopt(struct sock * sk,int level,int optname,sockptr_t optval,unsigned int optlen)88171e36b1bSAlexander Aring static int dgram_setsockopt(struct sock *sk, int level, int optname,
882a7b75c5aSChristoph Hellwig 			    sockptr_t optval, unsigned int optlen)
88371e36b1bSAlexander Aring {
88471e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
88571e36b1bSAlexander Aring 	struct net *net = sock_net(sk);
88671e36b1bSAlexander Aring 	int val;
88771e36b1bSAlexander Aring 	int err = 0;
88871e36b1bSAlexander Aring 
88971e36b1bSAlexander Aring 	if (optlen < sizeof(int))
89071e36b1bSAlexander Aring 		return -EINVAL;
89171e36b1bSAlexander Aring 
892a7b75c5aSChristoph Hellwig 	if (copy_from_sockptr(&val, optval, sizeof(int)))
89371e36b1bSAlexander Aring 		return -EFAULT;
89471e36b1bSAlexander Aring 
89571e36b1bSAlexander Aring 	lock_sock(sk);
89671e36b1bSAlexander Aring 
89771e36b1bSAlexander Aring 	switch (optname) {
89871e36b1bSAlexander Aring 	case WPAN_WANTACK:
89971e36b1bSAlexander Aring 		ro->want_ack = !!val;
90071e36b1bSAlexander Aring 		break;
901811e299fSRomuald CARI 	case WPAN_WANTLQI:
902811e299fSRomuald CARI 		ro->want_lqi = !!val;
903811e299fSRomuald CARI 		break;
90471e36b1bSAlexander Aring 	case WPAN_SECURITY:
90571e36b1bSAlexander Aring 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
90671e36b1bSAlexander Aring 		    !ns_capable(net->user_ns, CAP_NET_RAW)) {
90771e36b1bSAlexander Aring 			err = -EPERM;
90871e36b1bSAlexander Aring 			break;
90971e36b1bSAlexander Aring 		}
91071e36b1bSAlexander Aring 
91171e36b1bSAlexander Aring 		switch (val) {
91271e36b1bSAlexander Aring 		case WPAN_SECURITY_DEFAULT:
91371e36b1bSAlexander Aring 			ro->secen_override = 0;
91471e36b1bSAlexander Aring 			break;
91571e36b1bSAlexander Aring 		case WPAN_SECURITY_ON:
91671e36b1bSAlexander Aring 			ro->secen_override = 1;
91771e36b1bSAlexander Aring 			ro->secen = 1;
91871e36b1bSAlexander Aring 			break;
91971e36b1bSAlexander Aring 		case WPAN_SECURITY_OFF:
92071e36b1bSAlexander Aring 			ro->secen_override = 1;
92171e36b1bSAlexander Aring 			ro->secen = 0;
92271e36b1bSAlexander Aring 			break;
92371e36b1bSAlexander Aring 		default:
92471e36b1bSAlexander Aring 			err = -EINVAL;
92571e36b1bSAlexander Aring 			break;
92671e36b1bSAlexander Aring 		}
92771e36b1bSAlexander Aring 		break;
92871e36b1bSAlexander Aring 	case WPAN_SECURITY_LEVEL:
92971e36b1bSAlexander Aring 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
93071e36b1bSAlexander Aring 		    !ns_capable(net->user_ns, CAP_NET_RAW)) {
93171e36b1bSAlexander Aring 			err = -EPERM;
93271e36b1bSAlexander Aring 			break;
93371e36b1bSAlexander Aring 		}
93471e36b1bSAlexander Aring 
93571e36b1bSAlexander Aring 		if (val < WPAN_SECURITY_LEVEL_DEFAULT ||
93671e36b1bSAlexander Aring 		    val > IEEE802154_SCF_SECLEVEL_ENC_MIC128) {
93771e36b1bSAlexander Aring 			err = -EINVAL;
93871e36b1bSAlexander Aring 		} else if (val == WPAN_SECURITY_LEVEL_DEFAULT) {
93971e36b1bSAlexander Aring 			ro->seclevel_override = 0;
94071e36b1bSAlexander Aring 		} else {
94171e36b1bSAlexander Aring 			ro->seclevel_override = 1;
94271e36b1bSAlexander Aring 			ro->seclevel = val;
94371e36b1bSAlexander Aring 		}
94471e36b1bSAlexander Aring 		break;
94571e36b1bSAlexander Aring 	default:
94671e36b1bSAlexander Aring 		err = -ENOPROTOOPT;
94771e36b1bSAlexander Aring 		break;
94871e36b1bSAlexander Aring 	}
94971e36b1bSAlexander Aring 
95071e36b1bSAlexander Aring 	release_sock(sk);
95171e36b1bSAlexander Aring 	return err;
95271e36b1bSAlexander Aring }
95371e36b1bSAlexander Aring 
95471e36b1bSAlexander Aring static struct proto ieee802154_dgram_prot = {
95571e36b1bSAlexander Aring 	.name		= "IEEE-802.15.4-MAC",
95671e36b1bSAlexander Aring 	.owner		= THIS_MODULE,
95771e36b1bSAlexander Aring 	.obj_size	= sizeof(struct dgram_sock),
95871e36b1bSAlexander Aring 	.init		= dgram_init,
95971e36b1bSAlexander Aring 	.close		= dgram_close,
96071e36b1bSAlexander Aring 	.bind		= dgram_bind,
96171e36b1bSAlexander Aring 	.sendmsg	= dgram_sendmsg,
96271e36b1bSAlexander Aring 	.recvmsg	= dgram_recvmsg,
96371e36b1bSAlexander Aring 	.hash		= dgram_hash,
96471e36b1bSAlexander Aring 	.unhash		= dgram_unhash,
96571e36b1bSAlexander Aring 	.connect	= dgram_connect,
96671e36b1bSAlexander Aring 	.disconnect	= dgram_disconnect,
96771e36b1bSAlexander Aring 	.ioctl		= dgram_ioctl,
96871e36b1bSAlexander Aring 	.getsockopt	= dgram_getsockopt,
96971e36b1bSAlexander Aring 	.setsockopt	= dgram_setsockopt,
97071e36b1bSAlexander Aring };
97171e36b1bSAlexander Aring 
97271e36b1bSAlexander Aring static const struct proto_ops ieee802154_dgram_ops = {
97371e36b1bSAlexander Aring 	.family		   = PF_IEEE802154,
97471e36b1bSAlexander Aring 	.owner		   = THIS_MODULE,
97571e36b1bSAlexander Aring 	.release	   = ieee802154_sock_release,
97671e36b1bSAlexander Aring 	.bind		   = ieee802154_sock_bind,
97771e36b1bSAlexander Aring 	.connect	   = ieee802154_sock_connect,
97871e36b1bSAlexander Aring 	.socketpair	   = sock_no_socketpair,
97971e36b1bSAlexander Aring 	.accept		   = sock_no_accept,
98071e36b1bSAlexander Aring 	.getname	   = sock_no_getname,
981a11e1d43SLinus Torvalds 	.poll		   = datagram_poll,
98271e36b1bSAlexander Aring 	.ioctl		   = ieee802154_sock_ioctl,
983c7cbdbf2SArnd Bergmann 	.gettstamp	   = sock_gettstamp,
98471e36b1bSAlexander Aring 	.listen		   = sock_no_listen,
98571e36b1bSAlexander Aring 	.shutdown	   = sock_no_shutdown,
98671e36b1bSAlexander Aring 	.setsockopt	   = sock_common_setsockopt,
98771e36b1bSAlexander Aring 	.getsockopt	   = sock_common_getsockopt,
98871e36b1bSAlexander Aring 	.sendmsg	   = ieee802154_sock_sendmsg,
98971e36b1bSAlexander Aring 	.recvmsg	   = sock_common_recvmsg,
99071e36b1bSAlexander Aring 	.mmap		   = sock_no_mmap,
99171e36b1bSAlexander Aring };
99271e36b1bSAlexander Aring 
ieee802154_sock_destruct(struct sock * sk)9931090340fSTakeshi Misawa static void ieee802154_sock_destruct(struct sock *sk)
9941090340fSTakeshi Misawa {
9951090340fSTakeshi Misawa 	skb_queue_purge(&sk->sk_receive_queue);
9961090340fSTakeshi Misawa }
9971090340fSTakeshi Misawa 
99871e36b1bSAlexander Aring /* Create a socket. Initialise the socket, blank the addresses
99971e36b1bSAlexander Aring  * set the state.
100071e36b1bSAlexander Aring  */
ieee802154_create(struct net * net,struct socket * sock,int protocol,int kern)100171e36b1bSAlexander Aring static int ieee802154_create(struct net *net, struct socket *sock,
100271e36b1bSAlexander Aring 			     int protocol, int kern)
100371e36b1bSAlexander Aring {
100471e36b1bSAlexander Aring 	struct sock *sk;
100571e36b1bSAlexander Aring 	int rc;
100671e36b1bSAlexander Aring 	struct proto *proto;
100771e36b1bSAlexander Aring 	const struct proto_ops *ops;
100871e36b1bSAlexander Aring 
100971e36b1bSAlexander Aring 	if (!net_eq(net, &init_net))
101071e36b1bSAlexander Aring 		return -EAFNOSUPPORT;
101171e36b1bSAlexander Aring 
101271e36b1bSAlexander Aring 	switch (sock->type) {
101371e36b1bSAlexander Aring 	case SOCK_RAW:
1014e69dbd46SOri Nimron 		rc = -EPERM;
1015e69dbd46SOri Nimron 		if (!capable(CAP_NET_RAW))
1016e69dbd46SOri Nimron 			goto out;
101771e36b1bSAlexander Aring 		proto = &ieee802154_raw_prot;
101871e36b1bSAlexander Aring 		ops = &ieee802154_raw_ops;
101971e36b1bSAlexander Aring 		break;
102071e36b1bSAlexander Aring 	case SOCK_DGRAM:
102171e36b1bSAlexander Aring 		proto = &ieee802154_dgram_prot;
102271e36b1bSAlexander Aring 		ops = &ieee802154_dgram_ops;
102371e36b1bSAlexander Aring 		break;
102471e36b1bSAlexander Aring 	default:
102571e36b1bSAlexander Aring 		rc = -ESOCKTNOSUPPORT;
102671e36b1bSAlexander Aring 		goto out;
102771e36b1bSAlexander Aring 	}
102871e36b1bSAlexander Aring 
102971e36b1bSAlexander Aring 	rc = -ENOMEM;
103011aa9c28SEric W. Biederman 	sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto, kern);
103171e36b1bSAlexander Aring 	if (!sk)
103271e36b1bSAlexander Aring 		goto out;
103371e36b1bSAlexander Aring 	rc = 0;
103471e36b1bSAlexander Aring 
103571e36b1bSAlexander Aring 	sock->ops = ops;
103671e36b1bSAlexander Aring 
103771e36b1bSAlexander Aring 	sock_init_data(sock, sk);
10381090340fSTakeshi Misawa 	sk->sk_destruct = ieee802154_sock_destruct;
103971e36b1bSAlexander Aring 	sk->sk_family = PF_IEEE802154;
104071e36b1bSAlexander Aring 
104171e36b1bSAlexander Aring 	/* Checksums on by default */
104271e36b1bSAlexander Aring 	sock_set_flag(sk, SOCK_ZAPPED);
104371e36b1bSAlexander Aring 
1044086c653fSCraig Gallek 	if (sk->sk_prot->hash) {
1045086c653fSCraig Gallek 		rc = sk->sk_prot->hash(sk);
1046086c653fSCraig Gallek 		if (rc) {
1047086c653fSCraig Gallek 			sk_common_release(sk);
1048086c653fSCraig Gallek 			goto out;
1049086c653fSCraig Gallek 		}
1050086c653fSCraig Gallek 	}
105171e36b1bSAlexander Aring 
105271e36b1bSAlexander Aring 	if (sk->sk_prot->init) {
105371e36b1bSAlexander Aring 		rc = sk->sk_prot->init(sk);
105471e36b1bSAlexander Aring 		if (rc)
105571e36b1bSAlexander Aring 			sk_common_release(sk);
105671e36b1bSAlexander Aring 	}
105771e36b1bSAlexander Aring out:
105871e36b1bSAlexander Aring 	return rc;
105971e36b1bSAlexander Aring }
106071e36b1bSAlexander Aring 
106171e36b1bSAlexander Aring static const struct net_proto_family ieee802154_family_ops = {
106271e36b1bSAlexander Aring 	.family		= PF_IEEE802154,
106371e36b1bSAlexander Aring 	.create		= ieee802154_create,
106471e36b1bSAlexander Aring 	.owner		= THIS_MODULE,
106571e36b1bSAlexander Aring };
106671e36b1bSAlexander Aring 
ieee802154_rcv(struct sk_buff * skb,struct net_device * dev,struct packet_type * pt,struct net_device * orig_dev)106771e36b1bSAlexander Aring static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev,
106871e36b1bSAlexander Aring 			  struct packet_type *pt, struct net_device *orig_dev)
106971e36b1bSAlexander Aring {
107071e36b1bSAlexander Aring 	if (!netif_running(dev))
107171e36b1bSAlexander Aring 		goto drop;
107271e36b1bSAlexander Aring 	pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
107371e36b1bSAlexander Aring #ifdef DEBUG
107471e36b1bSAlexander Aring 	print_hex_dump_bytes("ieee802154_rcv ",
107571e36b1bSAlexander Aring 			     DUMP_PREFIX_NONE, skb->data, skb->len);
107671e36b1bSAlexander Aring #endif
107771e36b1bSAlexander Aring 
107871e36b1bSAlexander Aring 	if (!net_eq(dev_net(dev), &init_net))
107971e36b1bSAlexander Aring 		goto drop;
108071e36b1bSAlexander Aring 
108171e36b1bSAlexander Aring 	ieee802154_raw_deliver(dev, skb);
108271e36b1bSAlexander Aring 
108371e36b1bSAlexander Aring 	if (dev->type != ARPHRD_IEEE802154)
108471e36b1bSAlexander Aring 		goto drop;
108571e36b1bSAlexander Aring 
108671e36b1bSAlexander Aring 	if (skb->pkt_type != PACKET_OTHERHOST)
108771e36b1bSAlexander Aring 		return ieee802154_dgram_deliver(dev, skb);
108871e36b1bSAlexander Aring 
108971e36b1bSAlexander Aring drop:
109071e36b1bSAlexander Aring 	kfree_skb(skb);
109171e36b1bSAlexander Aring 	return NET_RX_DROP;
109271e36b1bSAlexander Aring }
109371e36b1bSAlexander Aring 
109471e36b1bSAlexander Aring static struct packet_type ieee802154_packet_type = {
109571e36b1bSAlexander Aring 	.type = htons(ETH_P_IEEE802154),
109671e36b1bSAlexander Aring 	.func = ieee802154_rcv,
109771e36b1bSAlexander Aring };
109871e36b1bSAlexander Aring 
af_ieee802154_init(void)109971e36b1bSAlexander Aring static int __init af_ieee802154_init(void)
110071e36b1bSAlexander Aring {
1101074014abSColin Ian King 	int rc;
110271e36b1bSAlexander Aring 
110371e36b1bSAlexander Aring 	rc = proto_register(&ieee802154_raw_prot, 1);
110471e36b1bSAlexander Aring 	if (rc)
110571e36b1bSAlexander Aring 		goto out;
110671e36b1bSAlexander Aring 
110771e36b1bSAlexander Aring 	rc = proto_register(&ieee802154_dgram_prot, 1);
110871e36b1bSAlexander Aring 	if (rc)
110971e36b1bSAlexander Aring 		goto err_dgram;
111071e36b1bSAlexander Aring 
111171e36b1bSAlexander Aring 	/* Tell SOCKET that we are alive */
111271e36b1bSAlexander Aring 	rc = sock_register(&ieee802154_family_ops);
111371e36b1bSAlexander Aring 	if (rc)
111471e36b1bSAlexander Aring 		goto err_sock;
111571e36b1bSAlexander Aring 	dev_add_pack(&ieee802154_packet_type);
111671e36b1bSAlexander Aring 
111771e36b1bSAlexander Aring 	rc = 0;
111871e36b1bSAlexander Aring 	goto out;
111971e36b1bSAlexander Aring 
112071e36b1bSAlexander Aring err_sock:
112171e36b1bSAlexander Aring 	proto_unregister(&ieee802154_dgram_prot);
112271e36b1bSAlexander Aring err_dgram:
112371e36b1bSAlexander Aring 	proto_unregister(&ieee802154_raw_prot);
112471e36b1bSAlexander Aring out:
112571e36b1bSAlexander Aring 	return rc;
112671e36b1bSAlexander Aring }
112771e36b1bSAlexander Aring 
af_ieee802154_remove(void)112871e36b1bSAlexander Aring static void __exit af_ieee802154_remove(void)
112971e36b1bSAlexander Aring {
113071e36b1bSAlexander Aring 	dev_remove_pack(&ieee802154_packet_type);
113171e36b1bSAlexander Aring 	sock_unregister(PF_IEEE802154);
113271e36b1bSAlexander Aring 	proto_unregister(&ieee802154_dgram_prot);
113371e36b1bSAlexander Aring 	proto_unregister(&ieee802154_raw_prot);
113471e36b1bSAlexander Aring }
113571e36b1bSAlexander Aring 
113671e36b1bSAlexander Aring module_init(af_ieee802154_init);
113771e36b1bSAlexander Aring module_exit(af_ieee802154_remove);
113871e36b1bSAlexander Aring 
113971e36b1bSAlexander Aring MODULE_LICENSE("GPL");
114071e36b1bSAlexander Aring MODULE_ALIAS_NETPROTO(PF_IEEE802154);
1141