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