1/* 2 * IEEE802154.4 socket interface 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 * Maxim Gorbachyov <maxim.gorbachev@siemens.com> 22 */ 23 24#include <linux/net.h> 25#include <linux/capability.h> 26#include <linux/module.h> 27#include <linux/if_arp.h> 28#include <linux/if.h> 29#include <linux/termios.h> /* For TIOCOUTQ/INQ */ 30#include <linux/list.h> 31#include <linux/slab.h> 32#include <net/datalink.h> 33#include <net/psnap.h> 34#include <net/sock.h> 35#include <net/tcp_states.h> 36#include <net/route.h> 37 38#include <net/af_ieee802154.h> 39#include <net/ieee802154_netdev.h> 40 41#include "af802154.h" 42 43/* Utility function for families */ 44struct net_device* 45ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr) 46{ 47 struct net_device *dev = NULL; 48 struct net_device *tmp; 49 __le16 pan_id, short_addr; 50 u8 hwaddr[IEEE802154_ADDR_LEN]; 51 52 switch (addr->mode) { 53 case IEEE802154_ADDR_LONG: 54 ieee802154_devaddr_to_raw(hwaddr, addr->extended_addr); 55 rcu_read_lock(); 56 dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, hwaddr); 57 if (dev) 58 dev_hold(dev); 59 rcu_read_unlock(); 60 break; 61 case IEEE802154_ADDR_SHORT: 62 if (addr->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST) || 63 addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) || 64 addr->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) 65 break; 66 67 rtnl_lock(); 68 69 for_each_netdev(net, tmp) { 70 if (tmp->type != ARPHRD_IEEE802154) 71 continue; 72 73 pan_id = ieee802154_mlme_ops(tmp)->get_pan_id(tmp); 74 short_addr = 75 ieee802154_mlme_ops(tmp)->get_short_addr(tmp); 76 77 if (pan_id == addr->pan_id && 78 short_addr == addr->short_addr) { 79 dev = tmp; 80 dev_hold(dev); 81 break; 82 } 83 } 84 85 rtnl_unlock(); 86 break; 87 default: 88 pr_warn("Unsupported ieee802154 address type: %d\n", 89 addr->mode); 90 break; 91 } 92 93 return dev; 94} 95 96static int ieee802154_sock_release(struct socket *sock) 97{ 98 struct sock *sk = sock->sk; 99 100 if (sk) { 101 sock->sk = NULL; 102 sk->sk_prot->close(sk, 0); 103 } 104 return 0; 105} 106static int ieee802154_sock_sendmsg(struct kiocb *iocb, struct socket *sock, 107 struct msghdr *msg, size_t len) 108{ 109 struct sock *sk = sock->sk; 110 111 return sk->sk_prot->sendmsg(iocb, sk, msg, len); 112} 113 114static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr, 115 int addr_len) 116{ 117 struct sock *sk = sock->sk; 118 119 if (sk->sk_prot->bind) 120 return sk->sk_prot->bind(sk, uaddr, addr_len); 121 122 return sock_no_bind(sock, uaddr, addr_len); 123} 124 125static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr, 126 int addr_len, int flags) 127{ 128 struct sock *sk = sock->sk; 129 130 if (addr_len < sizeof(uaddr->sa_family)) 131 return -EINVAL; 132 133 if (uaddr->sa_family == AF_UNSPEC) 134 return sk->sk_prot->disconnect(sk, flags); 135 136 return sk->sk_prot->connect(sk, uaddr, addr_len); 137} 138 139static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, 140 unsigned int cmd) 141{ 142 struct ifreq ifr; 143 int ret = -ENOIOCTLCMD; 144 struct net_device *dev; 145 146 if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) 147 return -EFAULT; 148 149 ifr.ifr_name[IFNAMSIZ-1] = 0; 150 151 dev_load(sock_net(sk), ifr.ifr_name); 152 dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); 153 154 if (!dev) 155 return -ENODEV; 156 157 if (dev->type == ARPHRD_IEEE802154 && dev->netdev_ops->ndo_do_ioctl) 158 ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); 159 160 if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) 161 ret = -EFAULT; 162 dev_put(dev); 163 164 return ret; 165} 166 167static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd, 168 unsigned long arg) 169{ 170 struct sock *sk = sock->sk; 171 172 switch (cmd) { 173 case SIOCGSTAMP: 174 return sock_get_timestamp(sk, (struct timeval __user *)arg); 175 case SIOCGSTAMPNS: 176 return sock_get_timestampns(sk, (struct timespec __user *)arg); 177 case SIOCGIFADDR: 178 case SIOCSIFADDR: 179 return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg, 180 cmd); 181 default: 182 if (!sk->sk_prot->ioctl) 183 return -ENOIOCTLCMD; 184 return sk->sk_prot->ioctl(sk, cmd, arg); 185 } 186} 187 188static const struct proto_ops ieee802154_raw_ops = { 189 .family = PF_IEEE802154, 190 .owner = THIS_MODULE, 191 .release = ieee802154_sock_release, 192 .bind = ieee802154_sock_bind, 193 .connect = ieee802154_sock_connect, 194 .socketpair = sock_no_socketpair, 195 .accept = sock_no_accept, 196 .getname = sock_no_getname, 197 .poll = datagram_poll, 198 .ioctl = ieee802154_sock_ioctl, 199 .listen = sock_no_listen, 200 .shutdown = sock_no_shutdown, 201 .setsockopt = sock_common_setsockopt, 202 .getsockopt = sock_common_getsockopt, 203 .sendmsg = ieee802154_sock_sendmsg, 204 .recvmsg = sock_common_recvmsg, 205 .mmap = sock_no_mmap, 206 .sendpage = sock_no_sendpage, 207#ifdef CONFIG_COMPAT 208 .compat_setsockopt = compat_sock_common_setsockopt, 209 .compat_getsockopt = compat_sock_common_getsockopt, 210#endif 211}; 212 213static const struct proto_ops ieee802154_dgram_ops = { 214 .family = PF_IEEE802154, 215 .owner = THIS_MODULE, 216 .release = ieee802154_sock_release, 217 .bind = ieee802154_sock_bind, 218 .connect = ieee802154_sock_connect, 219 .socketpair = sock_no_socketpair, 220 .accept = sock_no_accept, 221 .getname = sock_no_getname, 222 .poll = datagram_poll, 223 .ioctl = ieee802154_sock_ioctl, 224 .listen = sock_no_listen, 225 .shutdown = sock_no_shutdown, 226 .setsockopt = sock_common_setsockopt, 227 .getsockopt = sock_common_getsockopt, 228 .sendmsg = ieee802154_sock_sendmsg, 229 .recvmsg = sock_common_recvmsg, 230 .mmap = sock_no_mmap, 231 .sendpage = sock_no_sendpage, 232#ifdef CONFIG_COMPAT 233 .compat_setsockopt = compat_sock_common_setsockopt, 234 .compat_getsockopt = compat_sock_common_getsockopt, 235#endif 236}; 237 238 239/* Create a socket. Initialise the socket, blank the addresses 240 * set the state. 241 */ 242static int ieee802154_create(struct net *net, struct socket *sock, 243 int protocol, int kern) 244{ 245 struct sock *sk; 246 int rc; 247 struct proto *proto; 248 const struct proto_ops *ops; 249 250 if (!net_eq(net, &init_net)) 251 return -EAFNOSUPPORT; 252 253 switch (sock->type) { 254 case SOCK_RAW: 255 proto = &ieee802154_raw_prot; 256 ops = &ieee802154_raw_ops; 257 break; 258 case SOCK_DGRAM: 259 proto = &ieee802154_dgram_prot; 260 ops = &ieee802154_dgram_ops; 261 break; 262 default: 263 rc = -ESOCKTNOSUPPORT; 264 goto out; 265 } 266 267 rc = -ENOMEM; 268 sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto); 269 if (!sk) 270 goto out; 271 rc = 0; 272 273 sock->ops = ops; 274 275 sock_init_data(sock, sk); 276 /* FIXME: sk->sk_destruct */ 277 sk->sk_family = PF_IEEE802154; 278 279 /* Checksums on by default */ 280 sock_set_flag(sk, SOCK_ZAPPED); 281 282 if (sk->sk_prot->hash) 283 sk->sk_prot->hash(sk); 284 285 if (sk->sk_prot->init) { 286 rc = sk->sk_prot->init(sk); 287 if (rc) 288 sk_common_release(sk); 289 } 290out: 291 return rc; 292} 293 294static const struct net_proto_family ieee802154_family_ops = { 295 .family = PF_IEEE802154, 296 .create = ieee802154_create, 297 .owner = THIS_MODULE, 298}; 299 300static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, 301 struct packet_type *pt, struct net_device *orig_dev) 302{ 303 if (!netif_running(dev)) 304 goto drop; 305 pr_debug("got frame, type %d, dev %p\n", dev->type, dev); 306#ifdef DEBUG 307 print_hex_dump_bytes("ieee802154_rcv ", 308 DUMP_PREFIX_NONE, skb->data, skb->len); 309#endif 310 311 if (!net_eq(dev_net(dev), &init_net)) 312 goto drop; 313 314 ieee802154_raw_deliver(dev, skb); 315 316 if (dev->type != ARPHRD_IEEE802154) 317 goto drop; 318 319 if (skb->pkt_type != PACKET_OTHERHOST) 320 return ieee802154_dgram_deliver(dev, skb); 321 322drop: 323 kfree_skb(skb); 324 return NET_RX_DROP; 325} 326 327 328static struct packet_type ieee802154_packet_type = { 329 .type = htons(ETH_P_IEEE802154), 330 .func = ieee802154_rcv, 331}; 332 333static int __init af_ieee802154_init(void) 334{ 335 int rc = -EINVAL; 336 337 rc = proto_register(&ieee802154_raw_prot, 1); 338 if (rc) 339 goto out; 340 341 rc = proto_register(&ieee802154_dgram_prot, 1); 342 if (rc) 343 goto err_dgram; 344 345 /* Tell SOCKET that we are alive */ 346 rc = sock_register(&ieee802154_family_ops); 347 if (rc) 348 goto err_sock; 349 dev_add_pack(&ieee802154_packet_type); 350 351 rc = 0; 352 goto out; 353 354err_sock: 355 proto_unregister(&ieee802154_dgram_prot); 356err_dgram: 357 proto_unregister(&ieee802154_raw_prot); 358out: 359 return rc; 360} 361static void __exit af_ieee802154_remove(void) 362{ 363 dev_remove_pack(&ieee802154_packet_type); 364 sock_unregister(PF_IEEE802154); 365 proto_unregister(&ieee802154_dgram_prot); 366 proto_unregister(&ieee802154_raw_prot); 367} 368 369module_init(af_ieee802154_init); 370module_exit(af_ieee802154_remove); 371 372MODULE_LICENSE("GPL"); 373MODULE_ALIAS_NETPROTO(PF_IEEE802154); 374