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/* 44 * Utility function for families 45 */ 46struct net_device *ieee802154_get_dev(struct net *net, 47 struct ieee802154_addr *addr) 48{ 49 struct net_device *dev = NULL; 50 struct net_device *tmp; 51 u16 pan_id, short_addr; 52 53 switch (addr->addr_type) { 54 case IEEE802154_ADDR_LONG: 55 rtnl_lock(); 56 dev = dev_getbyhwaddr(net, ARPHRD_IEEE802154, addr->hwaddr); 57 if (dev) 58 dev_hold(dev); 59 rtnl_unlock(); 60 break; 61 case IEEE802154_ADDR_SHORT: 62 if (addr->pan_id == 0xffff || 63 addr->short_addr == IEEE802154_ADDR_UNDEF || 64 addr->short_addr == 0xffff) 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_warning("Unsupported ieee802154 address type: %d\n", 89 addr->addr_type); 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/* 240 * Create a socket. Initialise the socket, blank the addresses 241 * set the state. 242 */ 243static int ieee802154_create(struct net *net, struct socket *sock, 244 int protocol, int kern) 245{ 246 struct sock *sk; 247 int rc; 248 struct proto *proto; 249 const struct proto_ops *ops; 250 251 if (!net_eq(net, &init_net)) 252 return -EAFNOSUPPORT; 253 254 switch (sock->type) { 255 case SOCK_RAW: 256 proto = &ieee802154_raw_prot; 257 ops = &ieee802154_raw_ops; 258 break; 259 case SOCK_DGRAM: 260 proto = &ieee802154_dgram_prot; 261 ops = &ieee802154_dgram_ops; 262 break; 263 default: 264 rc = -ESOCKTNOSUPPORT; 265 goto out; 266 } 267 268 rc = -ENOMEM; 269 sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto); 270 if (!sk) 271 goto out; 272 rc = 0; 273 274 sock->ops = ops; 275 276 sock_init_data(sock, sk); 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 return -ENODEV; 305 pr_debug("got frame, type %d, dev %p\n", dev->type, dev); 306#ifdef DEBUG 307 print_hex_dump_bytes("ieee802154_rcv ", DUMP_PREFIX_NONE, skb->data, skb->len); 308#endif 309 310 if (!net_eq(dev_net(dev), &init_net)) 311 goto drop; 312 313 ieee802154_raw_deliver(dev, skb); 314 315 if (dev->type != ARPHRD_IEEE802154) 316 goto drop; 317 318 if (skb->pkt_type != PACKET_OTHERHOST) 319 return ieee802154_dgram_deliver(dev, skb); 320 321drop: 322 kfree_skb(skb); 323 return NET_RX_DROP; 324} 325 326 327static struct packet_type ieee802154_packet_type = { 328 .type = __constant_htons(ETH_P_IEEE802154), 329 .func = ieee802154_rcv, 330}; 331 332static int __init af_ieee802154_init(void) 333{ 334 int rc = -EINVAL; 335 336 rc = proto_register(&ieee802154_raw_prot, 1); 337 if (rc) 338 goto out; 339 340 rc = proto_register(&ieee802154_dgram_prot, 1); 341 if (rc) 342 goto err_dgram; 343 344 /* Tell SOCKET that we are alive */ 345 rc = sock_register(&ieee802154_family_ops); 346 if (rc) 347 goto err_sock; 348 dev_add_pack(&ieee802154_packet_type); 349 350 rc = 0; 351 goto out; 352 353err_sock: 354 proto_unregister(&ieee802154_dgram_prot); 355err_dgram: 356 proto_unregister(&ieee802154_raw_prot); 357out: 358 return rc; 359} 360static void __exit af_ieee802154_remove(void) 361{ 362 dev_remove_pack(&ieee802154_packet_type); 363 sock_unregister(PF_IEEE802154); 364 proto_unregister(&ieee802154_dgram_prot); 365 proto_unregister(&ieee802154_raw_prot); 366} 367 368module_init(af_ieee802154_init); 369module_exit(af_ieee802154_remove); 370 371MODULE_LICENSE("GPL"); 372MODULE_ALIAS_NETPROTO(PF_IEEE802154); 373