171e36b1bSAlexander Aring /* 271e36b1bSAlexander Aring * IEEE802154.4 socket interface 371e36b1bSAlexander Aring * 471e36b1bSAlexander Aring * Copyright 2007, 2008 Siemens AG 571e36b1bSAlexander Aring * 671e36b1bSAlexander Aring * This program is free software; you can redistribute it and/or modify 771e36b1bSAlexander Aring * it under the terms of the GNU General Public License version 2 871e36b1bSAlexander Aring * as published by the Free Software Foundation. 971e36b1bSAlexander Aring * 1071e36b1bSAlexander Aring * This program is distributed in the hope that it will be useful, 1171e36b1bSAlexander Aring * but WITHOUT ANY WARRANTY; without even the implied warranty of 1271e36b1bSAlexander Aring * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1371e36b1bSAlexander Aring * GNU General Public License for more details. 1471e36b1bSAlexander Aring * 1571e36b1bSAlexander Aring * Written by: 1671e36b1bSAlexander Aring * Sergey Lapin <slapin@ossfans.org> 1771e36b1bSAlexander Aring * Maxim Gorbachyov <maxim.gorbachev@siemens.com> 1871e36b1bSAlexander Aring */ 1971e36b1bSAlexander Aring 2071e36b1bSAlexander Aring #include <linux/net.h> 2171e36b1bSAlexander Aring #include <linux/capability.h> 2271e36b1bSAlexander Aring #include <linux/module.h> 2371e36b1bSAlexander Aring #include <linux/if_arp.h> 2471e36b1bSAlexander Aring #include <linux/if.h> 2571e36b1bSAlexander Aring #include <linux/termios.h> /* For TIOCOUTQ/INQ */ 2671e36b1bSAlexander Aring #include <linux/list.h> 2771e36b1bSAlexander Aring #include <linux/slab.h> 2871e36b1bSAlexander Aring #include <net/datalink.h> 2971e36b1bSAlexander Aring #include <net/psnap.h> 3071e36b1bSAlexander Aring #include <net/sock.h> 3171e36b1bSAlexander Aring #include <net/tcp_states.h> 3271e36b1bSAlexander Aring #include <net/route.h> 3371e36b1bSAlexander Aring 3471e36b1bSAlexander Aring #include <net/af_ieee802154.h> 3571e36b1bSAlexander Aring #include <net/ieee802154_netdev.h> 3671e36b1bSAlexander Aring 3771e36b1bSAlexander Aring /* Utility function for families */ 3871e36b1bSAlexander Aring static struct net_device* 3971e36b1bSAlexander Aring ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr) 4071e36b1bSAlexander Aring { 4171e36b1bSAlexander Aring struct net_device *dev = NULL; 4271e36b1bSAlexander Aring struct net_device *tmp; 4371e36b1bSAlexander Aring __le16 pan_id, short_addr; 4471e36b1bSAlexander Aring u8 hwaddr[IEEE802154_ADDR_LEN]; 4571e36b1bSAlexander Aring 4671e36b1bSAlexander Aring switch (addr->mode) { 4771e36b1bSAlexander Aring case IEEE802154_ADDR_LONG: 4871e36b1bSAlexander Aring ieee802154_devaddr_to_raw(hwaddr, addr->extended_addr); 4971e36b1bSAlexander Aring rcu_read_lock(); 5071e36b1bSAlexander Aring dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, hwaddr); 5171e36b1bSAlexander Aring if (dev) 5271e36b1bSAlexander Aring dev_hold(dev); 5371e36b1bSAlexander Aring rcu_read_unlock(); 5471e36b1bSAlexander Aring break; 5571e36b1bSAlexander Aring case IEEE802154_ADDR_SHORT: 5671e36b1bSAlexander Aring if (addr->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST) || 5771e36b1bSAlexander Aring addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) || 5871e36b1bSAlexander Aring addr->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) 5971e36b1bSAlexander Aring break; 6071e36b1bSAlexander Aring 6171e36b1bSAlexander Aring rtnl_lock(); 6271e36b1bSAlexander Aring 6371e36b1bSAlexander Aring for_each_netdev(net, tmp) { 6471e36b1bSAlexander Aring if (tmp->type != ARPHRD_IEEE802154) 6571e36b1bSAlexander Aring continue; 6671e36b1bSAlexander Aring 67c947f7e1SAlexander Aring pan_id = tmp->ieee802154_ptr->pan_id; 68c947f7e1SAlexander Aring short_addr = tmp->ieee802154_ptr->short_addr; 6971e36b1bSAlexander Aring if (pan_id == addr->pan_id && 7071e36b1bSAlexander Aring short_addr == addr->short_addr) { 7171e36b1bSAlexander Aring dev = tmp; 7271e36b1bSAlexander Aring dev_hold(dev); 7371e36b1bSAlexander Aring break; 7471e36b1bSAlexander Aring } 7571e36b1bSAlexander Aring } 7671e36b1bSAlexander Aring 7771e36b1bSAlexander Aring rtnl_unlock(); 7871e36b1bSAlexander Aring break; 7971e36b1bSAlexander Aring default: 8071e36b1bSAlexander Aring pr_warn("Unsupported ieee802154 address type: %d\n", 8171e36b1bSAlexander Aring addr->mode); 8271e36b1bSAlexander Aring break; 8371e36b1bSAlexander Aring } 8471e36b1bSAlexander Aring 8571e36b1bSAlexander Aring return dev; 8671e36b1bSAlexander Aring } 8771e36b1bSAlexander Aring 8871e36b1bSAlexander Aring static int ieee802154_sock_release(struct socket *sock) 8971e36b1bSAlexander Aring { 9071e36b1bSAlexander Aring struct sock *sk = sock->sk; 9171e36b1bSAlexander Aring 9271e36b1bSAlexander Aring if (sk) { 9371e36b1bSAlexander Aring sock->sk = NULL; 9471e36b1bSAlexander Aring sk->sk_prot->close(sk, 0); 9571e36b1bSAlexander Aring } 9671e36b1bSAlexander Aring return 0; 9771e36b1bSAlexander Aring } 9871e36b1bSAlexander Aring 991b784140SYing Xue static int ieee802154_sock_sendmsg(struct socket *sock, struct msghdr *msg, 1001b784140SYing Xue size_t len) 10171e36b1bSAlexander Aring { 10271e36b1bSAlexander Aring struct sock *sk = sock->sk; 10371e36b1bSAlexander Aring 1041b784140SYing Xue return sk->sk_prot->sendmsg(sk, msg, len); 10571e36b1bSAlexander Aring } 10671e36b1bSAlexander Aring 10771e36b1bSAlexander Aring static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr, 10871e36b1bSAlexander Aring int addr_len) 10971e36b1bSAlexander Aring { 11071e36b1bSAlexander Aring struct sock *sk = sock->sk; 11171e36b1bSAlexander Aring 11271e36b1bSAlexander Aring if (sk->sk_prot->bind) 11371e36b1bSAlexander Aring return sk->sk_prot->bind(sk, uaddr, addr_len); 11471e36b1bSAlexander Aring 11571e36b1bSAlexander Aring return sock_no_bind(sock, uaddr, addr_len); 11671e36b1bSAlexander Aring } 11771e36b1bSAlexander Aring 11871e36b1bSAlexander Aring static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr, 11971e36b1bSAlexander Aring int addr_len, int flags) 12071e36b1bSAlexander Aring { 12171e36b1bSAlexander Aring struct sock *sk = sock->sk; 12271e36b1bSAlexander Aring 12371e36b1bSAlexander Aring if (addr_len < sizeof(uaddr->sa_family)) 12471e36b1bSAlexander Aring return -EINVAL; 12571e36b1bSAlexander Aring 12671e36b1bSAlexander Aring if (uaddr->sa_family == AF_UNSPEC) 12771e36b1bSAlexander Aring return sk->sk_prot->disconnect(sk, flags); 12871e36b1bSAlexander Aring 12971e36b1bSAlexander Aring return sk->sk_prot->connect(sk, uaddr, addr_len); 13071e36b1bSAlexander Aring } 13171e36b1bSAlexander Aring 13271e36b1bSAlexander Aring static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, 13371e36b1bSAlexander Aring unsigned int cmd) 13471e36b1bSAlexander Aring { 13571e36b1bSAlexander Aring struct ifreq ifr; 13671e36b1bSAlexander Aring int ret = -ENOIOCTLCMD; 13771e36b1bSAlexander Aring struct net_device *dev; 13871e36b1bSAlexander Aring 13971e36b1bSAlexander Aring if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) 14071e36b1bSAlexander Aring return -EFAULT; 14171e36b1bSAlexander Aring 14271e36b1bSAlexander Aring ifr.ifr_name[IFNAMSIZ-1] = 0; 14371e36b1bSAlexander Aring 14471e36b1bSAlexander Aring dev_load(sock_net(sk), ifr.ifr_name); 14571e36b1bSAlexander Aring dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); 14671e36b1bSAlexander Aring 14771e36b1bSAlexander Aring if (!dev) 14871e36b1bSAlexander Aring return -ENODEV; 14971e36b1bSAlexander Aring 15071e36b1bSAlexander Aring if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl) 15171e36b1bSAlexander Aring ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); 15271e36b1bSAlexander Aring 15371e36b1bSAlexander Aring if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) 15471e36b1bSAlexander Aring ret = -EFAULT; 15571e36b1bSAlexander Aring dev_put(dev); 15671e36b1bSAlexander Aring 15771e36b1bSAlexander Aring return ret; 15871e36b1bSAlexander Aring } 15971e36b1bSAlexander Aring 16071e36b1bSAlexander Aring static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd, 16171e36b1bSAlexander Aring unsigned long arg) 16271e36b1bSAlexander Aring { 16371e36b1bSAlexander Aring struct sock *sk = sock->sk; 16471e36b1bSAlexander Aring 16571e36b1bSAlexander Aring switch (cmd) { 16671e36b1bSAlexander Aring case SIOCGSTAMP: 16771e36b1bSAlexander Aring return sock_get_timestamp(sk, (struct timeval __user *)arg); 16871e36b1bSAlexander Aring case SIOCGSTAMPNS: 16971e36b1bSAlexander Aring return sock_get_timestampns(sk, (struct timespec __user *)arg); 17071e36b1bSAlexander Aring case SIOCGIFADDR: 17171e36b1bSAlexander Aring case SIOCSIFADDR: 17271e36b1bSAlexander Aring return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg, 17371e36b1bSAlexander Aring cmd); 17471e36b1bSAlexander Aring default: 17571e36b1bSAlexander Aring if (!sk->sk_prot->ioctl) 17671e36b1bSAlexander Aring return -ENOIOCTLCMD; 17771e36b1bSAlexander Aring return sk->sk_prot->ioctl(sk, cmd, arg); 17871e36b1bSAlexander Aring } 17971e36b1bSAlexander Aring } 18071e36b1bSAlexander Aring 18171e36b1bSAlexander Aring /* RAW Sockets (802.15.4 created in userspace) */ 18271e36b1bSAlexander Aring static HLIST_HEAD(raw_head); 18371e36b1bSAlexander Aring static DEFINE_RWLOCK(raw_lock); 18471e36b1bSAlexander Aring 185086c653fSCraig Gallek static int raw_hash(struct sock *sk) 18671e36b1bSAlexander Aring { 18771e36b1bSAlexander Aring write_lock_bh(&raw_lock); 18871e36b1bSAlexander Aring sk_add_node(sk, &raw_head); 18971e36b1bSAlexander Aring sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); 19071e36b1bSAlexander Aring write_unlock_bh(&raw_lock); 191086c653fSCraig Gallek 192086c653fSCraig Gallek return 0; 19371e36b1bSAlexander Aring } 19471e36b1bSAlexander Aring 19571e36b1bSAlexander Aring static void raw_unhash(struct sock *sk) 19671e36b1bSAlexander Aring { 19771e36b1bSAlexander Aring write_lock_bh(&raw_lock); 19871e36b1bSAlexander Aring if (sk_del_node_init(sk)) 19971e36b1bSAlexander Aring sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); 20071e36b1bSAlexander Aring write_unlock_bh(&raw_lock); 20171e36b1bSAlexander Aring } 20271e36b1bSAlexander Aring 20371e36b1bSAlexander Aring static void raw_close(struct sock *sk, long timeout) 20471e36b1bSAlexander Aring { 20571e36b1bSAlexander Aring sk_common_release(sk); 20671e36b1bSAlexander Aring } 20771e36b1bSAlexander Aring 20871e36b1bSAlexander Aring static int raw_bind(struct sock *sk, struct sockaddr *_uaddr, int len) 20971e36b1bSAlexander Aring { 21071e36b1bSAlexander Aring struct ieee802154_addr addr; 21171e36b1bSAlexander Aring struct sockaddr_ieee802154 *uaddr = (struct sockaddr_ieee802154 *)_uaddr; 21271e36b1bSAlexander Aring int err = 0; 21371e36b1bSAlexander Aring struct net_device *dev = NULL; 21471e36b1bSAlexander Aring 21571e36b1bSAlexander Aring if (len < sizeof(*uaddr)) 21671e36b1bSAlexander Aring return -EINVAL; 21771e36b1bSAlexander Aring 21871e36b1bSAlexander Aring uaddr = (struct sockaddr_ieee802154 *)_uaddr; 21971e36b1bSAlexander Aring if (uaddr->family != AF_IEEE802154) 22071e36b1bSAlexander Aring return -EINVAL; 22171e36b1bSAlexander Aring 22271e36b1bSAlexander Aring lock_sock(sk); 22371e36b1bSAlexander Aring 22471e36b1bSAlexander Aring ieee802154_addr_from_sa(&addr, &uaddr->addr); 22571e36b1bSAlexander Aring dev = ieee802154_get_dev(sock_net(sk), &addr); 22671e36b1bSAlexander Aring if (!dev) { 22771e36b1bSAlexander Aring err = -ENODEV; 22871e36b1bSAlexander Aring goto out; 22971e36b1bSAlexander Aring } 23071e36b1bSAlexander Aring 23171e36b1bSAlexander Aring sk->sk_bound_dev_if = dev->ifindex; 23271e36b1bSAlexander Aring sk_dst_reset(sk); 23371e36b1bSAlexander Aring 23471e36b1bSAlexander Aring dev_put(dev); 23571e36b1bSAlexander Aring out: 23671e36b1bSAlexander Aring release_sock(sk); 23771e36b1bSAlexander Aring 23871e36b1bSAlexander Aring return err; 23971e36b1bSAlexander Aring } 24071e36b1bSAlexander Aring 24171e36b1bSAlexander Aring static int raw_connect(struct sock *sk, struct sockaddr *uaddr, 24271e36b1bSAlexander Aring int addr_len) 24371e36b1bSAlexander Aring { 24471e36b1bSAlexander Aring return -ENOTSUPP; 24571e36b1bSAlexander Aring } 24671e36b1bSAlexander Aring 24771e36b1bSAlexander Aring static int raw_disconnect(struct sock *sk, int flags) 24871e36b1bSAlexander Aring { 24971e36b1bSAlexander Aring return 0; 25071e36b1bSAlexander Aring } 25171e36b1bSAlexander Aring 2521b784140SYing Xue static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) 25371e36b1bSAlexander Aring { 25471e36b1bSAlexander Aring struct net_device *dev; 25571e36b1bSAlexander Aring unsigned int mtu; 25671e36b1bSAlexander Aring struct sk_buff *skb; 25771e36b1bSAlexander Aring int hlen, tlen; 25871e36b1bSAlexander Aring int err; 25971e36b1bSAlexander Aring 26071e36b1bSAlexander Aring if (msg->msg_flags & MSG_OOB) { 26171e36b1bSAlexander Aring pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags); 26271e36b1bSAlexander Aring return -EOPNOTSUPP; 26371e36b1bSAlexander Aring } 26471e36b1bSAlexander Aring 26571e36b1bSAlexander Aring lock_sock(sk); 26671e36b1bSAlexander Aring if (!sk->sk_bound_dev_if) 26771e36b1bSAlexander Aring dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); 26871e36b1bSAlexander Aring else 26971e36b1bSAlexander Aring dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); 27071e36b1bSAlexander Aring release_sock(sk); 27171e36b1bSAlexander Aring 27271e36b1bSAlexander Aring if (!dev) { 27371e36b1bSAlexander Aring pr_debug("no dev\n"); 27471e36b1bSAlexander Aring err = -ENXIO; 27571e36b1bSAlexander Aring goto out; 27671e36b1bSAlexander Aring } 27771e36b1bSAlexander Aring 278b40988c4SAlexander Aring mtu = IEEE802154_MTU; 27971e36b1bSAlexander Aring pr_debug("name = %s, mtu = %u\n", dev->name, mtu); 28071e36b1bSAlexander Aring 28171e36b1bSAlexander Aring if (size > mtu) { 28271e36b1bSAlexander Aring pr_debug("size = %Zu, mtu = %u\n", size, mtu); 283c032705eSLennert Buytenhek err = -EMSGSIZE; 28471e36b1bSAlexander Aring goto out_dev; 28571e36b1bSAlexander Aring } 28671e36b1bSAlexander Aring 28771e36b1bSAlexander Aring hlen = LL_RESERVED_SPACE(dev); 28871e36b1bSAlexander Aring tlen = dev->needed_tailroom; 28971e36b1bSAlexander Aring skb = sock_alloc_send_skb(sk, hlen + tlen + size, 29071e36b1bSAlexander Aring msg->msg_flags & MSG_DONTWAIT, &err); 29171e36b1bSAlexander Aring if (!skb) 29271e36b1bSAlexander Aring goto out_dev; 29371e36b1bSAlexander Aring 29471e36b1bSAlexander Aring skb_reserve(skb, hlen); 29571e36b1bSAlexander Aring 29671e36b1bSAlexander Aring skb_reset_mac_header(skb); 29771e36b1bSAlexander Aring skb_reset_network_header(skb); 29871e36b1bSAlexander Aring 29971e36b1bSAlexander Aring err = memcpy_from_msg(skb_put(skb, size), msg, size); 30071e36b1bSAlexander Aring if (err < 0) 30171e36b1bSAlexander Aring goto out_skb; 30271e36b1bSAlexander Aring 30371e36b1bSAlexander Aring skb->dev = dev; 30471e36b1bSAlexander Aring skb->sk = sk; 30571e36b1bSAlexander Aring skb->protocol = htons(ETH_P_IEEE802154); 30671e36b1bSAlexander Aring 30771e36b1bSAlexander Aring dev_put(dev); 30871e36b1bSAlexander Aring 30971e36b1bSAlexander Aring err = dev_queue_xmit(skb); 31071e36b1bSAlexander Aring if (err > 0) 31171e36b1bSAlexander Aring err = net_xmit_errno(err); 31271e36b1bSAlexander Aring 31371e36b1bSAlexander Aring return err ?: size; 31471e36b1bSAlexander Aring 31571e36b1bSAlexander Aring out_skb: 31671e36b1bSAlexander Aring kfree_skb(skb); 31771e36b1bSAlexander Aring out_dev: 31871e36b1bSAlexander Aring dev_put(dev); 31971e36b1bSAlexander Aring out: 32071e36b1bSAlexander Aring return err; 32171e36b1bSAlexander Aring } 32271e36b1bSAlexander Aring 3231b784140SYing Xue static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, 3241b784140SYing Xue int noblock, int flags, int *addr_len) 32571e36b1bSAlexander Aring { 32671e36b1bSAlexander Aring size_t copied = 0; 32771e36b1bSAlexander Aring int err = -EOPNOTSUPP; 32871e36b1bSAlexander Aring struct sk_buff *skb; 32971e36b1bSAlexander Aring 33071e36b1bSAlexander Aring skb = skb_recv_datagram(sk, flags, noblock, &err); 33171e36b1bSAlexander Aring if (!skb) 33271e36b1bSAlexander Aring goto out; 33371e36b1bSAlexander Aring 33471e36b1bSAlexander Aring copied = skb->len; 33571e36b1bSAlexander Aring if (len < copied) { 33671e36b1bSAlexander Aring msg->msg_flags |= MSG_TRUNC; 33771e36b1bSAlexander Aring copied = len; 33871e36b1bSAlexander Aring } 33971e36b1bSAlexander Aring 34071e36b1bSAlexander Aring err = skb_copy_datagram_msg(skb, 0, msg, copied); 34171e36b1bSAlexander Aring if (err) 34271e36b1bSAlexander Aring goto done; 34371e36b1bSAlexander Aring 34471e36b1bSAlexander Aring sock_recv_ts_and_drops(msg, sk, skb); 34571e36b1bSAlexander Aring 34671e36b1bSAlexander Aring if (flags & MSG_TRUNC) 34771e36b1bSAlexander Aring copied = skb->len; 34871e36b1bSAlexander Aring done: 34971e36b1bSAlexander Aring skb_free_datagram(sk, skb); 35071e36b1bSAlexander Aring out: 35171e36b1bSAlexander Aring if (err) 35271e36b1bSAlexander Aring return err; 35371e36b1bSAlexander Aring return copied; 35471e36b1bSAlexander Aring } 35571e36b1bSAlexander Aring 35671e36b1bSAlexander Aring static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) 35771e36b1bSAlexander Aring { 35871e36b1bSAlexander Aring skb = skb_share_check(skb, GFP_ATOMIC); 35971e36b1bSAlexander Aring if (!skb) 36071e36b1bSAlexander Aring return NET_RX_DROP; 36171e36b1bSAlexander Aring 36271e36b1bSAlexander Aring if (sock_queue_rcv_skb(sk, skb) < 0) { 36371e36b1bSAlexander Aring kfree_skb(skb); 36471e36b1bSAlexander Aring return NET_RX_DROP; 36571e36b1bSAlexander Aring } 36671e36b1bSAlexander Aring 36771e36b1bSAlexander Aring return NET_RX_SUCCESS; 36871e36b1bSAlexander Aring } 36971e36b1bSAlexander Aring 37071e36b1bSAlexander Aring static void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb) 37171e36b1bSAlexander Aring { 37271e36b1bSAlexander Aring struct sock *sk; 37371e36b1bSAlexander Aring 37471e36b1bSAlexander Aring read_lock(&raw_lock); 37571e36b1bSAlexander Aring sk_for_each(sk, &raw_head) { 37671e36b1bSAlexander Aring bh_lock_sock(sk); 37771e36b1bSAlexander Aring if (!sk->sk_bound_dev_if || 37871e36b1bSAlexander Aring sk->sk_bound_dev_if == dev->ifindex) { 37971e36b1bSAlexander Aring struct sk_buff *clone; 38071e36b1bSAlexander Aring 38171e36b1bSAlexander Aring clone = skb_clone(skb, GFP_ATOMIC); 38271e36b1bSAlexander Aring if (clone) 38371e36b1bSAlexander Aring raw_rcv_skb(sk, clone); 38471e36b1bSAlexander Aring } 38571e36b1bSAlexander Aring bh_unlock_sock(sk); 38671e36b1bSAlexander Aring } 38771e36b1bSAlexander Aring read_unlock(&raw_lock); 38871e36b1bSAlexander Aring } 38971e36b1bSAlexander Aring 39071e36b1bSAlexander Aring static int raw_getsockopt(struct sock *sk, int level, int optname, 39171e36b1bSAlexander Aring char __user *optval, int __user *optlen) 39271e36b1bSAlexander Aring { 39371e36b1bSAlexander Aring return -EOPNOTSUPP; 39471e36b1bSAlexander Aring } 39571e36b1bSAlexander Aring 39671e36b1bSAlexander Aring static int raw_setsockopt(struct sock *sk, int level, int optname, 39771e36b1bSAlexander Aring char __user *optval, unsigned int optlen) 39871e36b1bSAlexander Aring { 39971e36b1bSAlexander Aring return -EOPNOTSUPP; 40071e36b1bSAlexander Aring } 40171e36b1bSAlexander Aring 40271e36b1bSAlexander Aring static struct proto ieee802154_raw_prot = { 40371e36b1bSAlexander Aring .name = "IEEE-802.15.4-RAW", 40471e36b1bSAlexander Aring .owner = THIS_MODULE, 40571e36b1bSAlexander Aring .obj_size = sizeof(struct sock), 40671e36b1bSAlexander Aring .close = raw_close, 40771e36b1bSAlexander Aring .bind = raw_bind, 40871e36b1bSAlexander Aring .sendmsg = raw_sendmsg, 40971e36b1bSAlexander Aring .recvmsg = raw_recvmsg, 41071e36b1bSAlexander Aring .hash = raw_hash, 41171e36b1bSAlexander Aring .unhash = raw_unhash, 41271e36b1bSAlexander Aring .connect = raw_connect, 41371e36b1bSAlexander Aring .disconnect = raw_disconnect, 41471e36b1bSAlexander Aring .getsockopt = raw_getsockopt, 41571e36b1bSAlexander Aring .setsockopt = raw_setsockopt, 41671e36b1bSAlexander Aring }; 41771e36b1bSAlexander Aring 41871e36b1bSAlexander Aring static const struct proto_ops ieee802154_raw_ops = { 41971e36b1bSAlexander Aring .family = PF_IEEE802154, 42071e36b1bSAlexander Aring .owner = THIS_MODULE, 42171e36b1bSAlexander Aring .release = ieee802154_sock_release, 42271e36b1bSAlexander Aring .bind = ieee802154_sock_bind, 42371e36b1bSAlexander Aring .connect = ieee802154_sock_connect, 42471e36b1bSAlexander Aring .socketpair = sock_no_socketpair, 42571e36b1bSAlexander Aring .accept = sock_no_accept, 42671e36b1bSAlexander Aring .getname = sock_no_getname, 42771e36b1bSAlexander Aring .poll = datagram_poll, 42871e36b1bSAlexander Aring .ioctl = ieee802154_sock_ioctl, 42971e36b1bSAlexander Aring .listen = sock_no_listen, 43071e36b1bSAlexander Aring .shutdown = sock_no_shutdown, 43171e36b1bSAlexander Aring .setsockopt = sock_common_setsockopt, 43271e36b1bSAlexander Aring .getsockopt = sock_common_getsockopt, 43371e36b1bSAlexander Aring .sendmsg = ieee802154_sock_sendmsg, 43471e36b1bSAlexander Aring .recvmsg = sock_common_recvmsg, 43571e36b1bSAlexander Aring .mmap = sock_no_mmap, 43671e36b1bSAlexander Aring .sendpage = sock_no_sendpage, 43771e36b1bSAlexander Aring #ifdef CONFIG_COMPAT 43871e36b1bSAlexander Aring .compat_setsockopt = compat_sock_common_setsockopt, 43971e36b1bSAlexander Aring .compat_getsockopt = compat_sock_common_getsockopt, 44071e36b1bSAlexander Aring #endif 44171e36b1bSAlexander Aring }; 44271e36b1bSAlexander Aring 44371e36b1bSAlexander Aring /* DGRAM Sockets (802.15.4 dataframes) */ 44471e36b1bSAlexander Aring static HLIST_HEAD(dgram_head); 44571e36b1bSAlexander Aring static DEFINE_RWLOCK(dgram_lock); 44671e36b1bSAlexander Aring 44771e36b1bSAlexander Aring struct dgram_sock { 44871e36b1bSAlexander Aring struct sock sk; 44971e36b1bSAlexander Aring 45071e36b1bSAlexander Aring struct ieee802154_addr src_addr; 45171e36b1bSAlexander Aring struct ieee802154_addr dst_addr; 45271e36b1bSAlexander Aring 45371e36b1bSAlexander Aring unsigned int bound:1; 45471e36b1bSAlexander Aring unsigned int connected:1; 45571e36b1bSAlexander Aring unsigned int want_ack:1; 45671e36b1bSAlexander Aring unsigned int secen:1; 45771e36b1bSAlexander Aring unsigned int secen_override:1; 45871e36b1bSAlexander Aring unsigned int seclevel:3; 45971e36b1bSAlexander Aring unsigned int seclevel_override:1; 46071e36b1bSAlexander Aring }; 46171e36b1bSAlexander Aring 46271e36b1bSAlexander Aring static inline struct dgram_sock *dgram_sk(const struct sock *sk) 46371e36b1bSAlexander Aring { 46471e36b1bSAlexander Aring return container_of(sk, struct dgram_sock, sk); 46571e36b1bSAlexander Aring } 46671e36b1bSAlexander Aring 467086c653fSCraig Gallek static int dgram_hash(struct sock *sk) 46871e36b1bSAlexander Aring { 46971e36b1bSAlexander Aring write_lock_bh(&dgram_lock); 47071e36b1bSAlexander Aring sk_add_node(sk, &dgram_head); 47171e36b1bSAlexander Aring sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); 47271e36b1bSAlexander Aring write_unlock_bh(&dgram_lock); 473086c653fSCraig Gallek 474086c653fSCraig Gallek return 0; 47571e36b1bSAlexander Aring } 47671e36b1bSAlexander Aring 47771e36b1bSAlexander Aring static void dgram_unhash(struct sock *sk) 47871e36b1bSAlexander Aring { 47971e36b1bSAlexander Aring write_lock_bh(&dgram_lock); 48071e36b1bSAlexander Aring if (sk_del_node_init(sk)) 48171e36b1bSAlexander Aring sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); 48271e36b1bSAlexander Aring write_unlock_bh(&dgram_lock); 48371e36b1bSAlexander Aring } 48471e36b1bSAlexander Aring 48571e36b1bSAlexander Aring static int dgram_init(struct sock *sk) 48671e36b1bSAlexander Aring { 48771e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 48871e36b1bSAlexander Aring 48971e36b1bSAlexander Aring ro->want_ack = 1; 49071e36b1bSAlexander Aring return 0; 49171e36b1bSAlexander Aring } 49271e36b1bSAlexander Aring 49371e36b1bSAlexander Aring static void dgram_close(struct sock *sk, long timeout) 49471e36b1bSAlexander Aring { 49571e36b1bSAlexander Aring sk_common_release(sk); 49671e36b1bSAlexander Aring } 49771e36b1bSAlexander Aring 49871e36b1bSAlexander Aring static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) 49971e36b1bSAlexander Aring { 50071e36b1bSAlexander Aring struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; 50171e36b1bSAlexander Aring struct ieee802154_addr haddr; 50271e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 50371e36b1bSAlexander Aring int err = -EINVAL; 50471e36b1bSAlexander Aring struct net_device *dev; 50571e36b1bSAlexander Aring 50671e36b1bSAlexander Aring lock_sock(sk); 50771e36b1bSAlexander Aring 50871e36b1bSAlexander Aring ro->bound = 0; 50971e36b1bSAlexander Aring 51071e36b1bSAlexander Aring if (len < sizeof(*addr)) 51171e36b1bSAlexander Aring goto out; 51271e36b1bSAlexander Aring 51371e36b1bSAlexander Aring if (addr->family != AF_IEEE802154) 51471e36b1bSAlexander Aring goto out; 51571e36b1bSAlexander Aring 51671e36b1bSAlexander Aring ieee802154_addr_from_sa(&haddr, &addr->addr); 51771e36b1bSAlexander Aring dev = ieee802154_get_dev(sock_net(sk), &haddr); 51871e36b1bSAlexander Aring if (!dev) { 51971e36b1bSAlexander Aring err = -ENODEV; 52071e36b1bSAlexander Aring goto out; 52171e36b1bSAlexander Aring } 52271e36b1bSAlexander Aring 52371e36b1bSAlexander Aring if (dev->type != ARPHRD_IEEE802154) { 52471e36b1bSAlexander Aring err = -ENODEV; 52571e36b1bSAlexander Aring goto out_put; 52671e36b1bSAlexander Aring } 52771e36b1bSAlexander Aring 52871e36b1bSAlexander Aring ro->src_addr = haddr; 52971e36b1bSAlexander Aring 53071e36b1bSAlexander Aring ro->bound = 1; 53171e36b1bSAlexander Aring err = 0; 53271e36b1bSAlexander Aring out_put: 53371e36b1bSAlexander Aring dev_put(dev); 53471e36b1bSAlexander Aring out: 53571e36b1bSAlexander Aring release_sock(sk); 53671e36b1bSAlexander Aring 53771e36b1bSAlexander Aring return err; 53871e36b1bSAlexander Aring } 53971e36b1bSAlexander Aring 54071e36b1bSAlexander Aring static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) 54171e36b1bSAlexander Aring { 54271e36b1bSAlexander Aring switch (cmd) { 54371e36b1bSAlexander Aring case SIOCOUTQ: 54471e36b1bSAlexander Aring { 54571e36b1bSAlexander Aring int amount = sk_wmem_alloc_get(sk); 54671e36b1bSAlexander Aring 54771e36b1bSAlexander Aring return put_user(amount, (int __user *)arg); 54871e36b1bSAlexander Aring } 54971e36b1bSAlexander Aring 55071e36b1bSAlexander Aring case SIOCINQ: 55171e36b1bSAlexander Aring { 55271e36b1bSAlexander Aring struct sk_buff *skb; 55371e36b1bSAlexander Aring unsigned long amount; 55471e36b1bSAlexander Aring 55571e36b1bSAlexander Aring amount = 0; 55671e36b1bSAlexander Aring spin_lock_bh(&sk->sk_receive_queue.lock); 55771e36b1bSAlexander Aring skb = skb_peek(&sk->sk_receive_queue); 55871e36b1bSAlexander Aring if (skb) { 55971e36b1bSAlexander Aring /* We will only return the amount 56071e36b1bSAlexander Aring * of this packet since that is all 56171e36b1bSAlexander Aring * that will be read. 56271e36b1bSAlexander Aring */ 56371e36b1bSAlexander Aring amount = skb->len - ieee802154_hdr_length(skb); 56471e36b1bSAlexander Aring } 56571e36b1bSAlexander Aring spin_unlock_bh(&sk->sk_receive_queue.lock); 56671e36b1bSAlexander Aring return put_user(amount, (int __user *)arg); 56771e36b1bSAlexander Aring } 56871e36b1bSAlexander Aring } 56971e36b1bSAlexander Aring 57071e36b1bSAlexander Aring return -ENOIOCTLCMD; 57171e36b1bSAlexander Aring } 57271e36b1bSAlexander Aring 57371e36b1bSAlexander Aring /* FIXME: autobind */ 57471e36b1bSAlexander Aring static int dgram_connect(struct sock *sk, struct sockaddr *uaddr, 57571e36b1bSAlexander Aring int len) 57671e36b1bSAlexander Aring { 57771e36b1bSAlexander Aring struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; 57871e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 57971e36b1bSAlexander Aring int err = 0; 58071e36b1bSAlexander Aring 58171e36b1bSAlexander Aring if (len < sizeof(*addr)) 58271e36b1bSAlexander Aring return -EINVAL; 58371e36b1bSAlexander Aring 58471e36b1bSAlexander Aring if (addr->family != AF_IEEE802154) 58571e36b1bSAlexander Aring return -EINVAL; 58671e36b1bSAlexander Aring 58771e36b1bSAlexander Aring lock_sock(sk); 58871e36b1bSAlexander Aring 58971e36b1bSAlexander Aring if (!ro->bound) { 59071e36b1bSAlexander Aring err = -ENETUNREACH; 59171e36b1bSAlexander Aring goto out; 59271e36b1bSAlexander Aring } 59371e36b1bSAlexander Aring 59471e36b1bSAlexander Aring ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr); 59571e36b1bSAlexander Aring ro->connected = 1; 59671e36b1bSAlexander Aring 59771e36b1bSAlexander Aring out: 59871e36b1bSAlexander Aring release_sock(sk); 59971e36b1bSAlexander Aring return err; 60071e36b1bSAlexander Aring } 60171e36b1bSAlexander Aring 60271e36b1bSAlexander Aring static int dgram_disconnect(struct sock *sk, int flags) 60371e36b1bSAlexander Aring { 60471e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 60571e36b1bSAlexander Aring 60671e36b1bSAlexander Aring lock_sock(sk); 60771e36b1bSAlexander Aring ro->connected = 0; 60871e36b1bSAlexander Aring release_sock(sk); 60971e36b1bSAlexander Aring 61071e36b1bSAlexander Aring return 0; 61171e36b1bSAlexander Aring } 61271e36b1bSAlexander Aring 6131b784140SYing Xue static int dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) 61471e36b1bSAlexander Aring { 61571e36b1bSAlexander Aring struct net_device *dev; 61671e36b1bSAlexander Aring unsigned int mtu; 61771e36b1bSAlexander Aring struct sk_buff *skb; 61871e36b1bSAlexander Aring struct ieee802154_mac_cb *cb; 61971e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 62071e36b1bSAlexander Aring struct ieee802154_addr dst_addr; 62171e36b1bSAlexander Aring int hlen, tlen; 62271e36b1bSAlexander Aring int err; 62371e36b1bSAlexander Aring 62471e36b1bSAlexander Aring if (msg->msg_flags & MSG_OOB) { 62571e36b1bSAlexander Aring pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags); 62671e36b1bSAlexander Aring return -EOPNOTSUPP; 62771e36b1bSAlexander Aring } 62871e36b1bSAlexander Aring 62971e36b1bSAlexander Aring if (!ro->connected && !msg->msg_name) 63071e36b1bSAlexander Aring return -EDESTADDRREQ; 63171e36b1bSAlexander Aring else if (ro->connected && msg->msg_name) 63271e36b1bSAlexander Aring return -EISCONN; 63371e36b1bSAlexander Aring 63471e36b1bSAlexander Aring if (!ro->bound) 63571e36b1bSAlexander Aring dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); 63671e36b1bSAlexander Aring else 63771e36b1bSAlexander Aring dev = ieee802154_get_dev(sock_net(sk), &ro->src_addr); 63871e36b1bSAlexander Aring 63971e36b1bSAlexander Aring if (!dev) { 64071e36b1bSAlexander Aring pr_debug("no dev\n"); 64171e36b1bSAlexander Aring err = -ENXIO; 64271e36b1bSAlexander Aring goto out; 64371e36b1bSAlexander Aring } 644b40988c4SAlexander Aring mtu = IEEE802154_MTU; 64571e36b1bSAlexander Aring pr_debug("name = %s, mtu = %u\n", dev->name, mtu); 64671e36b1bSAlexander Aring 64771e36b1bSAlexander Aring if (size > mtu) { 64871e36b1bSAlexander Aring pr_debug("size = %Zu, mtu = %u\n", size, mtu); 64971e36b1bSAlexander Aring err = -EMSGSIZE; 65071e36b1bSAlexander Aring goto out_dev; 65171e36b1bSAlexander Aring } 65271e36b1bSAlexander Aring 65371e36b1bSAlexander Aring hlen = LL_RESERVED_SPACE(dev); 65471e36b1bSAlexander Aring tlen = dev->needed_tailroom; 65571e36b1bSAlexander Aring skb = sock_alloc_send_skb(sk, hlen + tlen + size, 65671e36b1bSAlexander Aring msg->msg_flags & MSG_DONTWAIT, 65771e36b1bSAlexander Aring &err); 65871e36b1bSAlexander Aring if (!skb) 65971e36b1bSAlexander Aring goto out_dev; 66071e36b1bSAlexander Aring 66171e36b1bSAlexander Aring skb_reserve(skb, hlen); 66271e36b1bSAlexander Aring 66371e36b1bSAlexander Aring skb_reset_network_header(skb); 66471e36b1bSAlexander Aring 66571e36b1bSAlexander Aring cb = mac_cb_init(skb); 66671e36b1bSAlexander Aring cb->type = IEEE802154_FC_TYPE_DATA; 66771e36b1bSAlexander Aring cb->ackreq = ro->want_ack; 66871e36b1bSAlexander Aring 66971e36b1bSAlexander Aring if (msg->msg_name) { 67071e36b1bSAlexander Aring DECLARE_SOCKADDR(struct sockaddr_ieee802154*, 67171e36b1bSAlexander Aring daddr, msg->msg_name); 67271e36b1bSAlexander Aring 67371e36b1bSAlexander Aring ieee802154_addr_from_sa(&dst_addr, &daddr->addr); 67471e36b1bSAlexander Aring } else { 67571e36b1bSAlexander Aring dst_addr = ro->dst_addr; 67671e36b1bSAlexander Aring } 67771e36b1bSAlexander Aring 67871e36b1bSAlexander Aring cb->secen = ro->secen; 67971e36b1bSAlexander Aring cb->secen_override = ro->secen_override; 68071e36b1bSAlexander Aring cb->seclevel = ro->seclevel; 68171e36b1bSAlexander Aring cb->seclevel_override = ro->seclevel_override; 68271e36b1bSAlexander Aring 683838b83d6SAlexander Aring err = wpan_dev_hard_header(skb, dev, &dst_addr, 68471e36b1bSAlexander Aring ro->bound ? &ro->src_addr : NULL, size); 68571e36b1bSAlexander Aring if (err < 0) 68671e36b1bSAlexander Aring goto out_skb; 68771e36b1bSAlexander Aring 68871e36b1bSAlexander Aring err = memcpy_from_msg(skb_put(skb, size), msg, size); 68971e36b1bSAlexander Aring if (err < 0) 69071e36b1bSAlexander Aring goto out_skb; 69171e36b1bSAlexander Aring 69271e36b1bSAlexander Aring skb->dev = dev; 69371e36b1bSAlexander Aring skb->sk = sk; 69471e36b1bSAlexander Aring skb->protocol = htons(ETH_P_IEEE802154); 69571e36b1bSAlexander Aring 69671e36b1bSAlexander Aring dev_put(dev); 69771e36b1bSAlexander Aring 69871e36b1bSAlexander Aring err = dev_queue_xmit(skb); 69971e36b1bSAlexander Aring if (err > 0) 70071e36b1bSAlexander Aring err = net_xmit_errno(err); 70171e36b1bSAlexander Aring 70271e36b1bSAlexander Aring return err ?: size; 70371e36b1bSAlexander Aring 70471e36b1bSAlexander Aring out_skb: 70571e36b1bSAlexander Aring kfree_skb(skb); 70671e36b1bSAlexander Aring out_dev: 70771e36b1bSAlexander Aring dev_put(dev); 70871e36b1bSAlexander Aring out: 70971e36b1bSAlexander Aring return err; 71071e36b1bSAlexander Aring } 71171e36b1bSAlexander Aring 7121b784140SYing Xue static int dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, 7131b784140SYing Xue int noblock, int flags, int *addr_len) 71471e36b1bSAlexander Aring { 71571e36b1bSAlexander Aring size_t copied = 0; 71671e36b1bSAlexander Aring int err = -EOPNOTSUPP; 71771e36b1bSAlexander Aring struct sk_buff *skb; 71871e36b1bSAlexander Aring DECLARE_SOCKADDR(struct sockaddr_ieee802154 *, saddr, msg->msg_name); 71971e36b1bSAlexander Aring 72071e36b1bSAlexander Aring skb = skb_recv_datagram(sk, flags, noblock, &err); 72171e36b1bSAlexander Aring if (!skb) 72271e36b1bSAlexander Aring goto out; 72371e36b1bSAlexander Aring 72471e36b1bSAlexander Aring copied = skb->len; 72571e36b1bSAlexander Aring if (len < copied) { 72671e36b1bSAlexander Aring msg->msg_flags |= MSG_TRUNC; 72771e36b1bSAlexander Aring copied = len; 72871e36b1bSAlexander Aring } 72971e36b1bSAlexander Aring 73071e36b1bSAlexander Aring /* FIXME: skip headers if necessary ?! */ 73171e36b1bSAlexander Aring err = skb_copy_datagram_msg(skb, 0, msg, copied); 73271e36b1bSAlexander Aring if (err) 73371e36b1bSAlexander Aring goto done; 73471e36b1bSAlexander Aring 73571e36b1bSAlexander Aring sock_recv_ts_and_drops(msg, sk, skb); 73671e36b1bSAlexander Aring 73771e36b1bSAlexander Aring if (saddr) { 7388a70cefaSLennert Buytenhek /* Clear the implicit padding in struct sockaddr_ieee802154 7398a70cefaSLennert Buytenhek * (16 bits between 'family' and 'addr') and in struct 7408a70cefaSLennert Buytenhek * ieee802154_addr_sa (16 bits at the end of the structure). 7418a70cefaSLennert Buytenhek */ 7428a70cefaSLennert Buytenhek memset(saddr, 0, sizeof(*saddr)); 7438a70cefaSLennert Buytenhek 74471e36b1bSAlexander Aring saddr->family = AF_IEEE802154; 74571e36b1bSAlexander Aring ieee802154_addr_to_sa(&saddr->addr, &mac_cb(skb)->source); 74671e36b1bSAlexander Aring *addr_len = sizeof(*saddr); 74771e36b1bSAlexander Aring } 74871e36b1bSAlexander Aring 74971e36b1bSAlexander Aring if (flags & MSG_TRUNC) 75071e36b1bSAlexander Aring copied = skb->len; 75171e36b1bSAlexander Aring done: 75271e36b1bSAlexander Aring skb_free_datagram(sk, skb); 75371e36b1bSAlexander Aring out: 75471e36b1bSAlexander Aring if (err) 75571e36b1bSAlexander Aring return err; 75671e36b1bSAlexander Aring return copied; 75771e36b1bSAlexander Aring } 75871e36b1bSAlexander Aring 75971e36b1bSAlexander Aring static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb) 76071e36b1bSAlexander Aring { 76171e36b1bSAlexander Aring skb = skb_share_check(skb, GFP_ATOMIC); 76271e36b1bSAlexander Aring if (!skb) 76371e36b1bSAlexander Aring return NET_RX_DROP; 76471e36b1bSAlexander Aring 76571e36b1bSAlexander Aring if (sock_queue_rcv_skb(sk, skb) < 0) { 76671e36b1bSAlexander Aring kfree_skb(skb); 76771e36b1bSAlexander Aring return NET_RX_DROP; 76871e36b1bSAlexander Aring } 76971e36b1bSAlexander Aring 77071e36b1bSAlexander Aring return NET_RX_SUCCESS; 77171e36b1bSAlexander Aring } 77271e36b1bSAlexander Aring 77371e36b1bSAlexander Aring static inline bool 77471e36b1bSAlexander Aring ieee802154_match_sock(__le64 hw_addr, __le16 pan_id, __le16 short_addr, 77571e36b1bSAlexander Aring struct dgram_sock *ro) 77671e36b1bSAlexander Aring { 77771e36b1bSAlexander Aring if (!ro->bound) 77871e36b1bSAlexander Aring return true; 77971e36b1bSAlexander Aring 78071e36b1bSAlexander Aring if (ro->src_addr.mode == IEEE802154_ADDR_LONG && 78171e36b1bSAlexander Aring hw_addr == ro->src_addr.extended_addr) 78271e36b1bSAlexander Aring return true; 78371e36b1bSAlexander Aring 78471e36b1bSAlexander Aring if (ro->src_addr.mode == IEEE802154_ADDR_SHORT && 78571e36b1bSAlexander Aring pan_id == ro->src_addr.pan_id && 78671e36b1bSAlexander Aring short_addr == ro->src_addr.short_addr) 78771e36b1bSAlexander Aring return true; 78871e36b1bSAlexander Aring 78971e36b1bSAlexander Aring return false; 79071e36b1bSAlexander Aring } 79171e36b1bSAlexander Aring 79271e36b1bSAlexander Aring static int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) 79371e36b1bSAlexander Aring { 79471e36b1bSAlexander Aring struct sock *sk, *prev = NULL; 79571e36b1bSAlexander Aring int ret = NET_RX_SUCCESS; 79671e36b1bSAlexander Aring __le16 pan_id, short_addr; 79771e36b1bSAlexander Aring __le64 hw_addr; 79871e36b1bSAlexander Aring 79971e36b1bSAlexander Aring /* Data frame processing */ 80071e36b1bSAlexander Aring BUG_ON(dev->type != ARPHRD_IEEE802154); 80171e36b1bSAlexander Aring 802c947f7e1SAlexander Aring pan_id = dev->ieee802154_ptr->pan_id; 803c947f7e1SAlexander Aring short_addr = dev->ieee802154_ptr->short_addr; 804c947f7e1SAlexander Aring hw_addr = dev->ieee802154_ptr->extended_addr; 80571e36b1bSAlexander Aring 80671e36b1bSAlexander Aring read_lock(&dgram_lock); 80771e36b1bSAlexander Aring sk_for_each(sk, &dgram_head) { 80871e36b1bSAlexander Aring if (ieee802154_match_sock(hw_addr, pan_id, short_addr, 80971e36b1bSAlexander Aring dgram_sk(sk))) { 81071e36b1bSAlexander Aring if (prev) { 81171e36b1bSAlexander Aring struct sk_buff *clone; 81271e36b1bSAlexander Aring 81371e36b1bSAlexander Aring clone = skb_clone(skb, GFP_ATOMIC); 81471e36b1bSAlexander Aring if (clone) 81571e36b1bSAlexander Aring dgram_rcv_skb(prev, clone); 81671e36b1bSAlexander Aring } 81771e36b1bSAlexander Aring 81871e36b1bSAlexander Aring prev = sk; 81971e36b1bSAlexander Aring } 82071e36b1bSAlexander Aring } 82171e36b1bSAlexander Aring 82271e36b1bSAlexander Aring if (prev) { 82371e36b1bSAlexander Aring dgram_rcv_skb(prev, skb); 82471e36b1bSAlexander Aring } else { 82571e36b1bSAlexander Aring kfree_skb(skb); 82671e36b1bSAlexander Aring ret = NET_RX_DROP; 82771e36b1bSAlexander Aring } 82871e36b1bSAlexander Aring read_unlock(&dgram_lock); 82971e36b1bSAlexander Aring 83071e36b1bSAlexander Aring return ret; 83171e36b1bSAlexander Aring } 83271e36b1bSAlexander Aring 83371e36b1bSAlexander Aring static int dgram_getsockopt(struct sock *sk, int level, int optname, 83471e36b1bSAlexander Aring char __user *optval, int __user *optlen) 83571e36b1bSAlexander Aring { 83671e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 83771e36b1bSAlexander Aring 83871e36b1bSAlexander Aring int val, len; 83971e36b1bSAlexander Aring 84071e36b1bSAlexander Aring if (level != SOL_IEEE802154) 84171e36b1bSAlexander Aring return -EOPNOTSUPP; 84271e36b1bSAlexander Aring 84371e36b1bSAlexander Aring if (get_user(len, optlen)) 84471e36b1bSAlexander Aring return -EFAULT; 84571e36b1bSAlexander Aring 84671e36b1bSAlexander Aring len = min_t(unsigned int, len, sizeof(int)); 84771e36b1bSAlexander Aring 84871e36b1bSAlexander Aring switch (optname) { 84971e36b1bSAlexander Aring case WPAN_WANTACK: 85071e36b1bSAlexander Aring val = ro->want_ack; 85171e36b1bSAlexander Aring break; 85271e36b1bSAlexander Aring case WPAN_SECURITY: 85371e36b1bSAlexander Aring if (!ro->secen_override) 85471e36b1bSAlexander Aring val = WPAN_SECURITY_DEFAULT; 85571e36b1bSAlexander Aring else if (ro->secen) 85671e36b1bSAlexander Aring val = WPAN_SECURITY_ON; 85771e36b1bSAlexander Aring else 85871e36b1bSAlexander Aring val = WPAN_SECURITY_OFF; 85971e36b1bSAlexander Aring break; 86071e36b1bSAlexander Aring case WPAN_SECURITY_LEVEL: 86171e36b1bSAlexander Aring if (!ro->seclevel_override) 86271e36b1bSAlexander Aring val = WPAN_SECURITY_LEVEL_DEFAULT; 86371e36b1bSAlexander Aring else 86471e36b1bSAlexander Aring val = ro->seclevel; 86571e36b1bSAlexander Aring break; 86671e36b1bSAlexander Aring default: 86771e36b1bSAlexander Aring return -ENOPROTOOPT; 86871e36b1bSAlexander Aring } 86971e36b1bSAlexander Aring 87071e36b1bSAlexander Aring if (put_user(len, optlen)) 87171e36b1bSAlexander Aring return -EFAULT; 87271e36b1bSAlexander Aring if (copy_to_user(optval, &val, len)) 87371e36b1bSAlexander Aring return -EFAULT; 87471e36b1bSAlexander Aring return 0; 87571e36b1bSAlexander Aring } 87671e36b1bSAlexander Aring 87771e36b1bSAlexander Aring static int dgram_setsockopt(struct sock *sk, int level, int optname, 87871e36b1bSAlexander Aring char __user *optval, unsigned int optlen) 87971e36b1bSAlexander Aring { 88071e36b1bSAlexander Aring struct dgram_sock *ro = dgram_sk(sk); 88171e36b1bSAlexander Aring struct net *net = sock_net(sk); 88271e36b1bSAlexander Aring int val; 88371e36b1bSAlexander Aring int err = 0; 88471e36b1bSAlexander Aring 88571e36b1bSAlexander Aring if (optlen < sizeof(int)) 88671e36b1bSAlexander Aring return -EINVAL; 88771e36b1bSAlexander Aring 88871e36b1bSAlexander Aring if (get_user(val, (int __user *)optval)) 88971e36b1bSAlexander Aring return -EFAULT; 89071e36b1bSAlexander Aring 89171e36b1bSAlexander Aring lock_sock(sk); 89271e36b1bSAlexander Aring 89371e36b1bSAlexander Aring switch (optname) { 89471e36b1bSAlexander Aring case WPAN_WANTACK: 89571e36b1bSAlexander Aring ro->want_ack = !!val; 89671e36b1bSAlexander Aring break; 89771e36b1bSAlexander Aring case WPAN_SECURITY: 89871e36b1bSAlexander Aring if (!ns_capable(net->user_ns, CAP_NET_ADMIN) && 89971e36b1bSAlexander Aring !ns_capable(net->user_ns, CAP_NET_RAW)) { 90071e36b1bSAlexander Aring err = -EPERM; 90171e36b1bSAlexander Aring break; 90271e36b1bSAlexander Aring } 90371e36b1bSAlexander Aring 90471e36b1bSAlexander Aring switch (val) { 90571e36b1bSAlexander Aring case WPAN_SECURITY_DEFAULT: 90671e36b1bSAlexander Aring ro->secen_override = 0; 90771e36b1bSAlexander Aring break; 90871e36b1bSAlexander Aring case WPAN_SECURITY_ON: 90971e36b1bSAlexander Aring ro->secen_override = 1; 91071e36b1bSAlexander Aring ro->secen = 1; 91171e36b1bSAlexander Aring break; 91271e36b1bSAlexander Aring case WPAN_SECURITY_OFF: 91371e36b1bSAlexander Aring ro->secen_override = 1; 91471e36b1bSAlexander Aring ro->secen = 0; 91571e36b1bSAlexander Aring break; 91671e36b1bSAlexander Aring default: 91771e36b1bSAlexander Aring err = -EINVAL; 91871e36b1bSAlexander Aring break; 91971e36b1bSAlexander Aring } 92071e36b1bSAlexander Aring break; 92171e36b1bSAlexander Aring case WPAN_SECURITY_LEVEL: 92271e36b1bSAlexander Aring if (!ns_capable(net->user_ns, CAP_NET_ADMIN) && 92371e36b1bSAlexander Aring !ns_capable(net->user_ns, CAP_NET_RAW)) { 92471e36b1bSAlexander Aring err = -EPERM; 92571e36b1bSAlexander Aring break; 92671e36b1bSAlexander Aring } 92771e36b1bSAlexander Aring 92871e36b1bSAlexander Aring if (val < WPAN_SECURITY_LEVEL_DEFAULT || 92971e36b1bSAlexander Aring val > IEEE802154_SCF_SECLEVEL_ENC_MIC128) { 93071e36b1bSAlexander Aring err = -EINVAL; 93171e36b1bSAlexander Aring } else if (val == WPAN_SECURITY_LEVEL_DEFAULT) { 93271e36b1bSAlexander Aring ro->seclevel_override = 0; 93371e36b1bSAlexander Aring } else { 93471e36b1bSAlexander Aring ro->seclevel_override = 1; 93571e36b1bSAlexander Aring ro->seclevel = val; 93671e36b1bSAlexander Aring } 93771e36b1bSAlexander Aring break; 93871e36b1bSAlexander Aring default: 93971e36b1bSAlexander Aring err = -ENOPROTOOPT; 94071e36b1bSAlexander Aring break; 94171e36b1bSAlexander Aring } 94271e36b1bSAlexander Aring 94371e36b1bSAlexander Aring release_sock(sk); 94471e36b1bSAlexander Aring return err; 94571e36b1bSAlexander Aring } 94671e36b1bSAlexander Aring 94771e36b1bSAlexander Aring static struct proto ieee802154_dgram_prot = { 94871e36b1bSAlexander Aring .name = "IEEE-802.15.4-MAC", 94971e36b1bSAlexander Aring .owner = THIS_MODULE, 95071e36b1bSAlexander Aring .obj_size = sizeof(struct dgram_sock), 95171e36b1bSAlexander Aring .init = dgram_init, 95271e36b1bSAlexander Aring .close = dgram_close, 95371e36b1bSAlexander Aring .bind = dgram_bind, 95471e36b1bSAlexander Aring .sendmsg = dgram_sendmsg, 95571e36b1bSAlexander Aring .recvmsg = dgram_recvmsg, 95671e36b1bSAlexander Aring .hash = dgram_hash, 95771e36b1bSAlexander Aring .unhash = dgram_unhash, 95871e36b1bSAlexander Aring .connect = dgram_connect, 95971e36b1bSAlexander Aring .disconnect = dgram_disconnect, 96071e36b1bSAlexander Aring .ioctl = dgram_ioctl, 96171e36b1bSAlexander Aring .getsockopt = dgram_getsockopt, 96271e36b1bSAlexander Aring .setsockopt = dgram_setsockopt, 96371e36b1bSAlexander Aring }; 96471e36b1bSAlexander Aring 96571e36b1bSAlexander Aring static const struct proto_ops ieee802154_dgram_ops = { 96671e36b1bSAlexander Aring .family = PF_IEEE802154, 96771e36b1bSAlexander Aring .owner = THIS_MODULE, 96871e36b1bSAlexander Aring .release = ieee802154_sock_release, 96971e36b1bSAlexander Aring .bind = ieee802154_sock_bind, 97071e36b1bSAlexander Aring .connect = ieee802154_sock_connect, 97171e36b1bSAlexander Aring .socketpair = sock_no_socketpair, 97271e36b1bSAlexander Aring .accept = sock_no_accept, 97371e36b1bSAlexander Aring .getname = sock_no_getname, 97471e36b1bSAlexander Aring .poll = datagram_poll, 97571e36b1bSAlexander Aring .ioctl = ieee802154_sock_ioctl, 97671e36b1bSAlexander Aring .listen = sock_no_listen, 97771e36b1bSAlexander Aring .shutdown = sock_no_shutdown, 97871e36b1bSAlexander Aring .setsockopt = sock_common_setsockopt, 97971e36b1bSAlexander Aring .getsockopt = sock_common_getsockopt, 98071e36b1bSAlexander Aring .sendmsg = ieee802154_sock_sendmsg, 98171e36b1bSAlexander Aring .recvmsg = sock_common_recvmsg, 98271e36b1bSAlexander Aring .mmap = sock_no_mmap, 98371e36b1bSAlexander Aring .sendpage = sock_no_sendpage, 98471e36b1bSAlexander Aring #ifdef CONFIG_COMPAT 98571e36b1bSAlexander Aring .compat_setsockopt = compat_sock_common_setsockopt, 98671e36b1bSAlexander Aring .compat_getsockopt = compat_sock_common_getsockopt, 98771e36b1bSAlexander Aring #endif 98871e36b1bSAlexander Aring }; 98971e36b1bSAlexander Aring 99071e36b1bSAlexander Aring /* Create a socket. Initialise the socket, blank the addresses 99171e36b1bSAlexander Aring * set the state. 99271e36b1bSAlexander Aring */ 99371e36b1bSAlexander Aring static int ieee802154_create(struct net *net, struct socket *sock, 99471e36b1bSAlexander Aring int protocol, int kern) 99571e36b1bSAlexander Aring { 99671e36b1bSAlexander Aring struct sock *sk; 99771e36b1bSAlexander Aring int rc; 99871e36b1bSAlexander Aring struct proto *proto; 99971e36b1bSAlexander Aring const struct proto_ops *ops; 100071e36b1bSAlexander Aring 100171e36b1bSAlexander Aring if (!net_eq(net, &init_net)) 100271e36b1bSAlexander Aring return -EAFNOSUPPORT; 100371e36b1bSAlexander Aring 100471e36b1bSAlexander Aring switch (sock->type) { 100571e36b1bSAlexander Aring case SOCK_RAW: 100671e36b1bSAlexander Aring proto = &ieee802154_raw_prot; 100771e36b1bSAlexander Aring ops = &ieee802154_raw_ops; 100871e36b1bSAlexander Aring break; 100971e36b1bSAlexander Aring case SOCK_DGRAM: 101071e36b1bSAlexander Aring proto = &ieee802154_dgram_prot; 101171e36b1bSAlexander Aring ops = &ieee802154_dgram_ops; 101271e36b1bSAlexander Aring break; 101371e36b1bSAlexander Aring default: 101471e36b1bSAlexander Aring rc = -ESOCKTNOSUPPORT; 101571e36b1bSAlexander Aring goto out; 101671e36b1bSAlexander Aring } 101771e36b1bSAlexander Aring 101871e36b1bSAlexander Aring rc = -ENOMEM; 101911aa9c28SEric W. Biederman sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto, kern); 102071e36b1bSAlexander Aring if (!sk) 102171e36b1bSAlexander Aring goto out; 102271e36b1bSAlexander Aring rc = 0; 102371e36b1bSAlexander Aring 102471e36b1bSAlexander Aring sock->ops = ops; 102571e36b1bSAlexander Aring 102671e36b1bSAlexander Aring sock_init_data(sock, sk); 102771e36b1bSAlexander Aring /* FIXME: sk->sk_destruct */ 102871e36b1bSAlexander Aring sk->sk_family = PF_IEEE802154; 102971e36b1bSAlexander Aring 103071e36b1bSAlexander Aring /* Checksums on by default */ 103171e36b1bSAlexander Aring sock_set_flag(sk, SOCK_ZAPPED); 103271e36b1bSAlexander Aring 1033086c653fSCraig Gallek if (sk->sk_prot->hash) { 1034086c653fSCraig Gallek rc = sk->sk_prot->hash(sk); 1035086c653fSCraig Gallek if (rc) { 1036086c653fSCraig Gallek sk_common_release(sk); 1037086c653fSCraig Gallek goto out; 1038086c653fSCraig Gallek } 1039086c653fSCraig Gallek } 104071e36b1bSAlexander Aring 104171e36b1bSAlexander Aring if (sk->sk_prot->init) { 104271e36b1bSAlexander Aring rc = sk->sk_prot->init(sk); 104371e36b1bSAlexander Aring if (rc) 104471e36b1bSAlexander Aring sk_common_release(sk); 104571e36b1bSAlexander Aring } 104671e36b1bSAlexander Aring out: 104771e36b1bSAlexander Aring return rc; 104871e36b1bSAlexander Aring } 104971e36b1bSAlexander Aring 105071e36b1bSAlexander Aring static const struct net_proto_family ieee802154_family_ops = { 105171e36b1bSAlexander Aring .family = PF_IEEE802154, 105271e36b1bSAlexander Aring .create = ieee802154_create, 105371e36b1bSAlexander Aring .owner = THIS_MODULE, 105471e36b1bSAlexander Aring }; 105571e36b1bSAlexander Aring 105671e36b1bSAlexander Aring static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, 105771e36b1bSAlexander Aring struct packet_type *pt, struct net_device *orig_dev) 105871e36b1bSAlexander Aring { 105971e36b1bSAlexander Aring if (!netif_running(dev)) 106071e36b1bSAlexander Aring goto drop; 106171e36b1bSAlexander Aring pr_debug("got frame, type %d, dev %p\n", dev->type, dev); 106271e36b1bSAlexander Aring #ifdef DEBUG 106371e36b1bSAlexander Aring print_hex_dump_bytes("ieee802154_rcv ", 106471e36b1bSAlexander Aring DUMP_PREFIX_NONE, skb->data, skb->len); 106571e36b1bSAlexander Aring #endif 106671e36b1bSAlexander Aring 106771e36b1bSAlexander Aring if (!net_eq(dev_net(dev), &init_net)) 106871e36b1bSAlexander Aring goto drop; 106971e36b1bSAlexander Aring 107071e36b1bSAlexander Aring ieee802154_raw_deliver(dev, skb); 107171e36b1bSAlexander Aring 107271e36b1bSAlexander Aring if (dev->type != ARPHRD_IEEE802154) 107371e36b1bSAlexander Aring goto drop; 107471e36b1bSAlexander Aring 107571e36b1bSAlexander Aring if (skb->pkt_type != PACKET_OTHERHOST) 107671e36b1bSAlexander Aring return ieee802154_dgram_deliver(dev, skb); 107771e36b1bSAlexander Aring 107871e36b1bSAlexander Aring drop: 107971e36b1bSAlexander Aring kfree_skb(skb); 108071e36b1bSAlexander Aring return NET_RX_DROP; 108171e36b1bSAlexander Aring } 108271e36b1bSAlexander Aring 108371e36b1bSAlexander Aring static struct packet_type ieee802154_packet_type = { 108471e36b1bSAlexander Aring .type = htons(ETH_P_IEEE802154), 108571e36b1bSAlexander Aring .func = ieee802154_rcv, 108671e36b1bSAlexander Aring }; 108771e36b1bSAlexander Aring 108871e36b1bSAlexander Aring static int __init af_ieee802154_init(void) 108971e36b1bSAlexander Aring { 109071e36b1bSAlexander Aring int rc = -EINVAL; 109171e36b1bSAlexander Aring 109271e36b1bSAlexander Aring rc = proto_register(&ieee802154_raw_prot, 1); 109371e36b1bSAlexander Aring if (rc) 109471e36b1bSAlexander Aring goto out; 109571e36b1bSAlexander Aring 109671e36b1bSAlexander Aring rc = proto_register(&ieee802154_dgram_prot, 1); 109771e36b1bSAlexander Aring if (rc) 109871e36b1bSAlexander Aring goto err_dgram; 109971e36b1bSAlexander Aring 110071e36b1bSAlexander Aring /* Tell SOCKET that we are alive */ 110171e36b1bSAlexander Aring rc = sock_register(&ieee802154_family_ops); 110271e36b1bSAlexander Aring if (rc) 110371e36b1bSAlexander Aring goto err_sock; 110471e36b1bSAlexander Aring dev_add_pack(&ieee802154_packet_type); 110571e36b1bSAlexander Aring 110671e36b1bSAlexander Aring rc = 0; 110771e36b1bSAlexander Aring goto out; 110871e36b1bSAlexander Aring 110971e36b1bSAlexander Aring err_sock: 111071e36b1bSAlexander Aring proto_unregister(&ieee802154_dgram_prot); 111171e36b1bSAlexander Aring err_dgram: 111271e36b1bSAlexander Aring proto_unregister(&ieee802154_raw_prot); 111371e36b1bSAlexander Aring out: 111471e36b1bSAlexander Aring return rc; 111571e36b1bSAlexander Aring } 111671e36b1bSAlexander Aring 111771e36b1bSAlexander Aring static void __exit af_ieee802154_remove(void) 111871e36b1bSAlexander Aring { 111971e36b1bSAlexander Aring dev_remove_pack(&ieee802154_packet_type); 112071e36b1bSAlexander Aring sock_unregister(PF_IEEE802154); 112171e36b1bSAlexander Aring proto_unregister(&ieee802154_dgram_prot); 112271e36b1bSAlexander Aring proto_unregister(&ieee802154_raw_prot); 112371e36b1bSAlexander Aring } 112471e36b1bSAlexander Aring 112571e36b1bSAlexander Aring module_init(af_ieee802154_init); 112671e36b1bSAlexander Aring module_exit(af_ieee802154_remove); 112771e36b1bSAlexander Aring 112871e36b1bSAlexander Aring MODULE_LICENSE("GPL"); 112971e36b1bSAlexander Aring MODULE_ALIAS_NETPROTO(PF_IEEE802154); 1130