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;
165e1d001faSBreno 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)533e1d001faSBreno Leitao static int dgram_ioctl(struct sock *sk, int cmd, int *karg)
53471e36b1bSAlexander Aring {
53571e36b1bSAlexander Aring switch (cmd) {
53671e36b1bSAlexander Aring case SIOCOUTQ:
53771e36b1bSAlexander Aring {
538e1d001faSBreno Leitao *karg = sk_wmem_alloc_get(sk);
53971e36b1bSAlexander Aring
540e1d001faSBreno Leitao return 0;
54171e36b1bSAlexander Aring }
54271e36b1bSAlexander Aring
54371e36b1bSAlexander Aring case SIOCINQ:
54471e36b1bSAlexander Aring {
54571e36b1bSAlexander Aring struct sk_buff *skb;
54671e36b1bSAlexander Aring
547e1d001faSBreno 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 */
555e1d001faSBreno Leitao *karg = skb->len - ieee802154_hdr_length(skb);
55671e36b1bSAlexander Aring }
55771e36b1bSAlexander Aring spin_unlock_bh(&sk->sk_receive_queue.lock);
558e1d001faSBreno 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);
1046*b4982fbfSIgnat Korchagin if (rc)
1047*b4982fbfSIgnat Korchagin goto out_sk_release;
1048086c653fSCraig Gallek }
104971e36b1bSAlexander Aring
105071e36b1bSAlexander Aring if (sk->sk_prot->init) {
105171e36b1bSAlexander Aring rc = sk->sk_prot->init(sk);
105271e36b1bSAlexander Aring if (rc)
1053*b4982fbfSIgnat Korchagin goto out_sk_release;
105471e36b1bSAlexander Aring }
105571e36b1bSAlexander Aring out:
105671e36b1bSAlexander Aring return rc;
1057*b4982fbfSIgnat Korchagin out_sk_release:
1058*b4982fbfSIgnat Korchagin sk_common_release(sk);
1059*b4982fbfSIgnat Korchagin sock->sk = NULL;
1060*b4982fbfSIgnat Korchagin goto out;
106171e36b1bSAlexander Aring }
106271e36b1bSAlexander Aring
106371e36b1bSAlexander Aring static const struct net_proto_family ieee802154_family_ops = {
106471e36b1bSAlexander Aring .family = PF_IEEE802154,
106571e36b1bSAlexander Aring .create = ieee802154_create,
106671e36b1bSAlexander Aring .owner = THIS_MODULE,
106771e36b1bSAlexander Aring };
106871e36b1bSAlexander Aring
ieee802154_rcv(struct sk_buff * skb,struct net_device * dev,struct packet_type * pt,struct net_device * orig_dev)106971e36b1bSAlexander Aring static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev,
107071e36b1bSAlexander Aring struct packet_type *pt, struct net_device *orig_dev)
107171e36b1bSAlexander Aring {
107271e36b1bSAlexander Aring if (!netif_running(dev))
107371e36b1bSAlexander Aring goto drop;
107471e36b1bSAlexander Aring pr_debug("got frame, type %d, dev %p\n", dev->type, dev);
107571e36b1bSAlexander Aring #ifdef DEBUG
107671e36b1bSAlexander Aring print_hex_dump_bytes("ieee802154_rcv ",
107771e36b1bSAlexander Aring DUMP_PREFIX_NONE, skb->data, skb->len);
107871e36b1bSAlexander Aring #endif
107971e36b1bSAlexander Aring
108071e36b1bSAlexander Aring if (!net_eq(dev_net(dev), &init_net))
108171e36b1bSAlexander Aring goto drop;
108271e36b1bSAlexander Aring
108371e36b1bSAlexander Aring ieee802154_raw_deliver(dev, skb);
108471e36b1bSAlexander Aring
108571e36b1bSAlexander Aring if (dev->type != ARPHRD_IEEE802154)
108671e36b1bSAlexander Aring goto drop;
108771e36b1bSAlexander Aring
108871e36b1bSAlexander Aring if (skb->pkt_type != PACKET_OTHERHOST)
108971e36b1bSAlexander Aring return ieee802154_dgram_deliver(dev, skb);
109071e36b1bSAlexander Aring
109171e36b1bSAlexander Aring drop:
109271e36b1bSAlexander Aring kfree_skb(skb);
109371e36b1bSAlexander Aring return NET_RX_DROP;
109471e36b1bSAlexander Aring }
109571e36b1bSAlexander Aring
109671e36b1bSAlexander Aring static struct packet_type ieee802154_packet_type = {
109771e36b1bSAlexander Aring .type = htons(ETH_P_IEEE802154),
109871e36b1bSAlexander Aring .func = ieee802154_rcv,
109971e36b1bSAlexander Aring };
110071e36b1bSAlexander Aring
af_ieee802154_init(void)110171e36b1bSAlexander Aring static int __init af_ieee802154_init(void)
110271e36b1bSAlexander Aring {
1103074014abSColin Ian King int rc;
110471e36b1bSAlexander Aring
110571e36b1bSAlexander Aring rc = proto_register(&ieee802154_raw_prot, 1);
110671e36b1bSAlexander Aring if (rc)
110771e36b1bSAlexander Aring goto out;
110871e36b1bSAlexander Aring
110971e36b1bSAlexander Aring rc = proto_register(&ieee802154_dgram_prot, 1);
111071e36b1bSAlexander Aring if (rc)
111171e36b1bSAlexander Aring goto err_dgram;
111271e36b1bSAlexander Aring
111371e36b1bSAlexander Aring /* Tell SOCKET that we are alive */
111471e36b1bSAlexander Aring rc = sock_register(&ieee802154_family_ops);
111571e36b1bSAlexander Aring if (rc)
111671e36b1bSAlexander Aring goto err_sock;
111771e36b1bSAlexander Aring dev_add_pack(&ieee802154_packet_type);
111871e36b1bSAlexander Aring
111971e36b1bSAlexander Aring rc = 0;
112071e36b1bSAlexander Aring goto out;
112171e36b1bSAlexander Aring
112271e36b1bSAlexander Aring err_sock:
112371e36b1bSAlexander Aring proto_unregister(&ieee802154_dgram_prot);
112471e36b1bSAlexander Aring err_dgram:
112571e36b1bSAlexander Aring proto_unregister(&ieee802154_raw_prot);
112671e36b1bSAlexander Aring out:
112771e36b1bSAlexander Aring return rc;
112871e36b1bSAlexander Aring }
112971e36b1bSAlexander Aring
af_ieee802154_remove(void)113071e36b1bSAlexander Aring static void __exit af_ieee802154_remove(void)
113171e36b1bSAlexander Aring {
113271e36b1bSAlexander Aring dev_remove_pack(&ieee802154_packet_type);
113371e36b1bSAlexander Aring sock_unregister(PF_IEEE802154);
113471e36b1bSAlexander Aring proto_unregister(&ieee802154_dgram_prot);
113571e36b1bSAlexander Aring proto_unregister(&ieee802154_raw_prot);
113671e36b1bSAlexander Aring }
113771e36b1bSAlexander Aring
113871e36b1bSAlexander Aring module_init(af_ieee802154_init);
113971e36b1bSAlexander Aring module_exit(af_ieee802154_remove);
114071e36b1bSAlexander Aring
114171e36b1bSAlexander Aring MODULE_LICENSE("GPL");
114271e36b1bSAlexander Aring MODULE_ALIAS_NETPROTO(PF_IEEE802154);
1143