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