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