1 /* 2 * Raw IEEE 802.15.4 sockets 3 * 4 * Copyright 2007, 2008 Siemens AG 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 8 * as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Written by: 20 * Sergey Lapin <slapin@ossfans.org> 21 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> 22 */ 23 24 #include <linux/net.h> 25 #include <linux/module.h> 26 #include <linux/if_arp.h> 27 #include <linux/list.h> 28 #include <linux/slab.h> 29 #include <net/sock.h> 30 #include <net/af_ieee802154.h> 31 32 #include "af802154.h" 33 34 static HLIST_HEAD(raw_head); 35 static DEFINE_RWLOCK(raw_lock); 36 raw_hash(struct sock * sk)37 static void raw_hash(struct sock *sk) 38 { 39 write_lock_bh(&raw_lock); 40 sk_add_node(sk, &raw_head); 41 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); 42 write_unlock_bh(&raw_lock); 43 } 44 raw_unhash(struct sock * sk)45 static void raw_unhash(struct sock *sk) 46 { 47 write_lock_bh(&raw_lock); 48 if (sk_del_node_init(sk)) 49 sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); 50 write_unlock_bh(&raw_lock); 51 } 52 raw_close(struct sock * sk,long timeout)53 static void raw_close(struct sock *sk, long timeout) 54 { 55 sk_common_release(sk); 56 } 57 raw_bind(struct sock * sk,struct sockaddr * uaddr,int len)58 static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int len) 59 { 60 struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; 61 int err = 0; 62 struct net_device *dev = NULL; 63 64 if (len < sizeof(*addr)) 65 return -EINVAL; 66 67 if (addr->family != AF_IEEE802154) 68 return -EINVAL; 69 70 lock_sock(sk); 71 72 dev = ieee802154_get_dev(sock_net(sk), &addr->addr); 73 if (!dev) { 74 err = -ENODEV; 75 goto out; 76 } 77 78 if (dev->type != ARPHRD_IEEE802154) { 79 err = -ENODEV; 80 goto out_put; 81 } 82 83 sk->sk_bound_dev_if = dev->ifindex; 84 sk_dst_reset(sk); 85 86 out_put: 87 dev_put(dev); 88 out: 89 release_sock(sk); 90 91 return err; 92 } 93 raw_connect(struct sock * sk,struct sockaddr * uaddr,int addr_len)94 static int raw_connect(struct sock *sk, struct sockaddr *uaddr, 95 int addr_len) 96 { 97 return -ENOTSUPP; 98 } 99 raw_disconnect(struct sock * sk,int flags)100 static int raw_disconnect(struct sock *sk, int flags) 101 { 102 return 0; 103 } 104 raw_sendmsg(struct kiocb * iocb,struct sock * sk,struct msghdr * msg,size_t size)105 static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 106 size_t size) 107 { 108 struct net_device *dev; 109 unsigned int mtu; 110 struct sk_buff *skb; 111 int hlen, tlen; 112 int err; 113 114 if (msg->msg_flags & MSG_OOB) { 115 pr_debug("msg->msg_flags = 0x%x\n", msg->msg_flags); 116 return -EOPNOTSUPP; 117 } 118 119 lock_sock(sk); 120 if (!sk->sk_bound_dev_if) 121 dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); 122 else 123 dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); 124 release_sock(sk); 125 126 if (!dev) { 127 pr_debug("no dev\n"); 128 err = -ENXIO; 129 goto out; 130 } 131 132 mtu = dev->mtu; 133 pr_debug("name = %s, mtu = %u\n", dev->name, mtu); 134 135 if (size > mtu) { 136 pr_debug("size = %Zu, mtu = %u\n", size, mtu); 137 err = -EINVAL; 138 goto out_dev; 139 } 140 141 hlen = LL_RESERVED_SPACE(dev); 142 tlen = dev->needed_tailroom; 143 skb = sock_alloc_send_skb(sk, hlen + tlen + size, 144 msg->msg_flags & MSG_DONTWAIT, &err); 145 if (!skb) 146 goto out_dev; 147 148 skb_reserve(skb, hlen); 149 150 skb_reset_mac_header(skb); 151 skb_reset_network_header(skb); 152 153 err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); 154 if (err < 0) 155 goto out_skb; 156 157 skb->dev = dev; 158 skb->sk = sk; 159 skb->protocol = htons(ETH_P_IEEE802154); 160 161 dev_put(dev); 162 163 err = dev_queue_xmit(skb); 164 if (err > 0) 165 err = net_xmit_errno(err); 166 167 return err ?: size; 168 169 out_skb: 170 kfree_skb(skb); 171 out_dev: 172 dev_put(dev); 173 out: 174 return err; 175 } 176 raw_recvmsg(struct kiocb * iocb,struct sock * sk,struct msghdr * msg,size_t len,int noblock,int flags,int * addr_len)177 static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, 178 size_t len, int noblock, int flags, int *addr_len) 179 { 180 size_t copied = 0; 181 int err = -EOPNOTSUPP; 182 struct sk_buff *skb; 183 184 skb = skb_recv_datagram(sk, flags, noblock, &err); 185 if (!skb) 186 goto out; 187 188 copied = skb->len; 189 if (len < copied) { 190 msg->msg_flags |= MSG_TRUNC; 191 copied = len; 192 } 193 194 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); 195 if (err) 196 goto done; 197 198 sock_recv_ts_and_drops(msg, sk, skb); 199 200 if (flags & MSG_TRUNC) 201 copied = skb->len; 202 done: 203 skb_free_datagram(sk, skb); 204 out: 205 if (err) 206 return err; 207 return copied; 208 } 209 raw_rcv_skb(struct sock * sk,struct sk_buff * skb)210 static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) 211 { 212 if (sock_queue_rcv_skb(sk, skb) < 0) { 213 kfree_skb(skb); 214 return NET_RX_DROP; 215 } 216 217 return NET_RX_SUCCESS; 218 } 219 220 ieee802154_raw_deliver(struct net_device * dev,struct sk_buff * skb)221 void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb) 222 { 223 struct sock *sk; 224 225 read_lock(&raw_lock); 226 sk_for_each(sk, &raw_head) { 227 bh_lock_sock(sk); 228 if (!sk->sk_bound_dev_if || 229 sk->sk_bound_dev_if == dev->ifindex) { 230 231 struct sk_buff *clone; 232 233 clone = skb_clone(skb, GFP_ATOMIC); 234 if (clone) 235 raw_rcv_skb(sk, clone); 236 } 237 bh_unlock_sock(sk); 238 } 239 read_unlock(&raw_lock); 240 } 241 raw_getsockopt(struct sock * sk,int level,int optname,char __user * optval,int __user * optlen)242 static int raw_getsockopt(struct sock *sk, int level, int optname, 243 char __user *optval, int __user *optlen) 244 { 245 return -EOPNOTSUPP; 246 } 247 raw_setsockopt(struct sock * sk,int level,int optname,char __user * optval,unsigned int optlen)248 static int raw_setsockopt(struct sock *sk, int level, int optname, 249 char __user *optval, unsigned int optlen) 250 { 251 return -EOPNOTSUPP; 252 } 253 254 struct proto ieee802154_raw_prot = { 255 .name = "IEEE-802.15.4-RAW", 256 .owner = THIS_MODULE, 257 .obj_size = sizeof(struct sock), 258 .close = raw_close, 259 .bind = raw_bind, 260 .sendmsg = raw_sendmsg, 261 .recvmsg = raw_recvmsg, 262 .hash = raw_hash, 263 .unhash = raw_unhash, 264 .connect = raw_connect, 265 .disconnect = raw_disconnect, 266 .getsockopt = raw_getsockopt, 267 .setsockopt = raw_setsockopt, 268 }; 269 270