netdevice: safe convert to netdev_priv() #part-4
[safe/jmp/linux-2.6] / 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         s->stats.rx_bytes += skb->len;
315
316         type = *(u8 *) skb->data; skb_pull(skb, 1);
317
318         if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES)
319                 goto badframe;
320
321         if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
322                 bnep_rx_control(s, skb->data, skb->len);
323                 kfree_skb(skb);
324                 return 0;
325         }
326
327         skb_reset_mac_header(skb);
328
329         /* Verify and pull out header */
330         if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
331                 goto badframe;
332
333         s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
334
335         if (type & BNEP_EXT_HEADER) {
336                 if (bnep_rx_extension(s, skb) < 0)
337                         goto badframe;
338         }
339
340         /* Strip 802.1p header */
341         if (ntohs(s->eh.h_proto) == 0x8100) {
342                 if (!skb_pull(skb, 4))
343                         goto badframe;
344                 s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
345         }
346
347         /* We have to alloc new skb and copy data here :(. Because original skb
348          * may not be modified and because of the alignment requirements. */
349         nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL);
350         if (!nskb) {
351                 s->stats.rx_dropped++;
352                 kfree_skb(skb);
353                 return -ENOMEM;
354         }
355         skb_reserve(nskb, 2);
356
357         /* Decompress header and construct ether frame */
358         switch (type & BNEP_TYPE_MASK) {
359         case BNEP_COMPRESSED:
360                 memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN);
361                 break;
362
363         case BNEP_COMPRESSED_SRC_ONLY:
364                 memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN);
365                 memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), ETH_ALEN);
366                 put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
367                 break;
368
369         case BNEP_COMPRESSED_DST_ONLY:
370                 memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb),
371                        ETH_ALEN);
372                 memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source,
373                        ETH_ALEN + 2);
374                 break;
375
376         case BNEP_GENERAL:
377                 memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb),
378                        ETH_ALEN * 2);
379                 put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
380                 break;
381         }
382
383         skb_copy_from_linear_data(skb, __skb_put(nskb, skb->len), skb->len);
384         kfree_skb(skb);
385
386         s->stats.rx_packets++;
387         nskb->ip_summed = CHECKSUM_NONE;
388         nskb->protocol  = eth_type_trans(nskb, dev);
389         netif_rx_ni(nskb);
390         return 0;
391
392 badframe:
393         s->stats.rx_errors++;
394         kfree_skb(skb);
395         return 0;
396 }
397
398 static u8 __bnep_tx_types[] = {
399         BNEP_GENERAL,
400         BNEP_COMPRESSED_SRC_ONLY,
401         BNEP_COMPRESSED_DST_ONLY,
402         BNEP_COMPRESSED
403 };
404
405 static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
406 {
407         struct ethhdr *eh = (void *) skb->data;
408         struct socket *sock = s->sock;
409         struct kvec iv[3];
410         int len = 0, il = 0;
411         u8 type = 0;
412
413         BT_DBG("skb %p dev %p type %d", skb, skb->dev, skb->pkt_type);
414
415         if (!skb->dev) {
416                 /* Control frame sent by us */
417                 goto send;
418         }
419
420         iv[il++] = (struct kvec) { &type, 1 };
421         len++;
422
423         if (compress_src && !compare_ether_addr(eh->h_dest, s->eh.h_source))
424                 type |= 0x01;
425
426         if (compress_dst && !compare_ether_addr(eh->h_source, s->eh.h_dest))
427                 type |= 0x02;
428
429         if (type)
430                 skb_pull(skb, ETH_ALEN * 2);
431
432         type = __bnep_tx_types[type];
433         switch (type) {
434         case BNEP_COMPRESSED_SRC_ONLY:
435                 iv[il++] = (struct kvec) { eh->h_source, ETH_ALEN };
436                 len += ETH_ALEN;
437                 break;
438
439         case BNEP_COMPRESSED_DST_ONLY:
440                 iv[il++] = (struct kvec) { eh->h_dest, ETH_ALEN };
441                 len += ETH_ALEN;
442                 break;
443         }
444
445 send:
446         iv[il++] = (struct kvec) { skb->data, skb->len };
447         len += skb->len;
448
449         /* FIXME: linearize skb */
450         {
451                 len = kernel_sendmsg(sock, &s->msg, iv, il, len);
452         }
453         kfree_skb(skb);
454
455         if (len > 0) {
456                 s->stats.tx_bytes += len;
457                 s->stats.tx_packets++;
458                 return 0;
459         }
460
461         return len;
462 }
463
464 static int bnep_session(void *arg)
465 {
466         struct bnep_session *s = arg;
467         struct net_device *dev = s->dev;
468         struct sock *sk = s->sock->sk;
469         struct sk_buff *skb;
470         wait_queue_t wait;
471
472         BT_DBG("");
473
474         daemonize("kbnepd %s", dev->name);
475         set_user_nice(current, -15);
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         /* Wakeup user-space polling for socket errors */
509         s->sock->sk->sk_err = EUNATCH;
510
511         wake_up_interruptible(s->sock->sk->sk_sleep);
512
513         /* Release the socket */
514         fput(s->sock->file);
515
516         __bnep_unlink_session(s);
517
518         up_write(&bnep_session_sem);
519         free_netdev(dev);
520         return 0;
521 }
522
523 static struct device *bnep_get_device(struct bnep_session *session)
524 {
525         bdaddr_t *src = &bt_sk(session->sock->sk)->src;
526         bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
527         struct hci_dev *hdev;
528         struct hci_conn *conn;
529
530         hdev = hci_get_route(dst, src);
531         if (!hdev)
532                 return NULL;
533
534         conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
535
536         hci_dev_put(hdev);
537
538         return conn ? &conn->dev : NULL;
539 }
540
541 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
542 {
543         struct net_device *dev;
544         struct bnep_session *s, *ss;
545         u8 dst[ETH_ALEN], src[ETH_ALEN];
546         int err;
547
548         BT_DBG("");
549
550         baswap((void *) dst, &bt_sk(sock->sk)->dst);
551         baswap((void *) src, &bt_sk(sock->sk)->src);
552
553         /* session struct allocated as private part of net_device */
554         dev = alloc_netdev(sizeof(struct bnep_session),
555                            (*req->device) ? req->device : "bnep%d",
556                            bnep_net_setup);
557         if (!dev)
558                 return -ENOMEM;
559
560         down_write(&bnep_session_sem);
561
562         ss = __bnep_get_session(dst);
563         if (ss && ss->state == BT_CONNECTED) {
564                 err = -EEXIST;
565                 goto failed;
566         }
567
568         s = netdev_priv(dev);
569
570         /* This is rx header therefore addresses are swapped.
571          * ie eh.h_dest is our local address. */
572         memcpy(s->eh.h_dest,   &src, ETH_ALEN);
573         memcpy(s->eh.h_source, &dst, ETH_ALEN);
574         memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
575
576         s->dev   = dev;
577         s->sock  = sock;
578         s->role  = req->role;
579         s->state = BT_CONNECTED;
580
581         s->msg.msg_flags = MSG_NOSIGNAL;
582
583 #ifdef CONFIG_BT_BNEP_MC_FILTER
584         /* Set default mc filter */
585         set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter);
586 #endif
587
588 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
589         /* Set default protocol filter */
590         bnep_set_default_proto_filter(s);
591 #endif
592
593         SET_NETDEV_DEV(dev, bnep_get_device(s));
594
595         err = register_netdev(dev);
596         if (err) {
597                 goto failed;
598         }
599
600         __bnep_link_session(s);
601
602         err = kernel_thread(bnep_session, s, CLONE_KERNEL);
603         if (err < 0) {
604                 /* Session thread start failed, gotta cleanup. */
605                 unregister_netdev(dev);
606                 __bnep_unlink_session(s);
607                 goto failed;
608         }
609
610         up_write(&bnep_session_sem);
611         strcpy(req->device, dev->name);
612         return 0;
613
614 failed:
615         up_write(&bnep_session_sem);
616         free_netdev(dev);
617         return err;
618 }
619
620 int bnep_del_connection(struct bnep_conndel_req *req)
621 {
622         struct bnep_session *s;
623         int  err = 0;
624
625         BT_DBG("");
626
627         down_read(&bnep_session_sem);
628
629         s = __bnep_get_session(req->dst);
630         if (s) {
631                 /* Wakeup user-space which is polling for socket errors.
632                  * This is temporary hack untill we have shutdown in L2CAP */
633                 s->sock->sk->sk_err = EUNATCH;
634
635                 /* Kill session thread */
636                 atomic_inc(&s->killed);
637                 wake_up_interruptible(s->sock->sk->sk_sleep);
638         } else
639                 err = -ENOENT;
640
641         up_read(&bnep_session_sem);
642         return err;
643 }
644
645 static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
646 {
647         memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
648         strcpy(ci->device, s->dev->name);
649         ci->flags = s->flags;
650         ci->state = s->state;
651         ci->role  = s->role;
652 }
653
654 int bnep_get_connlist(struct bnep_connlist_req *req)
655 {
656         struct list_head *p;
657         int err = 0, n = 0;
658
659         down_read(&bnep_session_sem);
660
661         list_for_each(p, &bnep_session_list) {
662                 struct bnep_session *s;
663                 struct bnep_conninfo ci;
664
665                 s = list_entry(p, struct bnep_session, list);
666
667                 __bnep_copy_ci(&ci, s);
668
669                 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
670                         err = -EFAULT;
671                         break;
672                 }
673
674                 if (++n >= req->cnum)
675                         break;
676
677                 req->ci++;
678         }
679         req->cnum = n;
680
681         up_read(&bnep_session_sem);
682         return err;
683 }
684
685 int bnep_get_conninfo(struct bnep_conninfo *ci)
686 {
687         struct bnep_session *s;
688         int err = 0;
689
690         down_read(&bnep_session_sem);
691
692         s = __bnep_get_session(ci->dst);
693         if (s)
694                 __bnep_copy_ci(ci, s);
695         else
696                 err = -ENOENT;
697
698         up_read(&bnep_session_sem);
699         return err;
700 }
701
702 static int __init bnep_init(void)
703 {
704         char flt[50] = "";
705
706         l2cap_load();
707
708 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
709         strcat(flt, "protocol ");
710 #endif
711
712 #ifdef CONFIG_BT_BNEP_MC_FILTER
713         strcat(flt, "multicast");
714 #endif
715
716         BT_INFO("BNEP (Ethernet Emulation) ver %s", VERSION);
717         if (flt[0])
718                 BT_INFO("BNEP filters: %s", flt);
719
720         bnep_sock_init();
721         return 0;
722 }
723
724 static void __exit bnep_exit(void)
725 {
726         bnep_sock_cleanup();
727 }
728
729 module_init(bnep_init);
730 module_exit(bnep_exit);
731
732 module_param(compress_src, bool, 0644);
733 MODULE_PARM_DESC(compress_src, "Compress sources headers");
734
735 module_param(compress_dst, bool, 0644);
736 MODULE_PARM_DESC(compress_dst, "Compress destination headers");
737
738 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
739 MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION);
740 MODULE_VERSION(VERSION);
741 MODULE_LICENSE("GPL");
742 MODULE_ALIAS("bt-proto-4");