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 if (dev) 4571e36b1bSAlexander Aring dev_hold(dev); 4671e36b1bSAlexander Aring rcu_read_unlock(); 4771e36b1bSAlexander Aring break; 4871e36b1bSAlexander Aring case IEEE802154_ADDR_SHORT: 4971e36b1bSAlexander Aring if (addr->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST) || 5071e36b1bSAlexander Aring addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) || 5171e36b1bSAlexander Aring addr->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) 5271e36b1bSAlexander Aring break; 5371e36b1bSAlexander Aring 5471e36b1bSAlexander Aring rtnl_lock(); 5571e36b1bSAlexander Aring 5671e36b1bSAlexander Aring for_each_netdev(net, tmp) { 5771e36b1bSAlexander Aring if (tmp->type != ARPHRD_IEEE802154) 5871e36b1bSAlexander Aring continue; 5971e36b1bSAlexander Aring 60c947f7e1SAlexander Aring pan_id = tmp->ieee802154_ptr->pan_id; 61c947f7e1SAlexander Aring short_addr = tmp->ieee802154_ptr->short_addr; 6271e36b1bSAlexander Aring if (pan_id == addr->pan_id && 6371e36b1bSAlexander Aring short_addr == addr->short_addr) { 6471e36b1bSAlexander Aring dev = tmp; 6571e36b1bSAlexander Aring dev_hold(dev); 6671e36b1bSAlexander Aring break; 6771e36b1bSAlexander Aring } 6871e36b1bSAlexander Aring } 6971e36b1bSAlexander Aring 7071e36b1bSAlexander Aring rtnl_unlock(); 7171e36b1bSAlexander Aring break; 7271e36b1bSAlexander Aring default: 7371e36b1bSAlexander Aring pr_warn("Unsupported ieee802154 address type: %d\n", 7471e36b1bSAlexander Aring addr->mode); 7571e36b1bSAlexander Aring break; 7671e36b1bSAlexander Aring } 7771e36b1bSAlexander Aring 7871e36b1bSAlexander Aring return dev; 7971e36b1bSAlexander Aring } 8071e36b1bSAlexander Aring 8171e36b1bSAlexander Aring static int ieee802154_sock_release(struct socket *sock) 8271e36b1bSAlexander Aring { 8371e36b1bSAlexander Aring struct sock *sk = sock->sk; 8471e36b1bSAlexander Aring 8571e36b1bSAlexander Aring if (sk) { 8671e36b1bSAlexander Aring sock->sk = NULL; 8771e36b1bSAlexander Aring sk->sk_prot->close(sk, 0); 8871e36b1bSAlexander Aring } 8971e36b1bSAlexander Aring return 0; 9071e36b1bSAlexander Aring } 9171e36b1bSAlexander Aring 921b784140SYing Xue static int ieee802154_sock_sendmsg(struct socket *sock, struct msghdr *msg, 931b784140SYing Xue size_t len) 9471e36b1bSAlexander Aring { 9571e36b1bSAlexander Aring struct sock *sk = sock->sk; 9671e36b1bSAlexander Aring 971b784140SYing Xue return sk->sk_prot->sendmsg(sk, msg, len); 9871e36b1bSAlexander Aring } 9971e36b1bSAlexander Aring 10071e36b1bSAlexander Aring static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr, 10171e36b1bSAlexander Aring int addr_len) 10271e36b1bSAlexander Aring { 10371e36b1bSAlexander Aring struct sock *sk = sock->sk; 10471e36b1bSAlexander Aring 10571e36b1bSAlexander Aring if (sk->sk_prot->bind) 10671e36b1bSAlexander Aring return sk->sk_prot->bind(sk, uaddr, addr_len); 10771e36b1bSAlexander Aring 10871e36b1bSAlexander Aring return sock_no_bind(sock, uaddr, addr_len); 10971e36b1bSAlexander Aring } 11071e36b1bSAlexander Aring 11171e36b1bSAlexander Aring static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr, 11271e36b1bSAlexander Aring int addr_len, int flags) 11371e36b1bSAlexander Aring { 11471e36b1bSAlexander Aring struct sock *sk = sock->sk; 11571e36b1bSAlexander Aring 11671e36b1bSAlexander Aring if (addr_len < sizeof(uaddr->sa_family)) 11771e36b1bSAlexander Aring return -EINVAL; 11871e36b1bSAlexander Aring 11971e36b1bSAlexander Aring if (uaddr->sa_family == AF_UNSPEC) 12071e36b1bSAlexander Aring return sk->sk_prot->disconnect(sk, flags); 12171e36b1bSAlexander Aring 12271e36b1bSAlexander Aring return sk->sk_prot->connect(sk, uaddr, addr_len); 12371e36b1bSAlexander Aring } 12471e36b1bSAlexander Aring 12571e36b1bSAlexander Aring static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, 12671e36b1bSAlexander Aring unsigned int cmd) 12771e36b1bSAlexander Aring { 12871e36b1bSAlexander Aring struct ifreq ifr; 12971e36b1bSAlexander Aring int ret = -ENOIOCTLCMD; 13071e36b1bSAlexander Aring struct net_device *dev; 13171e36b1bSAlexander Aring 13271e36b1bSAlexander Aring if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) 13371e36b1bSAlexander Aring return -EFAULT; 13471e36b1bSAlexander Aring 13571e36b1bSAlexander Aring ifr.ifr_name[IFNAMSIZ-1] = 0; 13671e36b1bSAlexander Aring 13771e36b1bSAlexander Aring dev_load(sock_net(sk), ifr.ifr_name); 13871e36b1bSAlexander Aring dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); 13971e36b1bSAlexander Aring 14071e36b1bSAlexander Aring if (!dev) 14171e36b1bSAlexander Aring return -ENODEV; 14271e36b1bSAlexander Aring 14371e36b1bSAlexander Aring if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl) 14471e36b1bSAlexander Aring ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); 14571e36b1bSAlexander Aring 14671e36b1bSAlexander Aring if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) 14771e36b1bSAlexander Aring ret = -EFAULT; 14871e36b1bSAlexander Aring dev_put(dev); 14971e36b1bSAlexander Aring 15071e36b1bSAlexander Aring return ret; 15171e36b1bSAlexander Aring } 15271e36b1bSAlexander Aring 15371e36b1bSAlexander Aring static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd, 15471e36b1bSAlexander Aring unsigned long arg) 15571e36b1bSAlexander Aring { 15671e36b1bSAlexander Aring struct sock *sk = sock->sk; 15771e36b1bSAlexander Aring 15871e36b1bSAlexander Aring switch (cmd) { 15971e36b1bSAlexander Aring case SIOCGIFADDR: 16071e36b1bSAlexander Aring case SIOCSIFADDR: 16171e36b1bSAlexander Aring return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg, 16271e36b1bSAlexander Aring cmd); 16371e36b1bSAlexander Aring default: 16471e36b1bSAlexander Aring if (!sk->sk_prot->ioctl) 16571e36b1bSAlexander Aring return -ENOIOCTLCMD; 16671e36b1bSAlexander Aring return sk->sk_prot->ioctl(sk, cmd, arg); 16771e36b1bSAlexander Aring } 16871e36b1bSAlexander Aring } 16971e36b1bSAlexander Aring 17071e36b1bSAlexander Aring /* RAW Sockets (802.15.4 created in userspace) */ 17171e36b1bSAlexander Aring static HLIST_HEAD(raw_head); 17271e36b1bSAlexander Aring static DEFINE_RWLOCK(raw_lock); 17371e36b1bSAlexander Aring 174086c653fSCraig Gallek static int raw_hash(struct sock *sk) 17571e36b1bSAlexander Aring { 17671e36b1bSAlexander Aring write_lock_bh(&raw_lock); 17771e36b1bSAlexander Aring sk_add_node(sk, &raw_head); 17871e36b1bSAlexander Aring sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); 17971e36b1bSAlexander Aring write_unlock_bh(&raw_lock); 180086c653fSCraig Gallek 181086c653fSCraig Gallek return 0; 18271e36b1bSAlexander Aring } 18371e36b1bSAlexander Aring 18471e36b1bSAlexander Aring static void raw_unhash(struct sock *sk) 18571e36b1bSAlexander Aring { 18671e36b1bSAlexander Aring write_lock_bh(&raw_lock); 18771e36b1bSAlexander Aring if (sk_del_node_init(sk)) 18871e36b1bSAlexander Aring sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); 18971e36b1bSAlexander Aring write_unlock_bh(&raw_lock); 19071e36b1bSAlexander Aring } 19171e36b1bSAlexander Aring 19271e36b1bSAlexander Aring static void raw_close(struct sock *sk, long timeout) 19371e36b1bSAlexander Aring { 19471e36b1bSAlexander Aring sk_common_release(sk); 19571e36b1bSAlexander Aring } 19671e36b1bSAlexander Aring 19771e36b1bSAlexander Aring static int raw_bind(struct sock *sk, struct sockaddr *_uaddr, int len) 19871e36b1bSAlexander Aring { 19971e36b1bSAlexander Aring struct ieee802154_addr addr; 20071e36b1bSAlexander Aring struct sockaddr_ieee802154 *uaddr = (struct sockaddr_ieee802154 *)_uaddr; 20171e36b1bSAlexander Aring int err = 0; 20271e36b1bSAlexander Aring struct net_device *dev = NULL; 20371e36b1bSAlexander Aring 20471e36b1bSAlexander Aring if (len < sizeof(*uaddr)) 20571e36b1bSAlexander Aring return -EINVAL; 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 } 27571e36b1bSAlexander Aring 27671e36b1bSAlexander Aring hlen = LL_RESERVED_SPACE(dev); 27771e36b1bSAlexander Aring tlen = dev->needed_tailroom; 27871e36b1bSAlexander Aring skb = sock_alloc_send_skb(sk, hlen + tlen + size, 27971e36b1bSAlexander Aring msg->msg_flags & MSG_DONTWAIT, &err); 28071e36b1bSAlexander Aring if (!skb) 28171e36b1bSAlexander Aring goto out_dev; 28271e36b1bSAlexander Aring 28371e36b1bSAlexander Aring skb_reserve(skb, hlen); 28471e36b1bSAlexander Aring 28571e36b1bSAlexander Aring skb_reset_mac_header(skb); 28671e36b1bSAlexander Aring skb_reset_network_header(skb); 28771e36b1bSAlexander Aring 28871e36b1bSAlexander Aring err = memcpy_from_msg(skb_put(skb, size), msg, size); 28971e36b1bSAlexander Aring if (err < 0) 29071e36b1bSAlexander Aring goto out_skb; 29171e36b1bSAlexander Aring 29271e36b1bSAlexander Aring skb->dev = dev; 29371e36b1bSAlexander Aring skb->protocol = htons(ETH_P_IEEE802154); 29471e36b1bSAlexander Aring 29571e36b1bSAlexander Aring err = dev_queue_xmit(skb); 29671e36b1bSAlexander Aring if (err > 0) 29771e36b1bSAlexander Aring err = net_xmit_errno(err); 29871e36b1bSAlexander Aring 299a611c58bSLin Zhang dev_put(dev); 300a611c58bSLin Zhang 30171e36b1bSAlexander Aring return err ?: size; 30271e36b1bSAlexander Aring 30371e36b1bSAlexander Aring out_skb: 30471e36b1bSAlexander Aring kfree_skb(skb); 30571e36b1bSAlexander Aring out_dev: 30671e36b1bSAlexander Aring dev_put(dev); 30771e36b1bSAlexander Aring out: 30871e36b1bSAlexander Aring return err; 30971e36b1bSAlexander Aring } 31071e36b1bSAlexander Aring 3111b784140SYing Xue static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, 3121b784140SYing Xue int noblock, int flags, int *addr_len) 31371e36b1bSAlexander Aring { 31471e36b1bSAlexander Aring size_t copied = 0; 31571e36b1bSAlexander Aring int err = -EOPNOTSUPP; 31671e36b1bSAlexander Aring struct sk_buff *skb; 31771e36b1bSAlexander Aring 31871e36b1bSAlexander Aring skb = skb_recv_datagram(sk, flags, noblock, &err); 31971e36b1bSAlexander Aring if (!skb) 32071e36b1bSAlexander Aring goto out; 32171e36b1bSAlexander Aring 32271e36b1bSAlexander Aring copied = skb->len; 32371e36b1bSAlexander Aring if (len < copied) { 32471e36b1bSAlexander Aring msg->msg_flags |= MSG_TRUNC; 32571e36b1bSAlexander Aring copied = len; 32671e36b1bSAlexander Aring } 32771e36b1bSAlexander Aring 32871e36b1bSAlexander Aring err = skb_copy_datagram_msg(skb, 0, msg, copied); 32971e36b1bSAlexander Aring if (err) 33071e36b1bSAlexander Aring goto done; 33171e36b1bSAlexander Aring 33271e36b1bSAlexander Aring sock_recv_ts_and_drops(msg, sk, skb); 33371e36b1bSAlexander Aring 33471e36b1bSAlexander Aring if (flags & MSG_TRUNC) 33571e36b1bSAlexander Aring copied = skb->len; 33671e36b1bSAlexander Aring done: 33771e36b1bSAlexander Aring skb_free_datagram(sk, skb); 33871e36b1bSAlexander Aring out: 33971e36b1bSAlexander Aring if (err) 34071e36b1bSAlexander Aring return err; 34171e36b1bSAlexander Aring return copied; 34271e36b1bSAlexander Aring } 34371e36b1bSAlexander Aring 34471e36b1bSAlexander Aring static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) 34571e36b1bSAlexander Aring { 34671e36b1bSAlexander Aring skb = skb_share_check(skb, GFP_ATOMIC); 34771e36b1bSAlexander Aring if (!skb) 34871e36b1bSAlexander Aring return NET_RX_DROP; 34971e36b1bSAlexander Aring 35071e36b1bSAlexander Aring if (sock_queue_rcv_skb(sk, skb) < 0) { 35171e36b1bSAlexander Aring kfree_skb(skb); 35271e36b1bSAlexander Aring return NET_RX_DROP; 35371e36b1bSAlexander Aring } 35471e36b1bSAlexander Aring 35571e36b1bSAlexander Aring return NET_RX_SUCCESS; 35671e36b1bSAlexander Aring } 35771e36b1bSAlexander Aring 35871e36b1bSAlexander Aring static void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb) 35971e36b1bSAlexander Aring { 36071e36b1bSAlexander Aring struct sock *sk; 36171e36b1bSAlexander Aring 36271e36b1bSAlexander Aring read_lock(&raw_lock); 36371e36b1bSAlexander Aring sk_for_each(sk, &raw_head) { 36471e36b1bSAlexander Aring bh_lock_sock(sk); 36571e36b1bSAlexander Aring if (!sk->sk_bound_dev_if || 36671e36b1bSAlexander Aring sk->sk_bound_dev_if == dev->ifindex) { 36771e36b1bSAlexander Aring struct sk_buff *clone; 36871e36b1bSAlexander Aring 36971e36b1bSAlexander Aring clone = skb_clone(skb, GFP_ATOMIC); 37071e36b1bSAlexander Aring if (clone) 37171e36b1bSAlexander Aring raw_rcv_skb(sk, clone); 37271e36b1bSAlexander Aring } 37371e36b1bSAlexander Aring bh_unlock_sock(sk); 37471e36b1bSAlexander Aring } 37571e36b1bSAlexander Aring read_unlock(&raw_lock); 37671e36b1bSAlexander Aring } 37771e36b1bSAlexander Aring 37871e36b1bSAlexander Aring static int raw_getsockopt(struct sock *sk, int level, int optname, 37971e36b1bSAlexander Aring char __user *optval, int __user *optlen) 38071e36b1bSAlexander Aring { 38171e36b1bSAlexander Aring return -EOPNOTSUPP; 38271e36b1bSAlexander Aring } 38371e36b1bSAlexander Aring 38471e36b1bSAlexander Aring static int raw_setsockopt(struct sock *sk, int level, int optname, 38571e36b1bSAlexander Aring char __user *optval, unsigned int optlen) 38671e36b1bSAlexander Aring { 38771e36b1bSAlexander Aring return -EOPNOTSUPP; 38871e36b1bSAlexander Aring } 38971e36b1bSAlexander Aring 39071e36b1bSAlexander Aring static struct proto ieee802154_raw_prot = { 39171e36b1bSAlexander Aring .name = "IEEE-802.15.4-RAW", 39271e36b1bSAlexander Aring .owner = THIS_MODULE, 39371e36b1bSAlexander Aring .obj_size = sizeof(struct sock), 39471e36b1bSAlexander Aring .close = raw_close, 39571e36b1bSAlexander Aring .bind = raw_bind, 39671e36b1bSAlexander Aring .sendmsg = raw_sendmsg, 39771e36b1bSAlexander Aring .recvmsg = raw_recvmsg, 39871e36b1bSAlexander Aring .hash = raw_hash, 39971e36b1bSAlexander Aring .unhash = raw_unhash, 40071e36b1bSAlexander Aring .connect = raw_connect, 40171e36b1bSAlexander Aring .disconnect = raw_disconnect, 40271e36b1bSAlexander Aring .getsockopt = raw_getsockopt, 40371e36b1bSAlexander Aring .setsockopt = raw_setsockopt, 40471e36b1bSAlexander Aring }; 40571e36b1bSAlexander Aring 40671e36b1bSAlexander Aring static const struct proto_ops ieee802154_raw_ops = { 40771e36b1bSAlexander Aring .family = PF_IEEE802154, 40871e36b1bSAlexander Aring .owner = THIS_MODULE, 40971e36b1bSAlexander Aring .release = ieee802154_sock_release, 41071e36b1bSAlexander Aring .bind = ieee802154_sock_bind, 41171e36b1bSAlexander Aring .connect = ieee802154_sock_connect, 41271e36b1bSAlexander Aring .socketpair = sock_no_socketpair, 41371e36b1bSAlexander Aring .accept = sock_no_accept, 41471e36b1bSAlexander Aring .getname = sock_no_getname, 415a11e1d43SLinus Torvalds .poll = datagram_poll, 41671e36b1bSAlexander Aring .ioctl = ieee802154_sock_ioctl, 417c7cbdbf2SArnd Bergmann .gettstamp = sock_gettstamp, 41871e36b1bSAlexander Aring .listen = sock_no_listen, 41971e36b1bSAlexander Aring .shutdown = sock_no_shutdown, 42071e36b1bSAlexander Aring .setsockopt = sock_common_setsockopt, 42171e36b1bSAlexander Aring .getsockopt = sock_common_getsockopt, 42271e36b1bSAlexander Aring .sendmsg = ieee802154_sock_sendmsg, 42371e36b1bSAlexander Aring .recvmsg = sock_common_recvmsg, 42471e36b1bSAlexander Aring .mmap = sock_no_mmap, 42571e36b1bSAlexander Aring .sendpage = sock_no_sendpage, 42671e36b1bSAlexander Aring #ifdef CONFIG_COMPAT 42771e36b1bSAlexander Aring .compat_setsockopt = compat_sock_common_setsockopt, 42871e36b1bSAlexander Aring .compat_getsockopt = compat_sock_common_getsockopt, 42971e36b1bSAlexander Aring #endif 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 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); 46271e36b1bSAlexander Aring write_unlock_bh(&dgram_lock); 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 50171e36b1bSAlexander Aring if (len < sizeof(*addr)) 50271e36b1bSAlexander Aring goto out; 50371e36b1bSAlexander Aring 50471e36b1bSAlexander Aring if (addr->family != AF_IEEE802154) 50571e36b1bSAlexander Aring goto out; 50671e36b1bSAlexander Aring 50771e36b1bSAlexander Aring ieee802154_addr_from_sa(&haddr, &addr->addr); 50871e36b1bSAlexander Aring dev = ieee802154_get_dev(sock_net(sk), &haddr); 50971e36b1bSAlexander Aring if (!dev) { 51071e36b1bSAlexander Aring err = -ENODEV; 51171e36b1bSAlexander Aring goto out; 51271e36b1bSAlexander Aring } 51371e36b1bSAlexander Aring 51471e36b1bSAlexander Aring if (dev->type != ARPHRD_IEEE802154) { 51571e36b1bSAlexander Aring err = -ENODEV; 51671e36b1bSAlexander Aring goto out_put; 51771e36b1bSAlexander Aring } 51871e36b1bSAlexander Aring 51971e36b1bSAlexander Aring ro->src_addr = haddr; 52071e36b1bSAlexander Aring 52171e36b1bSAlexander Aring ro->bound = 1; 52271e36b1bSAlexander Aring err = 0; 52371e36b1bSAlexander Aring out_put: 52471e36b1bSAlexander Aring dev_put(dev); 52571e36b1bSAlexander Aring out: 52671e36b1bSAlexander Aring release_sock(sk); 52771e36b1bSAlexander Aring 52871e36b1bSAlexander Aring return err; 52971e36b1bSAlexander Aring } 53071e36b1bSAlexander Aring 53171e36b1bSAlexander Aring static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) 53271e36b1bSAlexander Aring { 53371e36b1bSAlexander Aring switch (cmd) { 53471e36b1bSAlexander Aring case SIOCOUTQ: 53571e36b1bSAlexander Aring { 53671e36b1bSAlexander Aring int amount = sk_wmem_alloc_get(sk); 53771e36b1bSAlexander Aring 53871e36b1bSAlexander Aring return put_user(amount, (int __user *)arg); 53971e36b1bSAlexander Aring } 54071e36b1bSAlexander Aring 54171e36b1bSAlexander Aring case SIOCINQ: 54271e36b1bSAlexander Aring { 54371e36b1bSAlexander Aring struct sk_buff *skb; 54471e36b1bSAlexander Aring unsigned long amount; 54571e36b1bSAlexander Aring 54671e36b1bSAlexander Aring amount = 0; 54771e36b1bSAlexander Aring spin_lock_bh(&sk->sk_receive_queue.lock); 54871e36b1bSAlexander Aring skb = skb_peek(&sk->sk_receive_queue); 54971e36b1bSAlexander Aring if (skb) { 55071e36b1bSAlexander Aring /* We will only return the amount 55171e36b1bSAlexander Aring * of this packet since that is all 55271e36b1bSAlexander Aring * that will be read. 55371e36b1bSAlexander Aring */ 55471e36b1bSAlexander Aring amount = skb->len - ieee802154_hdr_length(skb); 55571e36b1bSAlexander Aring } 55671e36b1bSAlexander Aring spin_unlock_bh(&sk->sk_receive_queue.lock); 55771e36b1bSAlexander Aring return put_user(amount, (int __user *)arg); 55871e36b1bSAlexander Aring } 55971e36b1bSAlexander Aring } 56071e36b1bSAlexander Aring 56171e36b1bSAlexander Aring return -ENOIOCTLCMD; 56271e36b1bSAlexander Aring } 56371e36b1bSAlexander Aring 56471e36b1bSAlexander Aring /* FIXME: autobind */ 56571e36b1bSAlexander Aring static int dgram_connect(struct sock *sk, struct sockaddr *uaddr, 56671e36b1bSAlexander Aring int len) 56771e36b1bSAlexander Aring { 56871e36b1bSAlexander Aring struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; 56971e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 57071e36b1bSAlexander Aring int err = 0; 57171e36b1bSAlexander Aring 57271e36b1bSAlexander Aring if (len < sizeof(*addr)) 57371e36b1bSAlexander Aring return -EINVAL; 57471e36b1bSAlexander Aring 57571e36b1bSAlexander Aring if (addr->family != AF_IEEE802154) 57671e36b1bSAlexander Aring return -EINVAL; 57771e36b1bSAlexander Aring 57871e36b1bSAlexander Aring lock_sock(sk); 57971e36b1bSAlexander Aring 58071e36b1bSAlexander Aring if (!ro->bound) { 58171e36b1bSAlexander Aring err = -ENETUNREACH; 58271e36b1bSAlexander Aring goto out; 58371e36b1bSAlexander Aring } 58471e36b1bSAlexander Aring 58571e36b1bSAlexander Aring ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr); 58671e36b1bSAlexander Aring ro->connected = 1; 58771e36b1bSAlexander Aring 58871e36b1bSAlexander Aring out: 58971e36b1bSAlexander Aring release_sock(sk); 59071e36b1bSAlexander Aring return err; 59171e36b1bSAlexander Aring } 59271e36b1bSAlexander Aring 59371e36b1bSAlexander Aring static int dgram_disconnect(struct sock *sk, int flags) 59471e36b1bSAlexander Aring { 59571e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 59671e36b1bSAlexander Aring 59771e36b1bSAlexander Aring lock_sock(sk); 59871e36b1bSAlexander Aring ro->connected = 0; 59971e36b1bSAlexander Aring release_sock(sk); 60071e36b1bSAlexander Aring 60171e36b1bSAlexander Aring return 0; 60271e36b1bSAlexander Aring } 60371e36b1bSAlexander Aring 6041b784140SYing Xue static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) 60571e36b1bSAlexander Aring { 60671e36b1bSAlexander Aring struct net_device *dev; 60771e36b1bSAlexander Aring unsigned int mtu; 60871e36b1bSAlexander Aring struct sk_buff *skb; 60971e36b1bSAlexander Aring struct ieee802154_mac_cb *cb; 61071e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 61171e36b1bSAlexander Aring struct ieee802154_addr dst_addr; 61271e36b1bSAlexander Aring int hlen, tlen; 61371e36b1bSAlexander Aring int err; 61471e36b1bSAlexander Aring 61571e36b1bSAlexander Aring if (msg->msg_flags & MSG_OOB) { 61671e36b1bSAlexander Aring pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags); 61771e36b1bSAlexander Aring return -EOPNOTSUPP; 61871e36b1bSAlexander Aring } 61971e36b1bSAlexander Aring 62071e36b1bSAlexander Aring if (!ro->connected && !msg->msg_name) 62171e36b1bSAlexander Aring return -EDESTADDRREQ; 62271e36b1bSAlexander Aring else if (ro->connected && msg->msg_name) 62371e36b1bSAlexander Aring return -EISCONN; 62471e36b1bSAlexander Aring 62571e36b1bSAlexander Aring if (!ro->bound) 62671e36b1bSAlexander Aring dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); 62771e36b1bSAlexander Aring else 62871e36b1bSAlexander Aring dev = ieee802154_get_dev(sock_net(sk), &ro->src_addr); 62971e36b1bSAlexander Aring 63071e36b1bSAlexander Aring if (!dev) { 63171e36b1bSAlexander Aring pr_debug("no dev\n"); 63271e36b1bSAlexander Aring err = -ENXIO; 63371e36b1bSAlexander Aring goto out; 63471e36b1bSAlexander Aring } 635b40988c4SAlexander Aring mtu = IEEE802154_MTU; 63671e36b1bSAlexander Aring pr_debug("name = %s, mtu = %u\n", dev->name, mtu); 63771e36b1bSAlexander Aring 63871e36b1bSAlexander Aring if (size > mtu) { 6395b5e0928SAlexey Dobriyan pr_debug("size = %zu, mtu = %u\n", size, mtu); 64071e36b1bSAlexander Aring err = -EMSGSIZE; 64171e36b1bSAlexander Aring goto out_dev; 64271e36b1bSAlexander Aring } 64371e36b1bSAlexander Aring 64471e36b1bSAlexander Aring hlen = LL_RESERVED_SPACE(dev); 64571e36b1bSAlexander Aring tlen = dev->needed_tailroom; 64671e36b1bSAlexander Aring skb = sock_alloc_send_skb(sk, hlen + tlen + size, 64771e36b1bSAlexander Aring msg->msg_flags & MSG_DONTWAIT, 64871e36b1bSAlexander Aring &err); 64971e36b1bSAlexander Aring if (!skb) 65071e36b1bSAlexander Aring goto out_dev; 65171e36b1bSAlexander Aring 65271e36b1bSAlexander Aring skb_reserve(skb, hlen); 65371e36b1bSAlexander Aring 65471e36b1bSAlexander Aring skb_reset_network_header(skb); 65571e36b1bSAlexander Aring 65671e36b1bSAlexander Aring cb = mac_cb_init(skb); 65771e36b1bSAlexander Aring cb->type = IEEE802154_FC_TYPE_DATA; 65871e36b1bSAlexander Aring cb->ackreq = ro->want_ack; 65971e36b1bSAlexander Aring 66071e36b1bSAlexander Aring if (msg->msg_name) { 66171e36b1bSAlexander Aring DECLARE_SOCKADDR(struct sockaddr_ieee802154*, 66271e36b1bSAlexander Aring daddr, msg->msg_name); 66371e36b1bSAlexander Aring 66471e36b1bSAlexander Aring ieee802154_addr_from_sa(&dst_addr, &daddr->addr); 66571e36b1bSAlexander Aring } else { 66671e36b1bSAlexander Aring dst_addr = ro->dst_addr; 66771e36b1bSAlexander Aring } 66871e36b1bSAlexander Aring 66971e36b1bSAlexander Aring cb->secen = ro->secen; 67071e36b1bSAlexander Aring cb->secen_override = ro->secen_override; 67171e36b1bSAlexander Aring cb->seclevel = ro->seclevel; 67271e36b1bSAlexander Aring cb->seclevel_override = ro->seclevel_override; 67371e36b1bSAlexander Aring 674838b83d6SAlexander Aring err = wpan_dev_hard_header(skb, dev, &dst_addr, 67571e36b1bSAlexander Aring ro->bound ? &ro->src_addr : NULL, size); 67671e36b1bSAlexander Aring if (err < 0) 67771e36b1bSAlexander Aring goto out_skb; 67871e36b1bSAlexander Aring 67971e36b1bSAlexander Aring err = memcpy_from_msg(skb_put(skb, size), msg, size); 68071e36b1bSAlexander Aring if (err < 0) 68171e36b1bSAlexander Aring goto out_skb; 68271e36b1bSAlexander Aring 68371e36b1bSAlexander Aring skb->dev = dev; 68471e36b1bSAlexander Aring skb->protocol = htons(ETH_P_IEEE802154); 68571e36b1bSAlexander Aring 68671e36b1bSAlexander Aring err = dev_queue_xmit(skb); 68771e36b1bSAlexander Aring if (err > 0) 68871e36b1bSAlexander Aring err = net_xmit_errno(err); 68971e36b1bSAlexander Aring 690a611c58bSLin Zhang dev_put(dev); 691a611c58bSLin Zhang 69271e36b1bSAlexander Aring return err ?: size; 69371e36b1bSAlexander Aring 69471e36b1bSAlexander Aring out_skb: 69571e36b1bSAlexander Aring kfree_skb(skb); 69671e36b1bSAlexander Aring out_dev: 69771e36b1bSAlexander Aring dev_put(dev); 69871e36b1bSAlexander Aring out: 69971e36b1bSAlexander Aring return err; 70071e36b1bSAlexander Aring } 70171e36b1bSAlexander Aring 7021b784140SYing Xue static int dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, 7031b784140SYing Xue int noblock, int flags, int *addr_len) 70471e36b1bSAlexander Aring { 70571e36b1bSAlexander Aring size_t copied = 0; 70671e36b1bSAlexander Aring int err = -EOPNOTSUPP; 70771e36b1bSAlexander Aring struct sk_buff *skb; 708811e299fSRomuald CARI struct dgram_sock *ro = dgram_sk(sk); 70971e36b1bSAlexander Aring DECLARE_SOCKADDR(struct sockaddr_ieee802154 *, saddr, msg->msg_name); 71071e36b1bSAlexander Aring 71171e36b1bSAlexander Aring skb = skb_recv_datagram(sk, flags, noblock, &err); 71271e36b1bSAlexander Aring if (!skb) 71371e36b1bSAlexander Aring goto out; 71471e36b1bSAlexander Aring 71571e36b1bSAlexander Aring copied = skb->len; 71671e36b1bSAlexander Aring if (len < copied) { 71771e36b1bSAlexander Aring msg->msg_flags |= MSG_TRUNC; 71871e36b1bSAlexander Aring copied = len; 71971e36b1bSAlexander Aring } 72071e36b1bSAlexander Aring 72171e36b1bSAlexander Aring /* FIXME: skip headers if necessary ?! */ 72271e36b1bSAlexander Aring err = skb_copy_datagram_msg(skb, 0, msg, copied); 72371e36b1bSAlexander Aring if (err) 72471e36b1bSAlexander Aring goto done; 72571e36b1bSAlexander Aring 72671e36b1bSAlexander Aring sock_recv_ts_and_drops(msg, sk, skb); 72771e36b1bSAlexander Aring 72871e36b1bSAlexander Aring if (saddr) { 7298a70cefaSLennert Buytenhek /* Clear the implicit padding in struct sockaddr_ieee802154 7308a70cefaSLennert Buytenhek * (16 bits between 'family' and 'addr') and in struct 7318a70cefaSLennert Buytenhek * ieee802154_addr_sa (16 bits at the end of the structure). 7328a70cefaSLennert Buytenhek */ 7338a70cefaSLennert Buytenhek memset(saddr, 0, sizeof(*saddr)); 7348a70cefaSLennert Buytenhek 73571e36b1bSAlexander Aring saddr->family = AF_IEEE802154; 73671e36b1bSAlexander Aring ieee802154_addr_to_sa(&saddr->addr, &mac_cb(skb)->source); 73771e36b1bSAlexander Aring *addr_len = sizeof(*saddr); 73871e36b1bSAlexander Aring } 73971e36b1bSAlexander Aring 740811e299fSRomuald CARI if (ro->want_lqi) { 741811e299fSRomuald CARI err = put_cmsg(msg, SOL_IEEE802154, WPAN_WANTLQI, 742811e299fSRomuald CARI sizeof(uint8_t), &(mac_cb(skb)->lqi)); 743811e299fSRomuald CARI if (err) 744811e299fSRomuald CARI goto done; 745811e299fSRomuald CARI } 746811e299fSRomuald CARI 74771e36b1bSAlexander Aring if (flags & MSG_TRUNC) 74871e36b1bSAlexander Aring copied = skb->len; 74971e36b1bSAlexander Aring done: 75071e36b1bSAlexander Aring skb_free_datagram(sk, skb); 75171e36b1bSAlexander Aring out: 75271e36b1bSAlexander Aring if (err) 75371e36b1bSAlexander Aring return err; 75471e36b1bSAlexander Aring return copied; 75571e36b1bSAlexander Aring } 75671e36b1bSAlexander Aring 75771e36b1bSAlexander Aring static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb) 75871e36b1bSAlexander Aring { 75971e36b1bSAlexander Aring skb = skb_share_check(skb, GFP_ATOMIC); 76071e36b1bSAlexander Aring if (!skb) 76171e36b1bSAlexander Aring return NET_RX_DROP; 76271e36b1bSAlexander Aring 76371e36b1bSAlexander Aring if (sock_queue_rcv_skb(sk, skb) < 0) { 76471e36b1bSAlexander Aring kfree_skb(skb); 76571e36b1bSAlexander Aring return NET_RX_DROP; 76671e36b1bSAlexander Aring } 76771e36b1bSAlexander Aring 76871e36b1bSAlexander Aring return NET_RX_SUCCESS; 76971e36b1bSAlexander Aring } 77071e36b1bSAlexander Aring 77171e36b1bSAlexander Aring static inline bool 77271e36b1bSAlexander Aring ieee802154_match_sock(__le64 hw_addr, __le16 pan_id, __le16 short_addr, 77371e36b1bSAlexander Aring struct dgram_sock *ro) 77471e36b1bSAlexander Aring { 77571e36b1bSAlexander Aring if (!ro->bound) 77671e36b1bSAlexander Aring return true; 77771e36b1bSAlexander Aring 77871e36b1bSAlexander Aring if (ro->src_addr.mode == IEEE802154_ADDR_LONG && 77971e36b1bSAlexander Aring hw_addr == ro->src_addr.extended_addr) 78071e36b1bSAlexander Aring return true; 78171e36b1bSAlexander Aring 78271e36b1bSAlexander Aring if (ro->src_addr.mode == IEEE802154_ADDR_SHORT && 78371e36b1bSAlexander Aring pan_id == ro->src_addr.pan_id && 78471e36b1bSAlexander Aring short_addr == ro->src_addr.short_addr) 78571e36b1bSAlexander Aring return true; 78671e36b1bSAlexander Aring 78771e36b1bSAlexander Aring return false; 78871e36b1bSAlexander Aring } 78971e36b1bSAlexander Aring 79071e36b1bSAlexander Aring static int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) 79171e36b1bSAlexander Aring { 79271e36b1bSAlexander Aring struct sock *sk, *prev = NULL; 79371e36b1bSAlexander Aring int ret = NET_RX_SUCCESS; 79471e36b1bSAlexander Aring __le16 pan_id, short_addr; 79571e36b1bSAlexander Aring __le64 hw_addr; 79671e36b1bSAlexander Aring 79771e36b1bSAlexander Aring /* Data frame processing */ 79871e36b1bSAlexander Aring BUG_ON(dev->type != ARPHRD_IEEE802154); 79971e36b1bSAlexander Aring 800c947f7e1SAlexander Aring pan_id = dev->ieee802154_ptr->pan_id; 801c947f7e1SAlexander Aring short_addr = dev->ieee802154_ptr->short_addr; 802c947f7e1SAlexander Aring hw_addr = dev->ieee802154_ptr->extended_addr; 80371e36b1bSAlexander Aring 80471e36b1bSAlexander Aring read_lock(&dgram_lock); 80571e36b1bSAlexander Aring sk_for_each(sk, &dgram_head) { 80671e36b1bSAlexander Aring if (ieee802154_match_sock(hw_addr, pan_id, short_addr, 80771e36b1bSAlexander Aring dgram_sk(sk))) { 80871e36b1bSAlexander Aring if (prev) { 80971e36b1bSAlexander Aring struct sk_buff *clone; 81071e36b1bSAlexander Aring 81171e36b1bSAlexander Aring clone = skb_clone(skb, GFP_ATOMIC); 81271e36b1bSAlexander Aring if (clone) 81371e36b1bSAlexander Aring dgram_rcv_skb(prev, clone); 81471e36b1bSAlexander Aring } 81571e36b1bSAlexander Aring 81671e36b1bSAlexander Aring prev = sk; 81771e36b1bSAlexander Aring } 81871e36b1bSAlexander Aring } 81971e36b1bSAlexander Aring 82071e36b1bSAlexander Aring if (prev) { 82171e36b1bSAlexander Aring dgram_rcv_skb(prev, skb); 82271e36b1bSAlexander Aring } else { 82371e36b1bSAlexander Aring kfree_skb(skb); 82471e36b1bSAlexander Aring ret = NET_RX_DROP; 82571e36b1bSAlexander Aring } 82671e36b1bSAlexander Aring read_unlock(&dgram_lock); 82771e36b1bSAlexander Aring 82871e36b1bSAlexander Aring return ret; 82971e36b1bSAlexander Aring } 83071e36b1bSAlexander Aring 83171e36b1bSAlexander Aring static int dgram_getsockopt(struct sock *sk, int level, int optname, 83271e36b1bSAlexander Aring char __user *optval, int __user *optlen) 83371e36b1bSAlexander Aring { 83471e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 83571e36b1bSAlexander Aring 83671e36b1bSAlexander Aring int val, len; 83771e36b1bSAlexander Aring 83871e36b1bSAlexander Aring if (level != SOL_IEEE802154) 83971e36b1bSAlexander Aring return -EOPNOTSUPP; 84071e36b1bSAlexander Aring 84171e36b1bSAlexander Aring if (get_user(len, optlen)) 84271e36b1bSAlexander Aring return -EFAULT; 84371e36b1bSAlexander Aring 84471e36b1bSAlexander Aring len = min_t(unsigned int, len, sizeof(int)); 84571e36b1bSAlexander Aring 84671e36b1bSAlexander Aring switch (optname) { 84771e36b1bSAlexander Aring case WPAN_WANTACK: 84871e36b1bSAlexander Aring val = ro->want_ack; 84971e36b1bSAlexander Aring break; 850811e299fSRomuald CARI case WPAN_WANTLQI: 851811e299fSRomuald CARI val = ro->want_lqi; 852811e299fSRomuald CARI break; 85371e36b1bSAlexander Aring case WPAN_SECURITY: 85471e36b1bSAlexander Aring if (!ro->secen_override) 85571e36b1bSAlexander Aring val = WPAN_SECURITY_DEFAULT; 85671e36b1bSAlexander Aring else if (ro->secen) 85771e36b1bSAlexander Aring val = WPAN_SECURITY_ON; 85871e36b1bSAlexander Aring else 85971e36b1bSAlexander Aring val = WPAN_SECURITY_OFF; 86071e36b1bSAlexander Aring break; 86171e36b1bSAlexander Aring case WPAN_SECURITY_LEVEL: 86271e36b1bSAlexander Aring if (!ro->seclevel_override) 86371e36b1bSAlexander Aring val = WPAN_SECURITY_LEVEL_DEFAULT; 86471e36b1bSAlexander Aring else 86571e36b1bSAlexander Aring val = ro->seclevel; 86671e36b1bSAlexander Aring break; 86771e36b1bSAlexander Aring default: 86871e36b1bSAlexander Aring return -ENOPROTOOPT; 86971e36b1bSAlexander Aring } 87071e36b1bSAlexander Aring 87171e36b1bSAlexander Aring if (put_user(len, optlen)) 87271e36b1bSAlexander Aring return -EFAULT; 87371e36b1bSAlexander Aring if (copy_to_user(optval, &val, len)) 87471e36b1bSAlexander Aring return -EFAULT; 87571e36b1bSAlexander Aring return 0; 87671e36b1bSAlexander Aring } 87771e36b1bSAlexander Aring 87871e36b1bSAlexander Aring static int dgram_setsockopt(struct sock *sk, int level, int optname, 87971e36b1bSAlexander Aring char __user *optval, unsigned int optlen) 88071e36b1bSAlexander Aring { 88171e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 88271e36b1bSAlexander Aring struct net *net = sock_net(sk); 88371e36b1bSAlexander Aring int val; 88471e36b1bSAlexander Aring int err = 0; 88571e36b1bSAlexander Aring 88671e36b1bSAlexander Aring if (optlen < sizeof(int)) 88771e36b1bSAlexander Aring return -EINVAL; 88871e36b1bSAlexander Aring 88971e36b1bSAlexander Aring if (get_user(val, (int __user *)optval)) 89071e36b1bSAlexander Aring return -EFAULT; 89171e36b1bSAlexander Aring 89271e36b1bSAlexander Aring lock_sock(sk); 89371e36b1bSAlexander Aring 89471e36b1bSAlexander Aring switch (optname) { 89571e36b1bSAlexander Aring case WPAN_WANTACK: 89671e36b1bSAlexander Aring ro->want_ack = !!val; 89771e36b1bSAlexander Aring break; 898811e299fSRomuald CARI case WPAN_WANTLQI: 899811e299fSRomuald CARI ro->want_lqi = !!val; 900811e299fSRomuald CARI break; 90171e36b1bSAlexander Aring case WPAN_SECURITY: 90271e36b1bSAlexander Aring if (!ns_capable(net->user_ns, CAP_NET_ADMIN) && 90371e36b1bSAlexander Aring !ns_capable(net->user_ns, CAP_NET_RAW)) { 90471e36b1bSAlexander Aring err = -EPERM; 90571e36b1bSAlexander Aring break; 90671e36b1bSAlexander Aring } 90771e36b1bSAlexander Aring 90871e36b1bSAlexander Aring switch (val) { 90971e36b1bSAlexander Aring case WPAN_SECURITY_DEFAULT: 91071e36b1bSAlexander Aring ro->secen_override = 0; 91171e36b1bSAlexander Aring break; 91271e36b1bSAlexander Aring case WPAN_SECURITY_ON: 91371e36b1bSAlexander Aring ro->secen_override = 1; 91471e36b1bSAlexander Aring ro->secen = 1; 91571e36b1bSAlexander Aring break; 91671e36b1bSAlexander Aring case WPAN_SECURITY_OFF: 91771e36b1bSAlexander Aring ro->secen_override = 1; 91871e36b1bSAlexander Aring ro->secen = 0; 91971e36b1bSAlexander Aring break; 92071e36b1bSAlexander Aring default: 92171e36b1bSAlexander Aring err = -EINVAL; 92271e36b1bSAlexander Aring break; 92371e36b1bSAlexander Aring } 92471e36b1bSAlexander Aring break; 92571e36b1bSAlexander Aring case WPAN_SECURITY_LEVEL: 92671e36b1bSAlexander Aring if (!ns_capable(net->user_ns, CAP_NET_ADMIN) && 92771e36b1bSAlexander Aring !ns_capable(net->user_ns, CAP_NET_RAW)) { 92871e36b1bSAlexander Aring err = -EPERM; 92971e36b1bSAlexander Aring break; 93071e36b1bSAlexander Aring } 93171e36b1bSAlexander Aring 93271e36b1bSAlexander Aring if (val < WPAN_SECURITY_LEVEL_DEFAULT || 93371e36b1bSAlexander Aring val > IEEE802154_SCF_SECLEVEL_ENC_MIC128) { 93471e36b1bSAlexander Aring err = -EINVAL; 93571e36b1bSAlexander Aring } else if (val == WPAN_SECURITY_LEVEL_DEFAULT) { 93671e36b1bSAlexander Aring ro->seclevel_override = 0; 93771e36b1bSAlexander Aring } else { 93871e36b1bSAlexander Aring ro->seclevel_override = 1; 93971e36b1bSAlexander Aring ro->seclevel = val; 94071e36b1bSAlexander Aring } 94171e36b1bSAlexander Aring break; 94271e36b1bSAlexander Aring default: 94371e36b1bSAlexander Aring err = -ENOPROTOOPT; 94471e36b1bSAlexander Aring break; 94571e36b1bSAlexander Aring } 94671e36b1bSAlexander Aring 94771e36b1bSAlexander Aring release_sock(sk); 94871e36b1bSAlexander Aring return err; 94971e36b1bSAlexander Aring } 95071e36b1bSAlexander Aring 95171e36b1bSAlexander Aring static struct proto ieee802154_dgram_prot = { 95271e36b1bSAlexander Aring .name = "IEEE-802.15.4-MAC", 95371e36b1bSAlexander Aring .owner = THIS_MODULE, 95471e36b1bSAlexander Aring .obj_size = sizeof(struct dgram_sock), 95571e36b1bSAlexander Aring .init = dgram_init, 95671e36b1bSAlexander Aring .close = dgram_close, 95771e36b1bSAlexander Aring .bind = dgram_bind, 95871e36b1bSAlexander Aring .sendmsg = dgram_sendmsg, 95971e36b1bSAlexander Aring .recvmsg = dgram_recvmsg, 96071e36b1bSAlexander Aring .hash = dgram_hash, 96171e36b1bSAlexander Aring .unhash = dgram_unhash, 96271e36b1bSAlexander Aring .connect = dgram_connect, 96371e36b1bSAlexander Aring .disconnect = dgram_disconnect, 96471e36b1bSAlexander Aring .ioctl = dgram_ioctl, 96571e36b1bSAlexander Aring .getsockopt = dgram_getsockopt, 96671e36b1bSAlexander Aring .setsockopt = dgram_setsockopt, 96771e36b1bSAlexander Aring }; 96871e36b1bSAlexander Aring 96971e36b1bSAlexander Aring static const struct proto_ops ieee802154_dgram_ops = { 97071e36b1bSAlexander Aring .family = PF_IEEE802154, 97171e36b1bSAlexander Aring .owner = THIS_MODULE, 97271e36b1bSAlexander Aring .release = ieee802154_sock_release, 97371e36b1bSAlexander Aring .bind = ieee802154_sock_bind, 97471e36b1bSAlexander Aring .connect = ieee802154_sock_connect, 97571e36b1bSAlexander Aring .socketpair = sock_no_socketpair, 97671e36b1bSAlexander Aring .accept = sock_no_accept, 97771e36b1bSAlexander Aring .getname = sock_no_getname, 978a11e1d43SLinus Torvalds .poll = datagram_poll, 97971e36b1bSAlexander Aring .ioctl = ieee802154_sock_ioctl, 980c7cbdbf2SArnd Bergmann .gettstamp = sock_gettstamp, 98171e36b1bSAlexander Aring .listen = sock_no_listen, 98271e36b1bSAlexander Aring .shutdown = sock_no_shutdown, 98371e36b1bSAlexander Aring .setsockopt = sock_common_setsockopt, 98471e36b1bSAlexander Aring .getsockopt = sock_common_getsockopt, 98571e36b1bSAlexander Aring .sendmsg = ieee802154_sock_sendmsg, 98671e36b1bSAlexander Aring .recvmsg = sock_common_recvmsg, 98771e36b1bSAlexander Aring .mmap = sock_no_mmap, 98871e36b1bSAlexander Aring .sendpage = sock_no_sendpage, 98971e36b1bSAlexander Aring #ifdef CONFIG_COMPAT 99071e36b1bSAlexander Aring .compat_setsockopt = compat_sock_common_setsockopt, 99171e36b1bSAlexander Aring .compat_getsockopt = compat_sock_common_getsockopt, 99271e36b1bSAlexander Aring #endif 99371e36b1bSAlexander Aring }; 99471e36b1bSAlexander Aring 99571e36b1bSAlexander Aring /* Create a socket. Initialise the socket, blank the addresses 99671e36b1bSAlexander Aring * set the state. 99771e36b1bSAlexander Aring */ 99871e36b1bSAlexander Aring static int ieee802154_create(struct net *net, struct socket *sock, 99971e36b1bSAlexander Aring int protocol, int kern) 100071e36b1bSAlexander Aring { 100171e36b1bSAlexander Aring struct sock *sk; 100271e36b1bSAlexander Aring int rc; 100371e36b1bSAlexander Aring struct proto *proto; 100471e36b1bSAlexander Aring const struct proto_ops *ops; 100571e36b1bSAlexander Aring 100671e36b1bSAlexander Aring if (!net_eq(net, &init_net)) 100771e36b1bSAlexander Aring return -EAFNOSUPPORT; 100871e36b1bSAlexander Aring 100971e36b1bSAlexander Aring switch (sock->type) { 101071e36b1bSAlexander Aring case SOCK_RAW: 101171e36b1bSAlexander Aring proto = &ieee802154_raw_prot; 101271e36b1bSAlexander Aring ops = &ieee802154_raw_ops; 101371e36b1bSAlexander Aring break; 101471e36b1bSAlexander Aring case SOCK_DGRAM: 101571e36b1bSAlexander Aring proto = &ieee802154_dgram_prot; 101671e36b1bSAlexander Aring ops = &ieee802154_dgram_ops; 101771e36b1bSAlexander Aring break; 101871e36b1bSAlexander Aring default: 101971e36b1bSAlexander Aring rc = -ESOCKTNOSUPPORT; 102071e36b1bSAlexander Aring goto out; 102171e36b1bSAlexander Aring } 102271e36b1bSAlexander Aring 102371e36b1bSAlexander Aring rc = -ENOMEM; 102411aa9c28SEric W. Biederman sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto, kern); 102571e36b1bSAlexander Aring if (!sk) 102671e36b1bSAlexander Aring goto out; 102771e36b1bSAlexander Aring rc = 0; 102871e36b1bSAlexander Aring 102971e36b1bSAlexander Aring sock->ops = ops; 103071e36b1bSAlexander Aring 103171e36b1bSAlexander Aring sock_init_data(sock, sk); 103271e36b1bSAlexander Aring /* FIXME: sk->sk_destruct */ 103371e36b1bSAlexander Aring sk->sk_family = PF_IEEE802154; 103471e36b1bSAlexander Aring 103571e36b1bSAlexander Aring /* Checksums on by default */ 103671e36b1bSAlexander Aring sock_set_flag(sk, SOCK_ZAPPED); 103771e36b1bSAlexander Aring 1038086c653fSCraig Gallek if (sk->sk_prot->hash) { 1039086c653fSCraig Gallek rc = sk->sk_prot->hash(sk); 1040086c653fSCraig Gallek if (rc) { 1041086c653fSCraig Gallek sk_common_release(sk); 1042086c653fSCraig Gallek goto out; 1043086c653fSCraig Gallek } 1044086c653fSCraig Gallek } 104571e36b1bSAlexander Aring 104671e36b1bSAlexander Aring if (sk->sk_prot->init) { 104771e36b1bSAlexander Aring rc = sk->sk_prot->init(sk); 104871e36b1bSAlexander Aring if (rc) 104971e36b1bSAlexander Aring sk_common_release(sk); 105071e36b1bSAlexander Aring } 105171e36b1bSAlexander Aring out: 105271e36b1bSAlexander Aring return rc; 105371e36b1bSAlexander Aring } 105471e36b1bSAlexander Aring 105571e36b1bSAlexander Aring static const struct net_proto_family ieee802154_family_ops = { 105671e36b1bSAlexander Aring .family = PF_IEEE802154, 105771e36b1bSAlexander Aring .create = ieee802154_create, 105871e36b1bSAlexander Aring .owner = THIS_MODULE, 105971e36b1bSAlexander Aring }; 106071e36b1bSAlexander Aring 106171e36b1bSAlexander Aring static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, 106271e36b1bSAlexander Aring struct packet_type *pt, struct net_device *orig_dev) 106371e36b1bSAlexander Aring { 106471e36b1bSAlexander Aring if (!netif_running(dev)) 106571e36b1bSAlexander Aring goto drop; 106671e36b1bSAlexander Aring pr_debug("got frame, type %d, dev %p\n", dev->type, dev); 106771e36b1bSAlexander Aring #ifdef DEBUG 106871e36b1bSAlexander Aring print_hex_dump_bytes("ieee802154_rcv ", 106971e36b1bSAlexander Aring DUMP_PREFIX_NONE, skb->data, skb->len); 107071e36b1bSAlexander Aring #endif 107171e36b1bSAlexander Aring 107271e36b1bSAlexander Aring if (!net_eq(dev_net(dev), &init_net)) 107371e36b1bSAlexander Aring goto drop; 107471e36b1bSAlexander Aring 107571e36b1bSAlexander Aring ieee802154_raw_deliver(dev, skb); 107671e36b1bSAlexander Aring 107771e36b1bSAlexander Aring if (dev->type != ARPHRD_IEEE802154) 107871e36b1bSAlexander Aring goto drop; 107971e36b1bSAlexander Aring 108071e36b1bSAlexander Aring if (skb->pkt_type != PACKET_OTHERHOST) 108171e36b1bSAlexander Aring return ieee802154_dgram_deliver(dev, skb); 108271e36b1bSAlexander Aring 108371e36b1bSAlexander Aring drop: 108471e36b1bSAlexander Aring kfree_skb(skb); 108571e36b1bSAlexander Aring return NET_RX_DROP; 108671e36b1bSAlexander Aring } 108771e36b1bSAlexander Aring 108871e36b1bSAlexander Aring static struct packet_type ieee802154_packet_type = { 108971e36b1bSAlexander Aring .type = htons(ETH_P_IEEE802154), 109071e36b1bSAlexander Aring .func = ieee802154_rcv, 109171e36b1bSAlexander Aring }; 109271e36b1bSAlexander Aring 109371e36b1bSAlexander Aring static int __init af_ieee802154_init(void) 109471e36b1bSAlexander Aring { 109571e36b1bSAlexander Aring int rc = -EINVAL; 109671e36b1bSAlexander Aring 109771e36b1bSAlexander Aring rc = proto_register(&ieee802154_raw_prot, 1); 109871e36b1bSAlexander Aring if (rc) 109971e36b1bSAlexander Aring goto out; 110071e36b1bSAlexander Aring 110171e36b1bSAlexander Aring rc = proto_register(&ieee802154_dgram_prot, 1); 110271e36b1bSAlexander Aring if (rc) 110371e36b1bSAlexander Aring goto err_dgram; 110471e36b1bSAlexander Aring 110571e36b1bSAlexander Aring /* Tell SOCKET that we are alive */ 110671e36b1bSAlexander Aring rc = sock_register(&ieee802154_family_ops); 110771e36b1bSAlexander Aring if (rc) 110871e36b1bSAlexander Aring goto err_sock; 110971e36b1bSAlexander Aring dev_add_pack(&ieee802154_packet_type); 111071e36b1bSAlexander Aring 111171e36b1bSAlexander Aring rc = 0; 111271e36b1bSAlexander Aring goto out; 111371e36b1bSAlexander Aring 111471e36b1bSAlexander Aring err_sock: 111571e36b1bSAlexander Aring proto_unregister(&ieee802154_dgram_prot); 111671e36b1bSAlexander Aring err_dgram: 111771e36b1bSAlexander Aring proto_unregister(&ieee802154_raw_prot); 111871e36b1bSAlexander Aring out: 111971e36b1bSAlexander Aring return rc; 112071e36b1bSAlexander Aring } 112171e36b1bSAlexander Aring 112271e36b1bSAlexander Aring static void __exit af_ieee802154_remove(void) 112371e36b1bSAlexander Aring { 112471e36b1bSAlexander Aring dev_remove_pack(&ieee802154_packet_type); 112571e36b1bSAlexander Aring sock_unregister(PF_IEEE802154); 112671e36b1bSAlexander Aring proto_unregister(&ieee802154_dgram_prot); 112771e36b1bSAlexander Aring proto_unregister(&ieee802154_raw_prot); 112871e36b1bSAlexander Aring } 112971e36b1bSAlexander Aring 113071e36b1bSAlexander Aring module_init(af_ieee802154_init); 113171e36b1bSAlexander Aring module_exit(af_ieee802154_remove); 113271e36b1bSAlexander Aring 113371e36b1bSAlexander Aring MODULE_LICENSE("GPL"); 113471e36b1bSAlexander Aring MODULE_ALIAS_NETPROTO(PF_IEEE802154); 1135