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