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