xref: /openbmc/linux/net/ieee802154/socket.c (revision 444d8ad4)
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*
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 
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 
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 
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 
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 
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 
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;
16571e36b1bSAlexander Aring 		return sk->sk_prot->ioctl(sk, cmd, 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 
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 
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 
19171e36b1bSAlexander Aring static void raw_close(struct sock *sk, long timeout)
19271e36b1bSAlexander Aring {
19371e36b1bSAlexander Aring 	sk_common_release(sk);
19471e36b1bSAlexander Aring }
19571e36b1bSAlexander Aring 
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 
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 
23671e36b1bSAlexander Aring static int raw_disconnect(struct sock *sk, int flags)
23771e36b1bSAlexander Aring {
23871e36b1bSAlexander Aring 	return 0;
23971e36b1bSAlexander Aring }
24071e36b1bSAlexander Aring 
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 
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 
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 
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 
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 
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 	.sendpage	   = sock_no_sendpage,
43071e36b1bSAlexander Aring };
43171e36b1bSAlexander Aring 
43271e36b1bSAlexander Aring /* DGRAM Sockets (802.15.4 dataframes) */
43371e36b1bSAlexander Aring static HLIST_HEAD(dgram_head);
43471e36b1bSAlexander Aring static DEFINE_RWLOCK(dgram_lock);
43571e36b1bSAlexander Aring 
43671e36b1bSAlexander Aring struct dgram_sock {
43771e36b1bSAlexander Aring 	struct sock sk;
43871e36b1bSAlexander Aring 
43971e36b1bSAlexander Aring 	struct ieee802154_addr src_addr;
44071e36b1bSAlexander Aring 	struct ieee802154_addr dst_addr;
44171e36b1bSAlexander Aring 
44271e36b1bSAlexander Aring 	unsigned int bound:1;
44371e36b1bSAlexander Aring 	unsigned int connected:1;
44471e36b1bSAlexander Aring 	unsigned int want_ack:1;
445811e299fSRomuald CARI 	unsigned int want_lqi:1;
44671e36b1bSAlexander Aring 	unsigned int secen:1;
44771e36b1bSAlexander Aring 	unsigned int secen_override:1;
44871e36b1bSAlexander Aring 	unsigned int seclevel:3;
44971e36b1bSAlexander Aring 	unsigned int seclevel_override:1;
45071e36b1bSAlexander Aring };
45171e36b1bSAlexander Aring 
45271e36b1bSAlexander Aring static inline struct dgram_sock *dgram_sk(const struct sock *sk)
45371e36b1bSAlexander Aring {
45471e36b1bSAlexander Aring 	return container_of(sk, struct dgram_sock, sk);
45571e36b1bSAlexander Aring }
45671e36b1bSAlexander Aring 
457086c653fSCraig Gallek static int dgram_hash(struct sock *sk)
45871e36b1bSAlexander Aring {
45971e36b1bSAlexander Aring 	write_lock_bh(&dgram_lock);
46071e36b1bSAlexander Aring 	sk_add_node(sk, &dgram_head);
46171e36b1bSAlexander Aring 	write_unlock_bh(&dgram_lock);
462b3cb764aSEric Dumazet 	sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
463086c653fSCraig Gallek 
464086c653fSCraig Gallek 	return 0;
46571e36b1bSAlexander Aring }
46671e36b1bSAlexander Aring 
46771e36b1bSAlexander Aring static void dgram_unhash(struct sock *sk)
46871e36b1bSAlexander Aring {
46971e36b1bSAlexander Aring 	write_lock_bh(&dgram_lock);
47071e36b1bSAlexander Aring 	if (sk_del_node_init(sk))
47171e36b1bSAlexander Aring 		sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
47271e36b1bSAlexander Aring 	write_unlock_bh(&dgram_lock);
47371e36b1bSAlexander Aring }
47471e36b1bSAlexander Aring 
47571e36b1bSAlexander Aring static int dgram_init(struct sock *sk)
47671e36b1bSAlexander Aring {
47771e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
47871e36b1bSAlexander Aring 
47971e36b1bSAlexander Aring 	ro->want_ack = 1;
480811e299fSRomuald CARI 	ro->want_lqi = 0;
48171e36b1bSAlexander Aring 	return 0;
48271e36b1bSAlexander Aring }
48371e36b1bSAlexander Aring 
48471e36b1bSAlexander Aring static void dgram_close(struct sock *sk, long timeout)
48571e36b1bSAlexander Aring {
48671e36b1bSAlexander Aring 	sk_common_release(sk);
48771e36b1bSAlexander Aring }
48871e36b1bSAlexander Aring 
48971e36b1bSAlexander Aring static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
49071e36b1bSAlexander Aring {
49171e36b1bSAlexander Aring 	struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
49271e36b1bSAlexander Aring 	struct ieee802154_addr haddr;
49371e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
49471e36b1bSAlexander Aring 	int err = -EINVAL;
49571e36b1bSAlexander Aring 	struct net_device *dev;
49671e36b1bSAlexander Aring 
49771e36b1bSAlexander Aring 	lock_sock(sk);
49871e36b1bSAlexander Aring 
49971e36b1bSAlexander Aring 	ro->bound = 0;
50071e36b1bSAlexander Aring 
50194160108SHaimin Zhang 	err = ieee802154_sockaddr_check_size(addr, len);
50294160108SHaimin Zhang 	if (err < 0)
50371e36b1bSAlexander Aring 		goto out;
50471e36b1bSAlexander Aring 
505*444d8ad4SWei Yongjun 	if (addr->family != AF_IEEE802154) {
506*444d8ad4SWei Yongjun 		err = -EINVAL;
50771e36b1bSAlexander Aring 		goto out;
508*444d8ad4SWei Yongjun 	}
50971e36b1bSAlexander Aring 
51071e36b1bSAlexander Aring 	ieee802154_addr_from_sa(&haddr, &addr->addr);
51171e36b1bSAlexander Aring 	dev = ieee802154_get_dev(sock_net(sk), &haddr);
51271e36b1bSAlexander Aring 	if (!dev) {
51371e36b1bSAlexander Aring 		err = -ENODEV;
51471e36b1bSAlexander Aring 		goto out;
51571e36b1bSAlexander Aring 	}
51671e36b1bSAlexander Aring 
51771e36b1bSAlexander Aring 	if (dev->type != ARPHRD_IEEE802154) {
51871e36b1bSAlexander Aring 		err = -ENODEV;
51971e36b1bSAlexander Aring 		goto out_put;
52071e36b1bSAlexander Aring 	}
52171e36b1bSAlexander Aring 
52271e36b1bSAlexander Aring 	ro->src_addr = haddr;
52371e36b1bSAlexander Aring 
52471e36b1bSAlexander Aring 	ro->bound = 1;
52571e36b1bSAlexander Aring 	err = 0;
52671e36b1bSAlexander Aring out_put:
52771e36b1bSAlexander Aring 	dev_put(dev);
52871e36b1bSAlexander Aring out:
52971e36b1bSAlexander Aring 	release_sock(sk);
53071e36b1bSAlexander Aring 
53171e36b1bSAlexander Aring 	return err;
53271e36b1bSAlexander Aring }
53371e36b1bSAlexander Aring 
53471e36b1bSAlexander Aring static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
53571e36b1bSAlexander Aring {
53671e36b1bSAlexander Aring 	switch (cmd) {
53771e36b1bSAlexander Aring 	case SIOCOUTQ:
53871e36b1bSAlexander Aring 	{
53971e36b1bSAlexander Aring 		int amount = sk_wmem_alloc_get(sk);
54071e36b1bSAlexander Aring 
54171e36b1bSAlexander Aring 		return put_user(amount, (int __user *)arg);
54271e36b1bSAlexander Aring 	}
54371e36b1bSAlexander Aring 
54471e36b1bSAlexander Aring 	case SIOCINQ:
54571e36b1bSAlexander Aring 	{
54671e36b1bSAlexander Aring 		struct sk_buff *skb;
54771e36b1bSAlexander Aring 		unsigned long amount;
54871e36b1bSAlexander Aring 
54971e36b1bSAlexander Aring 		amount = 0;
55071e36b1bSAlexander Aring 		spin_lock_bh(&sk->sk_receive_queue.lock);
55171e36b1bSAlexander Aring 		skb = skb_peek(&sk->sk_receive_queue);
55271e36b1bSAlexander Aring 		if (skb) {
55371e36b1bSAlexander Aring 			/* We will only return the amount
55471e36b1bSAlexander Aring 			 * of this packet since that is all
55571e36b1bSAlexander Aring 			 * that will be read.
55671e36b1bSAlexander Aring 			 */
55771e36b1bSAlexander Aring 			amount = skb->len - ieee802154_hdr_length(skb);
55871e36b1bSAlexander Aring 		}
55971e36b1bSAlexander Aring 		spin_unlock_bh(&sk->sk_receive_queue.lock);
56071e36b1bSAlexander Aring 		return put_user(amount, (int __user *)arg);
56171e36b1bSAlexander Aring 	}
56271e36b1bSAlexander Aring 	}
56371e36b1bSAlexander Aring 
56471e36b1bSAlexander Aring 	return -ENOIOCTLCMD;
56571e36b1bSAlexander Aring }
56671e36b1bSAlexander Aring 
56771e36b1bSAlexander Aring /* FIXME: autobind */
56871e36b1bSAlexander Aring static int dgram_connect(struct sock *sk, struct sockaddr *uaddr,
56971e36b1bSAlexander Aring 			 int len)
57071e36b1bSAlexander Aring {
57171e36b1bSAlexander Aring 	struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
57271e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
57371e36b1bSAlexander Aring 	int err = 0;
57471e36b1bSAlexander Aring 
57594160108SHaimin Zhang 	err = ieee802154_sockaddr_check_size(addr, len);
57694160108SHaimin Zhang 	if (err < 0)
57794160108SHaimin Zhang 		return err;
57871e36b1bSAlexander Aring 
57971e36b1bSAlexander Aring 	if (addr->family != AF_IEEE802154)
58071e36b1bSAlexander Aring 		return -EINVAL;
58171e36b1bSAlexander Aring 
58271e36b1bSAlexander Aring 	lock_sock(sk);
58371e36b1bSAlexander Aring 
58471e36b1bSAlexander Aring 	if (!ro->bound) {
58571e36b1bSAlexander Aring 		err = -ENETUNREACH;
58671e36b1bSAlexander Aring 		goto out;
58771e36b1bSAlexander Aring 	}
58871e36b1bSAlexander Aring 
58971e36b1bSAlexander Aring 	ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr);
59071e36b1bSAlexander Aring 	ro->connected = 1;
59171e36b1bSAlexander Aring 
59271e36b1bSAlexander Aring out:
59371e36b1bSAlexander Aring 	release_sock(sk);
59471e36b1bSAlexander Aring 	return err;
59571e36b1bSAlexander Aring }
59671e36b1bSAlexander Aring 
59771e36b1bSAlexander Aring static int dgram_disconnect(struct sock *sk, int flags)
59871e36b1bSAlexander Aring {
59971e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
60071e36b1bSAlexander Aring 
60171e36b1bSAlexander Aring 	lock_sock(sk);
60271e36b1bSAlexander Aring 	ro->connected = 0;
60371e36b1bSAlexander Aring 	release_sock(sk);
60471e36b1bSAlexander Aring 
60571e36b1bSAlexander Aring 	return 0;
60671e36b1bSAlexander Aring }
60771e36b1bSAlexander Aring 
6081b784140SYing Xue static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
60971e36b1bSAlexander Aring {
61071e36b1bSAlexander Aring 	struct net_device *dev;
61171e36b1bSAlexander Aring 	unsigned int mtu;
61271e36b1bSAlexander Aring 	struct sk_buff *skb;
61371e36b1bSAlexander Aring 	struct ieee802154_mac_cb *cb;
61471e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
61571e36b1bSAlexander Aring 	struct ieee802154_addr dst_addr;
61694160108SHaimin Zhang 	DECLARE_SOCKADDR(struct sockaddr_ieee802154*, daddr, msg->msg_name);
61771e36b1bSAlexander Aring 	int hlen, tlen;
61871e36b1bSAlexander Aring 	int err;
61971e36b1bSAlexander Aring 
62071e36b1bSAlexander Aring 	if (msg->msg_flags & MSG_OOB) {
62171e36b1bSAlexander Aring 		pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags);
62271e36b1bSAlexander Aring 		return -EOPNOTSUPP;
62371e36b1bSAlexander Aring 	}
62471e36b1bSAlexander Aring 
62594160108SHaimin Zhang 	if (msg->msg_name) {
62694160108SHaimin Zhang 		if (ro->connected)
62771e36b1bSAlexander Aring 			return -EISCONN;
62894160108SHaimin Zhang 		if (msg->msg_namelen < IEEE802154_MIN_NAMELEN)
62994160108SHaimin Zhang 			return -EINVAL;
63094160108SHaimin Zhang 		err = ieee802154_sockaddr_check_size(daddr, msg->msg_namelen);
63194160108SHaimin Zhang 		if (err < 0)
63294160108SHaimin Zhang 			return err;
63394160108SHaimin Zhang 		ieee802154_addr_from_sa(&dst_addr, &daddr->addr);
63494160108SHaimin Zhang 	} else {
63594160108SHaimin Zhang 		if (!ro->connected)
63694160108SHaimin Zhang 			return -EDESTADDRREQ;
63794160108SHaimin Zhang 		dst_addr = ro->dst_addr;
63894160108SHaimin Zhang 	}
63971e36b1bSAlexander Aring 
64071e36b1bSAlexander Aring 	if (!ro->bound)
64171e36b1bSAlexander Aring 		dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154);
64271e36b1bSAlexander Aring 	else
64371e36b1bSAlexander Aring 		dev = ieee802154_get_dev(sock_net(sk), &ro->src_addr);
64471e36b1bSAlexander Aring 
64571e36b1bSAlexander Aring 	if (!dev) {
64671e36b1bSAlexander Aring 		pr_debug("no dev\n");
64771e36b1bSAlexander Aring 		err = -ENXIO;
64871e36b1bSAlexander Aring 		goto out;
64971e36b1bSAlexander Aring 	}
650b40988c4SAlexander Aring 	mtu = IEEE802154_MTU;
65171e36b1bSAlexander Aring 	pr_debug("name = %s, mtu = %u\n", dev->name, mtu);
65271e36b1bSAlexander Aring 
65371e36b1bSAlexander Aring 	if (size > mtu) {
6545b5e0928SAlexey Dobriyan 		pr_debug("size = %zu, mtu = %u\n", size, mtu);
65571e36b1bSAlexander Aring 		err = -EMSGSIZE;
65671e36b1bSAlexander Aring 		goto out_dev;
65771e36b1bSAlexander Aring 	}
65871e36b1bSAlexander Aring 
65971e36b1bSAlexander Aring 	hlen = LL_RESERVED_SPACE(dev);
66071e36b1bSAlexander Aring 	tlen = dev->needed_tailroom;
66171e36b1bSAlexander Aring 	skb = sock_alloc_send_skb(sk, hlen + tlen + size,
66271e36b1bSAlexander Aring 				  msg->msg_flags & MSG_DONTWAIT,
66371e36b1bSAlexander Aring 				  &err);
66471e36b1bSAlexander Aring 	if (!skb)
66571e36b1bSAlexander Aring 		goto out_dev;
66671e36b1bSAlexander Aring 
66771e36b1bSAlexander Aring 	skb_reserve(skb, hlen);
66871e36b1bSAlexander Aring 
66971e36b1bSAlexander Aring 	skb_reset_network_header(skb);
67071e36b1bSAlexander Aring 
67171e36b1bSAlexander Aring 	cb = mac_cb_init(skb);
67271e36b1bSAlexander Aring 	cb->type = IEEE802154_FC_TYPE_DATA;
67371e36b1bSAlexander Aring 	cb->ackreq = ro->want_ack;
67471e36b1bSAlexander Aring 	cb->secen = ro->secen;
67571e36b1bSAlexander Aring 	cb->secen_override = ro->secen_override;
67671e36b1bSAlexander Aring 	cb->seclevel = ro->seclevel;
67771e36b1bSAlexander Aring 	cb->seclevel_override = ro->seclevel_override;
67871e36b1bSAlexander Aring 
679838b83d6SAlexander Aring 	err = wpan_dev_hard_header(skb, dev, &dst_addr,
68071e36b1bSAlexander Aring 				   ro->bound ? &ro->src_addr : NULL, size);
68171e36b1bSAlexander Aring 	if (err < 0)
68271e36b1bSAlexander Aring 		goto out_skb;
68371e36b1bSAlexander Aring 
68471e36b1bSAlexander Aring 	err = memcpy_from_msg(skb_put(skb, size), msg, size);
68571e36b1bSAlexander Aring 	if (err < 0)
68671e36b1bSAlexander Aring 		goto out_skb;
68771e36b1bSAlexander Aring 
68871e36b1bSAlexander Aring 	skb->dev = dev;
68971e36b1bSAlexander Aring 	skb->protocol = htons(ETH_P_IEEE802154);
69071e36b1bSAlexander Aring 
69171e36b1bSAlexander Aring 	err = dev_queue_xmit(skb);
69271e36b1bSAlexander Aring 	if (err > 0)
69371e36b1bSAlexander Aring 		err = net_xmit_errno(err);
69471e36b1bSAlexander Aring 
695a611c58bSLin Zhang 	dev_put(dev);
696a611c58bSLin Zhang 
69771e36b1bSAlexander Aring 	return err ?: size;
69871e36b1bSAlexander Aring 
69971e36b1bSAlexander Aring out_skb:
70071e36b1bSAlexander Aring 	kfree_skb(skb);
70171e36b1bSAlexander Aring out_dev:
70271e36b1bSAlexander Aring 	dev_put(dev);
70371e36b1bSAlexander Aring out:
70471e36b1bSAlexander Aring 	return err;
70571e36b1bSAlexander Aring }
70671e36b1bSAlexander Aring 
7071b784140SYing Xue static int dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
708ec095263SOliver Hartkopp 			 int flags, int *addr_len)
70971e36b1bSAlexander Aring {
71071e36b1bSAlexander Aring 	size_t copied = 0;
71171e36b1bSAlexander Aring 	int err = -EOPNOTSUPP;
71271e36b1bSAlexander Aring 	struct sk_buff *skb;
713811e299fSRomuald CARI 	struct dgram_sock *ro = dgram_sk(sk);
71471e36b1bSAlexander Aring 	DECLARE_SOCKADDR(struct sockaddr_ieee802154 *, saddr, msg->msg_name);
71571e36b1bSAlexander Aring 
716f4b41f06SOliver Hartkopp 	skb = skb_recv_datagram(sk, flags, &err);
71771e36b1bSAlexander Aring 	if (!skb)
71871e36b1bSAlexander Aring 		goto out;
71971e36b1bSAlexander Aring 
72071e36b1bSAlexander Aring 	copied = skb->len;
72171e36b1bSAlexander Aring 	if (len < copied) {
72271e36b1bSAlexander Aring 		msg->msg_flags |= MSG_TRUNC;
72371e36b1bSAlexander Aring 		copied = len;
72471e36b1bSAlexander Aring 	}
72571e36b1bSAlexander Aring 
72671e36b1bSAlexander Aring 	/* FIXME: skip headers if necessary ?! */
72771e36b1bSAlexander Aring 	err = skb_copy_datagram_msg(skb, 0, msg, copied);
72871e36b1bSAlexander Aring 	if (err)
72971e36b1bSAlexander Aring 		goto done;
73071e36b1bSAlexander Aring 
7316fd1d51cSErin MacNeil 	sock_recv_cmsgs(msg, sk, skb);
73271e36b1bSAlexander Aring 
73371e36b1bSAlexander Aring 	if (saddr) {
7348a70cefaSLennert Buytenhek 		/* Clear the implicit padding in struct sockaddr_ieee802154
7358a70cefaSLennert Buytenhek 		 * (16 bits between 'family' and 'addr') and in struct
7368a70cefaSLennert Buytenhek 		 * ieee802154_addr_sa (16 bits at the end of the structure).
7378a70cefaSLennert Buytenhek 		 */
7388a70cefaSLennert Buytenhek 		memset(saddr, 0, sizeof(*saddr));
7398a70cefaSLennert Buytenhek 
74071e36b1bSAlexander Aring 		saddr->family = AF_IEEE802154;
74171e36b1bSAlexander Aring 		ieee802154_addr_to_sa(&saddr->addr, &mac_cb(skb)->source);
74271e36b1bSAlexander Aring 		*addr_len = sizeof(*saddr);
74371e36b1bSAlexander Aring 	}
74471e36b1bSAlexander Aring 
745811e299fSRomuald CARI 	if (ro->want_lqi) {
746811e299fSRomuald CARI 		err = put_cmsg(msg, SOL_IEEE802154, WPAN_WANTLQI,
747811e299fSRomuald CARI 			       sizeof(uint8_t), &(mac_cb(skb)->lqi));
748811e299fSRomuald CARI 		if (err)
749811e299fSRomuald CARI 			goto done;
750811e299fSRomuald CARI 	}
751811e299fSRomuald CARI 
75271e36b1bSAlexander Aring 	if (flags & MSG_TRUNC)
75371e36b1bSAlexander Aring 		copied = skb->len;
75471e36b1bSAlexander Aring done:
75571e36b1bSAlexander Aring 	skb_free_datagram(sk, skb);
75671e36b1bSAlexander Aring out:
75771e36b1bSAlexander Aring 	if (err)
75871e36b1bSAlexander Aring 		return err;
75971e36b1bSAlexander Aring 	return copied;
76071e36b1bSAlexander Aring }
76171e36b1bSAlexander Aring 
76271e36b1bSAlexander Aring static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb)
76371e36b1bSAlexander Aring {
76471e36b1bSAlexander Aring 	skb = skb_share_check(skb, GFP_ATOMIC);
76571e36b1bSAlexander Aring 	if (!skb)
76671e36b1bSAlexander Aring 		return NET_RX_DROP;
76771e36b1bSAlexander Aring 
76871e36b1bSAlexander Aring 	if (sock_queue_rcv_skb(sk, skb) < 0) {
76971e36b1bSAlexander Aring 		kfree_skb(skb);
77071e36b1bSAlexander Aring 		return NET_RX_DROP;
77171e36b1bSAlexander Aring 	}
77271e36b1bSAlexander Aring 
77371e36b1bSAlexander Aring 	return NET_RX_SUCCESS;
77471e36b1bSAlexander Aring }
77571e36b1bSAlexander Aring 
77671e36b1bSAlexander Aring static inline bool
77771e36b1bSAlexander Aring ieee802154_match_sock(__le64 hw_addr, __le16 pan_id, __le16 short_addr,
77871e36b1bSAlexander Aring 		      struct dgram_sock *ro)
77971e36b1bSAlexander Aring {
78071e36b1bSAlexander Aring 	if (!ro->bound)
78171e36b1bSAlexander Aring 		return true;
78271e36b1bSAlexander Aring 
78371e36b1bSAlexander Aring 	if (ro->src_addr.mode == IEEE802154_ADDR_LONG &&
78471e36b1bSAlexander Aring 	    hw_addr == ro->src_addr.extended_addr)
78571e36b1bSAlexander Aring 		return true;
78671e36b1bSAlexander Aring 
78771e36b1bSAlexander Aring 	if (ro->src_addr.mode == IEEE802154_ADDR_SHORT &&
78871e36b1bSAlexander Aring 	    pan_id == ro->src_addr.pan_id &&
78971e36b1bSAlexander Aring 	    short_addr == ro->src_addr.short_addr)
79071e36b1bSAlexander Aring 		return true;
79171e36b1bSAlexander Aring 
79271e36b1bSAlexander Aring 	return false;
79371e36b1bSAlexander Aring }
79471e36b1bSAlexander Aring 
79571e36b1bSAlexander Aring static int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
79671e36b1bSAlexander Aring {
79771e36b1bSAlexander Aring 	struct sock *sk, *prev = NULL;
79871e36b1bSAlexander Aring 	int ret = NET_RX_SUCCESS;
79971e36b1bSAlexander Aring 	__le16 pan_id, short_addr;
80071e36b1bSAlexander Aring 	__le64 hw_addr;
80171e36b1bSAlexander Aring 
80271e36b1bSAlexander Aring 	/* Data frame processing */
80371e36b1bSAlexander Aring 	BUG_ON(dev->type != ARPHRD_IEEE802154);
80471e36b1bSAlexander Aring 
805c947f7e1SAlexander Aring 	pan_id = dev->ieee802154_ptr->pan_id;
806c947f7e1SAlexander Aring 	short_addr = dev->ieee802154_ptr->short_addr;
807c947f7e1SAlexander Aring 	hw_addr = dev->ieee802154_ptr->extended_addr;
80871e36b1bSAlexander Aring 
80971e36b1bSAlexander Aring 	read_lock(&dgram_lock);
81071e36b1bSAlexander Aring 	sk_for_each(sk, &dgram_head) {
81171e36b1bSAlexander Aring 		if (ieee802154_match_sock(hw_addr, pan_id, short_addr,
81271e36b1bSAlexander Aring 					  dgram_sk(sk))) {
81371e36b1bSAlexander Aring 			if (prev) {
81471e36b1bSAlexander Aring 				struct sk_buff *clone;
81571e36b1bSAlexander Aring 
81671e36b1bSAlexander Aring 				clone = skb_clone(skb, GFP_ATOMIC);
81771e36b1bSAlexander Aring 				if (clone)
81871e36b1bSAlexander Aring 					dgram_rcv_skb(prev, clone);
81971e36b1bSAlexander Aring 			}
82071e36b1bSAlexander Aring 
82171e36b1bSAlexander Aring 			prev = sk;
82271e36b1bSAlexander Aring 		}
82371e36b1bSAlexander Aring 	}
82471e36b1bSAlexander Aring 
82571e36b1bSAlexander Aring 	if (prev) {
82671e36b1bSAlexander Aring 		dgram_rcv_skb(prev, skb);
82771e36b1bSAlexander Aring 	} else {
82871e36b1bSAlexander Aring 		kfree_skb(skb);
82971e36b1bSAlexander Aring 		ret = NET_RX_DROP;
83071e36b1bSAlexander Aring 	}
83171e36b1bSAlexander Aring 	read_unlock(&dgram_lock);
83271e36b1bSAlexander Aring 
83371e36b1bSAlexander Aring 	return ret;
83471e36b1bSAlexander Aring }
83571e36b1bSAlexander Aring 
83671e36b1bSAlexander Aring static int dgram_getsockopt(struct sock *sk, int level, int optname,
83771e36b1bSAlexander Aring 			    char __user *optval, int __user *optlen)
83871e36b1bSAlexander Aring {
83971e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
84071e36b1bSAlexander Aring 
84171e36b1bSAlexander Aring 	int val, len;
84271e36b1bSAlexander Aring 
84371e36b1bSAlexander Aring 	if (level != SOL_IEEE802154)
84471e36b1bSAlexander Aring 		return -EOPNOTSUPP;
84571e36b1bSAlexander Aring 
84671e36b1bSAlexander Aring 	if (get_user(len, optlen))
84771e36b1bSAlexander Aring 		return -EFAULT;
84871e36b1bSAlexander Aring 
84971e36b1bSAlexander Aring 	len = min_t(unsigned int, len, sizeof(int));
85071e36b1bSAlexander Aring 
85171e36b1bSAlexander Aring 	switch (optname) {
85271e36b1bSAlexander Aring 	case WPAN_WANTACK:
85371e36b1bSAlexander Aring 		val = ro->want_ack;
85471e36b1bSAlexander Aring 		break;
855811e299fSRomuald CARI 	case WPAN_WANTLQI:
856811e299fSRomuald CARI 		val = ro->want_lqi;
857811e299fSRomuald CARI 		break;
85871e36b1bSAlexander Aring 	case WPAN_SECURITY:
85971e36b1bSAlexander Aring 		if (!ro->secen_override)
86071e36b1bSAlexander Aring 			val = WPAN_SECURITY_DEFAULT;
86171e36b1bSAlexander Aring 		else if (ro->secen)
86271e36b1bSAlexander Aring 			val = WPAN_SECURITY_ON;
86371e36b1bSAlexander Aring 		else
86471e36b1bSAlexander Aring 			val = WPAN_SECURITY_OFF;
86571e36b1bSAlexander Aring 		break;
86671e36b1bSAlexander Aring 	case WPAN_SECURITY_LEVEL:
86771e36b1bSAlexander Aring 		if (!ro->seclevel_override)
86871e36b1bSAlexander Aring 			val = WPAN_SECURITY_LEVEL_DEFAULT;
86971e36b1bSAlexander Aring 		else
87071e36b1bSAlexander Aring 			val = ro->seclevel;
87171e36b1bSAlexander Aring 		break;
87271e36b1bSAlexander Aring 	default:
87371e36b1bSAlexander Aring 		return -ENOPROTOOPT;
87471e36b1bSAlexander Aring 	}
87571e36b1bSAlexander Aring 
87671e36b1bSAlexander Aring 	if (put_user(len, optlen))
87771e36b1bSAlexander Aring 		return -EFAULT;
87871e36b1bSAlexander Aring 	if (copy_to_user(optval, &val, len))
87971e36b1bSAlexander Aring 		return -EFAULT;
88071e36b1bSAlexander Aring 	return 0;
88171e36b1bSAlexander Aring }
88271e36b1bSAlexander Aring 
88371e36b1bSAlexander Aring static int dgram_setsockopt(struct sock *sk, int level, int optname,
884a7b75c5aSChristoph Hellwig 			    sockptr_t optval, unsigned int optlen)
88571e36b1bSAlexander Aring {
88671e36b1bSAlexander Aring 	struct dgram_sock *ro = dgram_sk(sk);
88771e36b1bSAlexander Aring 	struct net *net = sock_net(sk);
88871e36b1bSAlexander Aring 	int val;
88971e36b1bSAlexander Aring 	int err = 0;
89071e36b1bSAlexander Aring 
89171e36b1bSAlexander Aring 	if (optlen < sizeof(int))
89271e36b1bSAlexander Aring 		return -EINVAL;
89371e36b1bSAlexander Aring 
894a7b75c5aSChristoph Hellwig 	if (copy_from_sockptr(&val, optval, sizeof(int)))
89571e36b1bSAlexander Aring 		return -EFAULT;
89671e36b1bSAlexander Aring 
89771e36b1bSAlexander Aring 	lock_sock(sk);
89871e36b1bSAlexander Aring 
89971e36b1bSAlexander Aring 	switch (optname) {
90071e36b1bSAlexander Aring 	case WPAN_WANTACK:
90171e36b1bSAlexander Aring 		ro->want_ack = !!val;
90271e36b1bSAlexander Aring 		break;
903811e299fSRomuald CARI 	case WPAN_WANTLQI:
904811e299fSRomuald CARI 		ro->want_lqi = !!val;
905811e299fSRomuald CARI 		break;
90671e36b1bSAlexander Aring 	case WPAN_SECURITY:
90771e36b1bSAlexander Aring 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
90871e36b1bSAlexander Aring 		    !ns_capable(net->user_ns, CAP_NET_RAW)) {
90971e36b1bSAlexander Aring 			err = -EPERM;
91071e36b1bSAlexander Aring 			break;
91171e36b1bSAlexander Aring 		}
91271e36b1bSAlexander Aring 
91371e36b1bSAlexander Aring 		switch (val) {
91471e36b1bSAlexander Aring 		case WPAN_SECURITY_DEFAULT:
91571e36b1bSAlexander Aring 			ro->secen_override = 0;
91671e36b1bSAlexander Aring 			break;
91771e36b1bSAlexander Aring 		case WPAN_SECURITY_ON:
91871e36b1bSAlexander Aring 			ro->secen_override = 1;
91971e36b1bSAlexander Aring 			ro->secen = 1;
92071e36b1bSAlexander Aring 			break;
92171e36b1bSAlexander Aring 		case WPAN_SECURITY_OFF:
92271e36b1bSAlexander Aring 			ro->secen_override = 1;
92371e36b1bSAlexander Aring 			ro->secen = 0;
92471e36b1bSAlexander Aring 			break;
92571e36b1bSAlexander Aring 		default:
92671e36b1bSAlexander Aring 			err = -EINVAL;
92771e36b1bSAlexander Aring 			break;
92871e36b1bSAlexander Aring 		}
92971e36b1bSAlexander Aring 		break;
93071e36b1bSAlexander Aring 	case WPAN_SECURITY_LEVEL:
93171e36b1bSAlexander Aring 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
93271e36b1bSAlexander Aring 		    !ns_capable(net->user_ns, CAP_NET_RAW)) {
93371e36b1bSAlexander Aring 			err = -EPERM;
93471e36b1bSAlexander Aring 			break;
93571e36b1bSAlexander Aring 		}
93671e36b1bSAlexander Aring 
93771e36b1bSAlexander Aring 		if (val < WPAN_SECURITY_LEVEL_DEFAULT ||
93871e36b1bSAlexander Aring 		    val > IEEE802154_SCF_SECLEVEL_ENC_MIC128) {
93971e36b1bSAlexander Aring 			err = -EINVAL;
94071e36b1bSAlexander Aring 		} else if (val == WPAN_SECURITY_LEVEL_DEFAULT) {
94171e36b1bSAlexander Aring 			ro->seclevel_override = 0;
94271e36b1bSAlexander Aring 		} else {
94371e36b1bSAlexander Aring 			ro->seclevel_override = 1;
94471e36b1bSAlexander Aring 			ro->seclevel = val;
94571e36b1bSAlexander Aring 		}
94671e36b1bSAlexander Aring 		break;
94771e36b1bSAlexander Aring 	default:
94871e36b1bSAlexander Aring 		err = -ENOPROTOOPT;
94971e36b1bSAlexander Aring 		break;
95071e36b1bSAlexander Aring 	}
95171e36b1bSAlexander Aring 
95271e36b1bSAlexander Aring 	release_sock(sk);
95371e36b1bSAlexander Aring 	return err;
95471e36b1bSAlexander Aring }
95571e36b1bSAlexander Aring 
95671e36b1bSAlexander Aring static struct proto ieee802154_dgram_prot = {
95771e36b1bSAlexander Aring 	.name		= "IEEE-802.15.4-MAC",
95871e36b1bSAlexander Aring 	.owner		= THIS_MODULE,
95971e36b1bSAlexander Aring 	.obj_size	= sizeof(struct dgram_sock),
96071e36b1bSAlexander Aring 	.init		= dgram_init,
96171e36b1bSAlexander Aring 	.close		= dgram_close,
96271e36b1bSAlexander Aring 	.bind		= dgram_bind,
96371e36b1bSAlexander Aring 	.sendmsg	= dgram_sendmsg,
96471e36b1bSAlexander Aring 	.recvmsg	= dgram_recvmsg,
96571e36b1bSAlexander Aring 	.hash		= dgram_hash,
96671e36b1bSAlexander Aring 	.unhash		= dgram_unhash,
96771e36b1bSAlexander Aring 	.connect	= dgram_connect,
96871e36b1bSAlexander Aring 	.disconnect	= dgram_disconnect,
96971e36b1bSAlexander Aring 	.ioctl		= dgram_ioctl,
97071e36b1bSAlexander Aring 	.getsockopt	= dgram_getsockopt,
97171e36b1bSAlexander Aring 	.setsockopt	= dgram_setsockopt,
97271e36b1bSAlexander Aring };
97371e36b1bSAlexander Aring 
97471e36b1bSAlexander Aring static const struct proto_ops ieee802154_dgram_ops = {
97571e36b1bSAlexander Aring 	.family		   = PF_IEEE802154,
97671e36b1bSAlexander Aring 	.owner		   = THIS_MODULE,
97771e36b1bSAlexander Aring 	.release	   = ieee802154_sock_release,
97871e36b1bSAlexander Aring 	.bind		   = ieee802154_sock_bind,
97971e36b1bSAlexander Aring 	.connect	   = ieee802154_sock_connect,
98071e36b1bSAlexander Aring 	.socketpair	   = sock_no_socketpair,
98171e36b1bSAlexander Aring 	.accept		   = sock_no_accept,
98271e36b1bSAlexander Aring 	.getname	   = sock_no_getname,
983a11e1d43SLinus Torvalds 	.poll		   = datagram_poll,
98471e36b1bSAlexander Aring 	.ioctl		   = ieee802154_sock_ioctl,
985c7cbdbf2SArnd Bergmann 	.gettstamp	   = sock_gettstamp,
98671e36b1bSAlexander Aring 	.listen		   = sock_no_listen,
98771e36b1bSAlexander Aring 	.shutdown	   = sock_no_shutdown,
98871e36b1bSAlexander Aring 	.setsockopt	   = sock_common_setsockopt,
98971e36b1bSAlexander Aring 	.getsockopt	   = sock_common_getsockopt,
99071e36b1bSAlexander Aring 	.sendmsg	   = ieee802154_sock_sendmsg,
99171e36b1bSAlexander Aring 	.recvmsg	   = sock_common_recvmsg,
99271e36b1bSAlexander Aring 	.mmap		   = sock_no_mmap,
99371e36b1bSAlexander Aring 	.sendpage	   = sock_no_sendpage,
99471e36b1bSAlexander Aring };
99571e36b1bSAlexander Aring 
9961090340fSTakeshi Misawa static void ieee802154_sock_destruct(struct sock *sk)
9971090340fSTakeshi Misawa {
9981090340fSTakeshi Misawa 	skb_queue_purge(&sk->sk_receive_queue);
9991090340fSTakeshi Misawa }
10001090340fSTakeshi Misawa 
100171e36b1bSAlexander Aring /* Create a socket. Initialise the socket, blank the addresses
100271e36b1bSAlexander Aring  * set the state.
100371e36b1bSAlexander Aring  */
100471e36b1bSAlexander Aring static int ieee802154_create(struct net *net, struct socket *sock,
100571e36b1bSAlexander Aring 			     int protocol, int kern)
100671e36b1bSAlexander Aring {
100771e36b1bSAlexander Aring 	struct sock *sk;
100871e36b1bSAlexander Aring 	int rc;
100971e36b1bSAlexander Aring 	struct proto *proto;
101071e36b1bSAlexander Aring 	const struct proto_ops *ops;
101171e36b1bSAlexander Aring 
101271e36b1bSAlexander Aring 	if (!net_eq(net, &init_net))
101371e36b1bSAlexander Aring 		return -EAFNOSUPPORT;
101471e36b1bSAlexander Aring 
101571e36b1bSAlexander Aring 	switch (sock->type) {
101671e36b1bSAlexander Aring 	case SOCK_RAW:
1017e69dbd46SOri Nimron 		rc = -EPERM;
1018e69dbd46SOri Nimron 		if (!capable(CAP_NET_RAW))
1019e69dbd46SOri Nimron 			goto out;
102071e36b1bSAlexander Aring 		proto = &ieee802154_raw_prot;
102171e36b1bSAlexander Aring 		ops = &ieee802154_raw_ops;
102271e36b1bSAlexander Aring 		break;
102371e36b1bSAlexander Aring 	case SOCK_DGRAM:
102471e36b1bSAlexander Aring 		proto = &ieee802154_dgram_prot;
102571e36b1bSAlexander Aring 		ops = &ieee802154_dgram_ops;
102671e36b1bSAlexander Aring 		break;
102771e36b1bSAlexander Aring 	default:
102871e36b1bSAlexander Aring 		rc = -ESOCKTNOSUPPORT;
102971e36b1bSAlexander Aring 		goto out;
103071e36b1bSAlexander Aring 	}
103171e36b1bSAlexander Aring 
103271e36b1bSAlexander Aring 	rc = -ENOMEM;
103311aa9c28SEric W. Biederman 	sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto, kern);
103471e36b1bSAlexander Aring 	if (!sk)
103571e36b1bSAlexander Aring 		goto out;
103671e36b1bSAlexander Aring 	rc = 0;
103771e36b1bSAlexander Aring 
103871e36b1bSAlexander Aring 	sock->ops = ops;
103971e36b1bSAlexander Aring 
104071e36b1bSAlexander Aring 	sock_init_data(sock, sk);
10411090340fSTakeshi Misawa 	sk->sk_destruct = ieee802154_sock_destruct;
104271e36b1bSAlexander Aring 	sk->sk_family = PF_IEEE802154;
104371e36b1bSAlexander Aring 
104471e36b1bSAlexander Aring 	/* Checksums on by default */
104571e36b1bSAlexander Aring 	sock_set_flag(sk, SOCK_ZAPPED);
104671e36b1bSAlexander Aring 
1047086c653fSCraig Gallek 	if (sk->sk_prot->hash) {
1048086c653fSCraig Gallek 		rc = sk->sk_prot->hash(sk);
1049086c653fSCraig Gallek 		if (rc) {
1050086c653fSCraig Gallek 			sk_common_release(sk);
1051086c653fSCraig Gallek 			goto out;
1052086c653fSCraig Gallek 		}
1053086c653fSCraig Gallek 	}
105471e36b1bSAlexander Aring 
105571e36b1bSAlexander Aring 	if (sk->sk_prot->init) {
105671e36b1bSAlexander Aring 		rc = sk->sk_prot->init(sk);
105771e36b1bSAlexander Aring 		if (rc)
105871e36b1bSAlexander Aring 			sk_common_release(sk);
105971e36b1bSAlexander Aring 	}
106071e36b1bSAlexander Aring out:
106171e36b1bSAlexander Aring 	return rc;
106271e36b1bSAlexander Aring }
106371e36b1bSAlexander Aring 
106471e36b1bSAlexander Aring static const struct net_proto_family ieee802154_family_ops = {
106571e36b1bSAlexander Aring 	.family		= PF_IEEE802154,
106671e36b1bSAlexander Aring 	.create		= ieee802154_create,
106771e36b1bSAlexander Aring 	.owner		= THIS_MODULE,
106871e36b1bSAlexander Aring };
106971e36b1bSAlexander Aring 
107071e36b1bSAlexander Aring static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev,
107171e36b1bSAlexander Aring 			  struct packet_type *pt, struct net_device *orig_dev)
107271e36b1bSAlexander Aring {
107371e36b1bSAlexander Aring 	if (!netif_running(dev))
107471e36b1bSAlexander Aring 		goto drop;
107571e36b1bSAlexander Aring 	pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
107671e36b1bSAlexander Aring #ifdef DEBUG
107771e36b1bSAlexander Aring 	print_hex_dump_bytes("ieee802154_rcv ",
107871e36b1bSAlexander Aring 			     DUMP_PREFIX_NONE, skb->data, skb->len);
107971e36b1bSAlexander Aring #endif
108071e36b1bSAlexander Aring 
108171e36b1bSAlexander Aring 	if (!net_eq(dev_net(dev), &init_net))
108271e36b1bSAlexander Aring 		goto drop;
108371e36b1bSAlexander Aring 
108471e36b1bSAlexander Aring 	ieee802154_raw_deliver(dev, skb);
108571e36b1bSAlexander Aring 
108671e36b1bSAlexander Aring 	if (dev->type != ARPHRD_IEEE802154)
108771e36b1bSAlexander Aring 		goto drop;
108871e36b1bSAlexander Aring 
108971e36b1bSAlexander Aring 	if (skb->pkt_type != PACKET_OTHERHOST)
109071e36b1bSAlexander Aring 		return ieee802154_dgram_deliver(dev, skb);
109171e36b1bSAlexander Aring 
109271e36b1bSAlexander Aring drop:
109371e36b1bSAlexander Aring 	kfree_skb(skb);
109471e36b1bSAlexander Aring 	return NET_RX_DROP;
109571e36b1bSAlexander Aring }
109671e36b1bSAlexander Aring 
109771e36b1bSAlexander Aring static struct packet_type ieee802154_packet_type = {
109871e36b1bSAlexander Aring 	.type = htons(ETH_P_IEEE802154),
109971e36b1bSAlexander Aring 	.func = ieee802154_rcv,
110071e36b1bSAlexander Aring };
110171e36b1bSAlexander Aring 
110271e36b1bSAlexander Aring static int __init af_ieee802154_init(void)
110371e36b1bSAlexander Aring {
1104074014abSColin Ian King 	int rc;
110571e36b1bSAlexander Aring 
110671e36b1bSAlexander Aring 	rc = proto_register(&ieee802154_raw_prot, 1);
110771e36b1bSAlexander Aring 	if (rc)
110871e36b1bSAlexander Aring 		goto out;
110971e36b1bSAlexander Aring 
111071e36b1bSAlexander Aring 	rc = proto_register(&ieee802154_dgram_prot, 1);
111171e36b1bSAlexander Aring 	if (rc)
111271e36b1bSAlexander Aring 		goto err_dgram;
111371e36b1bSAlexander Aring 
111471e36b1bSAlexander Aring 	/* Tell SOCKET that we are alive */
111571e36b1bSAlexander Aring 	rc = sock_register(&ieee802154_family_ops);
111671e36b1bSAlexander Aring 	if (rc)
111771e36b1bSAlexander Aring 		goto err_sock;
111871e36b1bSAlexander Aring 	dev_add_pack(&ieee802154_packet_type);
111971e36b1bSAlexander Aring 
112071e36b1bSAlexander Aring 	rc = 0;
112171e36b1bSAlexander Aring 	goto out;
112271e36b1bSAlexander Aring 
112371e36b1bSAlexander Aring err_sock:
112471e36b1bSAlexander Aring 	proto_unregister(&ieee802154_dgram_prot);
112571e36b1bSAlexander Aring err_dgram:
112671e36b1bSAlexander Aring 	proto_unregister(&ieee802154_raw_prot);
112771e36b1bSAlexander Aring out:
112871e36b1bSAlexander Aring 	return rc;
112971e36b1bSAlexander Aring }
113071e36b1bSAlexander Aring 
113171e36b1bSAlexander Aring static void __exit af_ieee802154_remove(void)
113271e36b1bSAlexander Aring {
113371e36b1bSAlexander Aring 	dev_remove_pack(&ieee802154_packet_type);
113471e36b1bSAlexander Aring 	sock_unregister(PF_IEEE802154);
113571e36b1bSAlexander Aring 	proto_unregister(&ieee802154_dgram_prot);
113671e36b1bSAlexander Aring 	proto_unregister(&ieee802154_raw_prot);
113771e36b1bSAlexander Aring }
113871e36b1bSAlexander Aring 
113971e36b1bSAlexander Aring module_init(af_ieee802154_init);
114071e36b1bSAlexander Aring module_exit(af_ieee802154_remove);
114171e36b1bSAlexander Aring 
114271e36b1bSAlexander Aring MODULE_LICENSE("GPL");
114371e36b1bSAlexander Aring MODULE_ALIAS_NETPROTO(PF_IEEE802154);
1144