Pull acpi_os_free into release branch
[pandora-kernel.git] / net / bluetooth / bnep / core.c
1 /* 
2    BNEP implementation for Linux Bluetooth stack (BlueZ).
3    Copyright (C) 2001-2002 Inventel Systemes
4    Written 2001-2002 by
5         ClĂ©ment Moreau <clement.moreau@inventel.fr>
6         David Libault  <david.libault@inventel.fr>
7
8    Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License version 2 as
12    published by the Free Software Foundation;
13
14    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
17    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
18    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
19    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
20    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
21    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
24    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
25    SOFTWARE IS DISCLAIMED.
26 */
27
28 /*
29  * $Id: core.c,v 1.20 2002/08/04 21:23:58 maxk Exp $
30  */ 
31
32 #include <linux/module.h>
33
34 #include <linux/kernel.h>
35 #include <linux/sched.h>
36 #include <linux/signal.h>
37 #include <linux/init.h>
38 #include <linux/wait.h>
39 #include <linux/errno.h>
40 #include <linux/smp_lock.h>
41 #include <linux/net.h>
42 #include <net/sock.h>
43
44 #include <linux/socket.h>
45 #include <linux/file.h>
46
47 #include <linux/netdevice.h>
48 #include <linux/etherdevice.h>
49 #include <linux/skbuff.h>
50
51 #include <asm/unaligned.h>
52
53 #include <net/bluetooth/bluetooth.h>
54 #include <net/bluetooth/l2cap.h>
55
56 #include "bnep.h"
57
58 #ifndef CONFIG_BT_BNEP_DEBUG
59 #undef  BT_DBG
60 #define BT_DBG(D...)
61 #endif
62
63 #define VERSION "1.2"
64
65 static LIST_HEAD(bnep_session_list);
66 static DECLARE_RWSEM(bnep_session_sem);
67
68 static struct bnep_session *__bnep_get_session(u8 *dst)
69 {
70         struct bnep_session *s;
71         struct list_head *p;
72
73         BT_DBG("");
74
75         list_for_each(p, &bnep_session_list) {
76                 s = list_entry(p, struct bnep_session, list);   
77                 if (!compare_ether_addr(dst, s->eh.h_source))
78                         return s;
79         }
80         return NULL;
81 }
82
83 static void __bnep_link_session(struct bnep_session *s)
84 {
85         /* It's safe to call __module_get() here because sessions are added
86            by the socket layer which has to hold the refference to this module.
87          */
88         __module_get(THIS_MODULE);
89         list_add(&s->list, &bnep_session_list); 
90 }
91
92 static void __bnep_unlink_session(struct bnep_session *s)
93 {
94         list_del(&s->list);
95         module_put(THIS_MODULE);
96 }
97
98 static int bnep_send(struct bnep_session *s, void *data, size_t len)
99 {
100         struct socket *sock = s->sock;
101         struct kvec iv = { data, len };
102
103         return kernel_sendmsg(sock, &s->msg, &iv, 1, len);
104 }
105
106 static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
107 {
108         struct bnep_control_rsp rsp;
109         rsp.type = BNEP_CONTROL;
110         rsp.ctrl = ctrl;
111         rsp.resp = htons(resp);
112         return bnep_send(s, &rsp, sizeof(rsp));
113 }
114
115 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
116 static inline void bnep_set_default_proto_filter(struct bnep_session *s)
117 {
118         /* (IPv4, ARP)  */
119         s->proto_filter[0].start = htons(0x0800);
120         s->proto_filter[0].end   = htons(0x0806);
121         /* (RARP, AppleTalk) */
122         s->proto_filter[1].start = htons(0x8035);
123         s->proto_filter[1].end   = htons(0x80F3);
124         /* (IPX, IPv6) */
125         s->proto_filter[2].start = htons(0x8137);
126         s->proto_filter[2].end   = htons(0x86DD);
127 }
128 #endif
129
130 static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
131 {
132         int n;
133
134         if (len < 2)
135                 return -EILSEQ;
136
137         n = ntohs(get_unaligned(data));
138         data++; len -= 2;
139
140         if (len < n)
141                 return -EILSEQ;
142
143         BT_DBG("filter len %d", n);
144
145 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
146         n /= 4;
147         if (n <= BNEP_MAX_PROTO_FILTERS) {
148                 struct bnep_proto_filter *f = s->proto_filter;
149                 int i;
150
151                 for (i = 0; i < n; i++) {
152                         f[i].start = get_unaligned(data++);
153                         f[i].end   = get_unaligned(data++);
154
155                         BT_DBG("proto filter start %d end %d",
156                                 f[i].start, f[i].end);
157                 }
158
159                 if (i < BNEP_MAX_PROTO_FILTERS)
160                         memset(f + i, 0, sizeof(*f));
161
162                 if (n == 0)
163                         bnep_set_default_proto_filter(s);
164
165                 bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_SUCCESS);
166         } else {
167                 bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_LIMIT_REACHED);
168         }
169 #else
170         bnep_send_rsp(s, BNEP_FILTER_NET_TYPE_RSP, BNEP_FILTER_UNSUPPORTED_REQ);
171 #endif
172         return 0;
173 }
174
175 static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
176 {
177         int n;
178
179         if (len < 2)
180                 return -EILSEQ;
181
182         n = ntohs(get_unaligned((u16 *) data)); 
183         data += 2; len -= 2;
184
185         if (len < n)
186                 return -EILSEQ;
187
188         BT_DBG("filter len %d", n);
189
190 #ifdef CONFIG_BT_BNEP_MC_FILTER
191         n /= (ETH_ALEN * 2);
192
193         if (n > 0) {
194                 s->mc_filter = 0;
195
196                 /* Always send broadcast */
197                 set_bit(bnep_mc_hash(s->dev->broadcast), (ulong *) &s->mc_filter);
198
199                 /* Add address ranges to the multicast hash */
200                 for (; n > 0; n--) {
201                         u8 a1[6], *a2;
202
203                         memcpy(a1, data, ETH_ALEN); data += ETH_ALEN;
204                         a2 = data; data += ETH_ALEN;
205         
206                         BT_DBG("mc filter %s -> %s",
207                                 batostr((void *) a1), batostr((void *) a2));
208
209                         #define INCA(a) { int i = 5; while (i >=0 && ++a[i--] == 0); }
210
211                         /* Iterate from a1 to a2 */
212                         set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
213                         while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) {
214                                 INCA(a1);
215                                 set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
216                         }
217                 }
218         }
219
220         BT_DBG("mc filter hash 0x%llx", s->mc_filter);
221
222         bnep_send_rsp(s, BNEP_FILTER_MULTI_ADDR_RSP, BNEP_SUCCESS);
223 #else
224         bnep_send_rsp(s, BNEP_FILTER_MULTI_ADDR_RSP, BNEP_FILTER_UNSUPPORTED_REQ);
225 #endif
226         return 0;
227 }
228
229 static int bnep_rx_control(struct bnep_session *s, void *data, int len)
230 {
231         u8  cmd = *(u8 *)data;
232         int err = 0;
233
234         data++; len--;
235
236         switch (cmd) {
237         case BNEP_CMD_NOT_UNDERSTOOD:
238         case BNEP_SETUP_CONN_REQ:
239         case BNEP_SETUP_CONN_RSP:
240         case BNEP_FILTER_NET_TYPE_RSP:
241         case BNEP_FILTER_MULTI_ADDR_RSP:
242                 /* Ignore these for now */
243                 break;
244
245         case BNEP_FILTER_NET_TYPE_SET:
246                 err = bnep_ctrl_set_netfilter(s, data, len);
247                 break;
248
249         case BNEP_FILTER_MULTI_ADDR_SET:
250                 err = bnep_ctrl_set_mcfilter(s, data, len);
251                 break;
252
253         default: {
254                         u8 pkt[3];
255                         pkt[0] = BNEP_CONTROL;
256                         pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
257                         pkt[2] = cmd;
258                         bnep_send(s, pkt, sizeof(pkt));
259                 }
260                 break;
261         }
262
263         return err;
264 }
265
266 static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
267 {
268         struct bnep_ext_hdr *h;
269         int err = 0;
270
271         do {
272                 h = (void *) skb->data;
273                 if (!skb_pull(skb, sizeof(*h))) {
274                         err = -EILSEQ;
275                         break;
276                 }
277
278                 BT_DBG("type 0x%x len %d", h->type, h->len);
279         
280                 switch (h->type & BNEP_TYPE_MASK) {
281                 case BNEP_EXT_CONTROL:
282                         bnep_rx_control(s, skb->data, skb->len);
283                         break;
284
285                 default:
286                         /* Unknown extension, skip it. */
287                         break;
288                 }
289
290                 if (!skb_pull(skb, h->len)) {
291                         err = -EILSEQ;
292                         break;
293                 }
294         } while (!err && (h->type & BNEP_EXT_HEADER));
295         
296         return err;
297 }
298
299 static u8 __bnep_rx_hlen[] = {
300         ETH_HLEN,     /* BNEP_GENERAL */
301         0,            /* BNEP_CONTROL */
302         2,            /* BNEP_COMPRESSED */
303         ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */
304         ETH_ALEN + 2  /* BNEP_COMPRESSED_DST_ONLY */
305 };
306 #define BNEP_RX_TYPES   (sizeof(__bnep_rx_hlen) - 1)
307
308 static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
309 {
310         struct net_device *dev = s->dev;
311         struct sk_buff *nskb;
312         u8 type;
313
314         dev->last_rx = jiffies;
315         s->stats.rx_bytes += skb->len;
316
317         type = *(u8 *) skb->data; skb_pull(skb, 1);
318
319         if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES)
320                 goto badframe;
321         
322         if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
323                 bnep_rx_control(s, skb->data, skb->len);
324                 kfree_skb(skb);
325                 return 0;
326         }
327
328         skb->mac.raw = skb->data;
329
330         /* Verify and pull out header */
331         if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
332                 goto badframe;
333
334         s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2));
335
336         if (type & BNEP_EXT_HEADER) {
337                 if (bnep_rx_extension(s, skb) < 0)
338                         goto badframe;
339         }
340
341         /* Strip 802.1p header */
342         if (ntohs(s->eh.h_proto) == 0x8100) {
343                 if (!skb_pull(skb, 4))
344                         goto badframe;
345                 s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2));
346         }
347         
348         /* We have to alloc new skb and copy data here :(. Because original skb
349          * may not be modified and because of the alignment requirements. */
350         nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL);
351         if (!nskb) {
352                 s->stats.rx_dropped++;
353                 kfree_skb(skb);
354                 return -ENOMEM;
355         }
356         skb_reserve(nskb, 2);
357
358         /* Decompress header and construct ether frame */
359         switch (type & BNEP_TYPE_MASK) {
360         case BNEP_COMPRESSED:
361                 memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN);
362                 break;
363         
364         case BNEP_COMPRESSED_SRC_ONLY:
365                 memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN);
366                 memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN);
367                 put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2));
368                 break;
369
370         case BNEP_COMPRESSED_DST_ONLY:
371                 memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN);
372                 memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, ETH_ALEN + 2);
373                 break;
374
375         case BNEP_GENERAL:
376                 memcpy(__skb_put(nskb, ETH_ALEN * 2), skb->mac.raw, ETH_ALEN * 2);
377                 put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2));
378                 break;
379         }
380
381         memcpy(__skb_put(nskb, skb->len), skb->data, skb->len);
382         kfree_skb(skb);
383         
384         s->stats.rx_packets++;
385         nskb->dev       = dev;
386         nskb->ip_summed = CHECKSUM_NONE;
387         nskb->protocol  = eth_type_trans(nskb, dev);
388         netif_rx_ni(nskb);
389         return 0;
390
391 badframe:
392         s->stats.rx_errors++;
393         kfree_skb(skb);
394         return 0;
395 }
396
397 static u8 __bnep_tx_types[] = {
398         BNEP_GENERAL,
399         BNEP_COMPRESSED_SRC_ONLY,
400         BNEP_COMPRESSED_DST_ONLY,
401         BNEP_COMPRESSED
402 };
403
404 static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
405 {
406         struct ethhdr *eh = (void *) skb->data;
407         struct socket *sock = s->sock;
408         struct kvec iv[3];
409         int len = 0, il = 0;
410         u8 type = 0;
411
412         BT_DBG("skb %p dev %p type %d", skb, skb->dev, skb->pkt_type);
413
414         if (!skb->dev) {
415                 /* Control frame sent by us */
416                 goto send;
417         }
418
419         iv[il++] = (struct kvec) { &type, 1 };
420         len++;
421
422         if (!compare_ether_addr(eh->h_dest, s->eh.h_source))
423                 type |= 0x01;
424
425         if (!compare_ether_addr(eh->h_source, s->eh.h_dest))
426                 type |= 0x02;
427
428         if (type)
429                 skb_pull(skb, ETH_ALEN * 2);
430
431         type = __bnep_tx_types[type];
432         switch (type) {
433         case BNEP_COMPRESSED_SRC_ONLY:
434                 iv[il++] = (struct kvec) { eh->h_source, ETH_ALEN };
435                 len += ETH_ALEN;
436                 break;
437                 
438         case BNEP_COMPRESSED_DST_ONLY:
439                 iv[il++] = (struct kvec) { eh->h_dest, ETH_ALEN };
440                 len += ETH_ALEN;
441                 break;
442         }
443
444 send:
445         iv[il++] = (struct kvec) { skb->data, skb->len };
446         len += skb->len;
447         
448         /* FIXME: linearize skb */
449         {
450                 len = kernel_sendmsg(sock, &s->msg, iv, il, len);
451         }
452         kfree_skb(skb);
453
454         if (len > 0) {
455                 s->stats.tx_bytes += len;
456                 s->stats.tx_packets++;
457                 return 0;
458         }
459
460         return len;
461 }
462
463 static int bnep_session(void *arg)
464 {
465         struct bnep_session *s = arg;
466         struct net_device *dev = s->dev;
467         struct sock *sk = s->sock->sk;
468         struct sk_buff *skb;
469         wait_queue_t wait;
470
471         BT_DBG("");
472
473         daemonize("kbnepd %s", dev->name);
474         set_user_nice(current, -15);
475         current->flags |= PF_NOFREEZE;
476
477         init_waitqueue_entry(&wait, current);
478         add_wait_queue(sk->sk_sleep, &wait);
479         while (!atomic_read(&s->killed)) {
480                 set_current_state(TASK_INTERRUPTIBLE);
481
482                 // RX
483                 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
484                         skb_orphan(skb);
485                         bnep_rx_frame(s, skb);
486                 }
487
488                 if (sk->sk_state != BT_CONNECTED)
489                         break;
490         
491                 // TX
492                 while ((skb = skb_dequeue(&sk->sk_write_queue)))
493                         if (bnep_tx_frame(s, skb))
494                                 break;
495                 netif_wake_queue(dev);
496         
497                 schedule();
498         }
499         set_current_state(TASK_RUNNING);
500         remove_wait_queue(sk->sk_sleep, &wait);
501
502         /* Cleanup session */
503         down_write(&bnep_session_sem);
504
505         /* Delete network device */
506         unregister_netdev(dev);
507
508         /* Release the socket */
509         fput(s->sock->file);
510
511         __bnep_unlink_session(s);
512
513         up_write(&bnep_session_sem);
514         free_netdev(dev);
515         return 0;
516 }
517
518 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
519 {
520         struct net_device *dev;
521         struct bnep_session *s, *ss;
522         u8 dst[ETH_ALEN], src[ETH_ALEN];
523         int err;
524
525         BT_DBG("");
526
527         baswap((void *) dst, &bt_sk(sock->sk)->dst);
528         baswap((void *) src, &bt_sk(sock->sk)->src);
529
530         /* session struct allocated as private part of net_device */
531         dev = alloc_netdev(sizeof(struct bnep_session),
532                            (*req->device) ? req->device : "bnep%d",
533                            bnep_net_setup);
534         if (!dev)
535                 return -ENOMEM;
536
537
538         down_write(&bnep_session_sem);
539
540         ss = __bnep_get_session(dst);
541         if (ss && ss->state == BT_CONNECTED) {
542                 err = -EEXIST;
543                 goto failed;
544         }
545
546         s = dev->priv;
547
548         /* This is rx header therefore addresses are swapped.
549          * ie eh.h_dest is our local address. */
550         memcpy(s->eh.h_dest,   &src, ETH_ALEN);
551         memcpy(s->eh.h_source, &dst, ETH_ALEN);
552         memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
553
554         s->dev = dev;
555         s->sock  = sock;
556         s->role  = req->role;
557         s->state = BT_CONNECTED;
558         
559         s->msg.msg_flags = MSG_NOSIGNAL;
560
561 #ifdef CONFIG_BT_BNEP_MC_FILTER
562         /* Set default mc filter */
563         set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter);
564 #endif
565
566 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
567         /* Set default protocol filter */
568         bnep_set_default_proto_filter(s);
569 #endif
570
571         err = register_netdev(dev);
572         if (err) {
573                 goto failed;
574         }
575
576         __bnep_link_session(s);
577         
578         err = kernel_thread(bnep_session, s, CLONE_KERNEL);
579         if (err < 0) {
580                 /* Session thread start failed, gotta cleanup. */
581                 unregister_netdev(dev);
582                 __bnep_unlink_session(s);
583                 goto failed;
584         }
585
586         up_write(&bnep_session_sem);
587         strcpy(req->device, dev->name);
588         return 0;
589
590 failed:
591         up_write(&bnep_session_sem);
592         free_netdev(dev);
593         return err;
594 }
595
596 int bnep_del_connection(struct bnep_conndel_req *req)
597 {
598         struct bnep_session *s;
599         int  err = 0;
600
601         BT_DBG("");
602
603         down_read(&bnep_session_sem);
604
605         s = __bnep_get_session(req->dst);
606         if (s) {
607                 /* Wakeup user-space which is polling for socket errors.
608                  * This is temporary hack untill we have shutdown in L2CAP */
609                 s->sock->sk->sk_err = EUNATCH;
610                 
611                 /* Kill session thread */
612                 atomic_inc(&s->killed);
613                 wake_up_interruptible(s->sock->sk->sk_sleep);
614         } else
615                 err = -ENOENT;
616
617         up_read(&bnep_session_sem);
618         return err;
619 }
620
621 static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
622 {
623         memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
624         strcpy(ci->device, s->dev->name);
625         ci->flags = s->flags;
626         ci->state = s->state;
627         ci->role  = s->role;
628 }
629
630 int bnep_get_connlist(struct bnep_connlist_req *req)
631 {
632         struct list_head *p;
633         int err = 0, n = 0;
634
635         down_read(&bnep_session_sem);
636
637         list_for_each(p, &bnep_session_list) {
638                 struct bnep_session *s;
639                 struct bnep_conninfo ci;
640
641                 s = list_entry(p, struct bnep_session, list);
642
643                 __bnep_copy_ci(&ci, s);
644                 
645                 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
646                         err = -EFAULT;
647                         break;
648                 }
649
650                 if (++n >= req->cnum)
651                         break;
652
653                 req->ci++;
654         }
655         req->cnum = n;
656
657         up_read(&bnep_session_sem);
658         return err;
659 }
660
661 int bnep_get_conninfo(struct bnep_conninfo *ci)
662 {
663         struct bnep_session *s;
664         int err = 0;
665
666         down_read(&bnep_session_sem);
667
668         s = __bnep_get_session(ci->dst);
669         if (s)
670                 __bnep_copy_ci(ci, s);
671         else
672                 err = -ENOENT;
673
674         up_read(&bnep_session_sem);
675         return err;
676 }
677
678 static int __init bnep_init(void)
679 {       
680         char flt[50] = "";
681
682         l2cap_load();
683
684 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
685         strcat(flt, "protocol ");
686 #endif
687
688 #ifdef CONFIG_BT_BNEP_MC_FILTER
689         strcat(flt, "multicast");
690 #endif
691
692         BT_INFO("BNEP (Ethernet Emulation) ver %s", VERSION);
693         if (flt[0])
694                 BT_INFO("BNEP filters: %s", flt);
695
696         bnep_sock_init();
697         return 0;
698 }
699
700 static void __exit bnep_exit(void)
701 {
702         bnep_sock_cleanup();
703 }
704
705 module_init(bnep_init);
706 module_exit(bnep_exit);
707
708 MODULE_AUTHOR("David Libault <david.libault@inventel.fr>, Maxim Krasnyansky <maxk@qualcomm.com>");
709 MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION);
710 MODULE_VERSION(VERSION);
711 MODULE_LICENSE("GPL");
712 MODULE_ALIAS("bt-proto-4");