[Bluetooth] Add parameters to control BNEP header compression
[linux-2.6.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 #include <linux/module.h>
29
30 #include <linux/kernel.h>
31 #include <linux/sched.h>
32 #include <linux/signal.h>
33 #include <linux/init.h>
34 #include <linux/wait.h>
35 #include <linux/freezer.h>
36 #include <linux/errno.h>
37 #include <linux/net.h>
38 #include <net/sock.h>
39
40 #include <linux/socket.h>
41 #include <linux/file.h>
42
43 #include <linux/netdevice.h>
44 #include <linux/etherdevice.h>
45 #include <linux/skbuff.h>
46
47 #include <asm/unaligned.h>
48
49 #include <net/bluetooth/bluetooth.h>
50 #include <net/bluetooth/hci_core.h>
51 #include <net/bluetooth/l2cap.h>
52
53 #include "bnep.h"
54
55 #ifndef CONFIG_BT_BNEP_DEBUG
56 #undef  BT_DBG
57 #define BT_DBG(D...)
58 #endif
59
60 #define VERSION "1.3"
61
62 static int compress_src = 1;
63 static int compress_dst = 1;
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 = ETH_P_IP;
120         s->proto_filter[0].end   = ETH_P_ARP;
121         /* (RARP, AppleTalk) */
122         s->proto_filter[1].start = ETH_P_RARP;
123         s->proto_filter[1].end   = ETH_P_AARP;
124         /* (IPX, IPv6) */
125         s->proto_filter[2].start = ETH_P_IPX;
126         s->proto_filter[2].end   = ETH_P_IPV6;
127 }
128 #endif
129
130 static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len)
131 {
132         int n;
133
134         if (len < 2)
135                 return -EILSEQ;
136
137         n = get_unaligned_be16(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_be16(data++);
153                         f[i].end   = get_unaligned_be16(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 = get_unaligned_be16(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_reset_mac_header(skb);
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((__be16 *) (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((__be16 *) (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_header(skb), ETH_ALEN);
367                 put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
368                 break;
369
370         case BNEP_COMPRESSED_DST_ONLY:
371                 memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb),
372                        ETH_ALEN);
373                 memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source,
374                        ETH_ALEN + 2);
375                 break;
376
377         case BNEP_GENERAL:
378                 memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb),
379                        ETH_ALEN * 2);
380                 put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
381                 break;
382         }
383
384         skb_copy_from_linear_data(skb, __skb_put(nskb, skb->len), skb->len);
385         kfree_skb(skb);
386
387         s->stats.rx_packets++;
388         nskb->ip_summed = CHECKSUM_NONE;
389         nskb->protocol  = eth_type_trans(nskb, dev);
390         netif_rx_ni(nskb);
391         return 0;
392
393 badframe:
394         s->stats.rx_errors++;
395         kfree_skb(skb);
396         return 0;
397 }
398
399 static u8 __bnep_tx_types[] = {
400         BNEP_GENERAL,
401         BNEP_COMPRESSED_SRC_ONLY,
402         BNEP_COMPRESSED_DST_ONLY,
403         BNEP_COMPRESSED
404 };
405
406 static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
407 {
408         struct ethhdr *eh = (void *) skb->data;
409         struct socket *sock = s->sock;
410         struct kvec iv[3];
411         int len = 0, il = 0;
412         u8 type = 0;
413
414         BT_DBG("skb %p dev %p type %d", skb, skb->dev, skb->pkt_type);
415
416         if (!skb->dev) {
417                 /* Control frame sent by us */
418                 goto send;
419         }
420
421         iv[il++] = (struct kvec) { &type, 1 };
422         len++;
423
424         if (compress_src && !compare_ether_addr(eh->h_dest, s->eh.h_source))
425                 type |= 0x01;
426
427         if (compress_dst && !compare_ether_addr(eh->h_source, s->eh.h_dest))
428                 type |= 0x02;
429
430         if (type)
431                 skb_pull(skb, ETH_ALEN * 2);
432
433         type = __bnep_tx_types[type];
434         switch (type) {
435         case BNEP_COMPRESSED_SRC_ONLY:
436                 iv[il++] = (struct kvec) { eh->h_source, ETH_ALEN };
437                 len += ETH_ALEN;
438                 break;
439
440         case BNEP_COMPRESSED_DST_ONLY:
441                 iv[il++] = (struct kvec) { eh->h_dest, ETH_ALEN };
442                 len += ETH_ALEN;
443                 break;
444         }
445
446 send:
447         iv[il++] = (struct kvec) { skb->data, skb->len };
448         len += skb->len;
449
450         /* FIXME: linearize skb */
451         {
452                 len = kernel_sendmsg(sock, &s->msg, iv, il, len);
453         }
454         kfree_skb(skb);
455
456         if (len > 0) {
457                 s->stats.tx_bytes += len;
458                 s->stats.tx_packets++;
459                 return 0;
460         }
461
462         return len;
463 }
464
465 static int bnep_session(void *arg)
466 {
467         struct bnep_session *s = arg;
468         struct net_device *dev = s->dev;
469         struct sock *sk = s->sock->sk;
470         struct sk_buff *skb;
471         wait_queue_t wait;
472
473         BT_DBG("");
474
475         daemonize("kbnepd %s", dev->name);
476         set_user_nice(current, -15);
477
478         init_waitqueue_entry(&wait, current);
479         add_wait_queue(sk->sk_sleep, &wait);
480         while (!atomic_read(&s->killed)) {
481                 set_current_state(TASK_INTERRUPTIBLE);
482
483                 // RX
484                 while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
485                         skb_orphan(skb);
486                         bnep_rx_frame(s, skb);
487                 }
488
489                 if (sk->sk_state != BT_CONNECTED)
490                         break;
491
492                 // TX
493                 while ((skb = skb_dequeue(&sk->sk_write_queue)))
494                         if (bnep_tx_frame(s, skb))
495                                 break;
496                 netif_wake_queue(dev);
497
498                 schedule();
499         }
500         set_current_state(TASK_RUNNING);
501         remove_wait_queue(sk->sk_sleep, &wait);
502
503         /* Cleanup session */
504         down_write(&bnep_session_sem);
505
506         /* Delete network device */
507         unregister_netdev(dev);
508
509         /* Wakeup user-space polling for socket errors */
510         s->sock->sk->sk_err = EUNATCH;
511
512         wake_up_interruptible(s->sock->sk->sk_sleep);
513
514         /* Release the socket */
515         fput(s->sock->file);
516
517         __bnep_unlink_session(s);
518
519         up_write(&bnep_session_sem);
520         free_netdev(dev);
521         return 0;
522 }
523
524 static struct device *bnep_get_device(struct bnep_session *session)
525 {
526         bdaddr_t *src = &bt_sk(session->sock->sk)->src;
527         bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
528         struct hci_dev *hdev;
529         struct hci_conn *conn;
530
531         hdev = hci_get_route(dst, src);
532         if (!hdev)
533                 return NULL;
534
535         conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
536
537         hci_dev_put(hdev);
538
539         return conn ? &conn->dev : NULL;
540 }
541
542 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
543 {
544         struct net_device *dev;
545         struct bnep_session *s, *ss;
546         u8 dst[ETH_ALEN], src[ETH_ALEN];
547         int err;
548
549         BT_DBG("");
550
551         baswap((void *) dst, &bt_sk(sock->sk)->dst);
552         baswap((void *) src, &bt_sk(sock->sk)->src);
553
554         /* session struct allocated as private part of net_device */
555         dev = alloc_netdev(sizeof(struct bnep_session),
556                            (*req->device) ? req->device : "bnep%d",
557                            bnep_net_setup);
558         if (!dev)
559                 return -ENOMEM;
560
561         down_write(&bnep_session_sem);
562
563         ss = __bnep_get_session(dst);
564         if (ss && ss->state == BT_CONNECTED) {
565                 err = -EEXIST;
566                 goto failed;
567         }
568
569         s = dev->priv;
570
571         /* This is rx header therefore addresses are swapped.
572          * ie eh.h_dest is our local address. */
573         memcpy(s->eh.h_dest,   &src, ETH_ALEN);
574         memcpy(s->eh.h_source, &dst, ETH_ALEN);
575         memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
576
577         s->dev   = dev;
578         s->sock  = sock;
579         s->role  = req->role;
580         s->state = BT_CONNECTED;
581
582         s->msg.msg_flags = MSG_NOSIGNAL;
583
584 #ifdef CONFIG_BT_BNEP_MC_FILTER
585         /* Set default mc filter */
586         set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter);
587 #endif
588
589 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
590         /* Set default protocol filter */
591         bnep_set_default_proto_filter(s);
592 #endif
593
594         SET_NETDEV_DEV(dev, bnep_get_device(s));
595
596         err = register_netdev(dev);
597         if (err) {
598                 goto failed;
599         }
600
601         __bnep_link_session(s);
602
603         err = kernel_thread(bnep_session, s, CLONE_KERNEL);
604         if (err < 0) {
605                 /* Session thread start failed, gotta cleanup. */
606                 unregister_netdev(dev);
607                 __bnep_unlink_session(s);
608                 goto failed;
609         }
610
611         up_write(&bnep_session_sem);
612         strcpy(req->device, dev->name);
613         return 0;
614
615 failed:
616         up_write(&bnep_session_sem);
617         free_netdev(dev);
618         return err;
619 }
620
621 int bnep_del_connection(struct bnep_conndel_req *req)
622 {
623         struct bnep_session *s;
624         int  err = 0;
625
626         BT_DBG("");
627
628         down_read(&bnep_session_sem);
629
630         s = __bnep_get_session(req->dst);
631         if (s) {
632                 /* Wakeup user-space which is polling for socket errors.
633                  * This is temporary hack untill we have shutdown in L2CAP */
634                 s->sock->sk->sk_err = EUNATCH;
635
636                 /* Kill session thread */
637                 atomic_inc(&s->killed);
638                 wake_up_interruptible(s->sock->sk->sk_sleep);
639         } else
640                 err = -ENOENT;
641
642         up_read(&bnep_session_sem);
643         return err;
644 }
645
646 static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
647 {
648         memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
649         strcpy(ci->device, s->dev->name);
650         ci->flags = s->flags;
651         ci->state = s->state;
652         ci->role  = s->role;
653 }
654
655 int bnep_get_connlist(struct bnep_connlist_req *req)
656 {
657         struct list_head *p;
658         int err = 0, n = 0;
659
660         down_read(&bnep_session_sem);
661
662         list_for_each(p, &bnep_session_list) {
663                 struct bnep_session *s;
664                 struct bnep_conninfo ci;
665
666                 s = list_entry(p, struct bnep_session, list);
667
668                 __bnep_copy_ci(&ci, s);
669
670                 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
671                         err = -EFAULT;
672                         break;
673                 }
674
675                 if (++n >= req->cnum)
676                         break;
677
678                 req->ci++;
679         }
680         req->cnum = n;
681
682         up_read(&bnep_session_sem);
683         return err;
684 }
685
686 int bnep_get_conninfo(struct bnep_conninfo *ci)
687 {
688         struct bnep_session *s;
689         int err = 0;
690
691         down_read(&bnep_session_sem);
692
693         s = __bnep_get_session(ci->dst);
694         if (s)
695                 __bnep_copy_ci(ci, s);
696         else
697                 err = -ENOENT;
698
699         up_read(&bnep_session_sem);
700         return err;
701 }
702
703 static int __init bnep_init(void)
704 {
705         char flt[50] = "";
706
707         l2cap_load();
708
709 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
710         strcat(flt, "protocol ");
711 #endif
712
713 #ifdef CONFIG_BT_BNEP_MC_FILTER
714         strcat(flt, "multicast");
715 #endif
716
717         BT_INFO("BNEP (Ethernet Emulation) ver %s", VERSION);
718         if (flt[0])
719                 BT_INFO("BNEP filters: %s", flt);
720
721         bnep_sock_init();
722         return 0;
723 }
724
725 static void __exit bnep_exit(void)
726 {
727         bnep_sock_cleanup();
728 }
729
730 module_init(bnep_init);
731 module_exit(bnep_exit);
732
733 module_param(compress_src, bool, 0644);
734 MODULE_PARM_DESC(compress_src, "Compress sources headers");
735
736 module_param(compress_dst, bool, 0644);
737 MODULE_PARM_DESC(compress_dst, "Compress destination headers");
738
739 MODULE_AUTHOR("David Libault <david.libault@inventel.fr>, Maxim Krasnyansky <maxk@qualcomm.com>");
740 MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION);
741 MODULE_VERSION(VERSION);
742 MODULE_LICENSE("GPL");
743 MODULE_ALIAS("bt-proto-4");