xref: /linux/net/bluetooth/bnep/core.c (revision a1741e7fcbc19a67520115df480ab17012cc3d0b)
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 (1) {
488 		set_current_state(TASK_INTERRUPTIBLE);
489 
490 		if (atomic_read(&s->terminate))
491 			break;
492 		/* RX */
493 		while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
494 			skb_orphan(skb);
495 			bnep_rx_frame(s, skb);
496 		}
497 
498 		if (sk->sk_state != BT_CONNECTED)
499 			break;
500 
501 		/* TX */
502 		while ((skb = skb_dequeue(&sk->sk_write_queue)))
503 			if (bnep_tx_frame(s, skb))
504 				break;
505 		netif_wake_queue(dev);
506 
507 		schedule();
508 	}
509 	__set_current_state(TASK_RUNNING);
510 	remove_wait_queue(sk_sleep(sk), &wait);
511 
512 	/* Cleanup session */
513 	down_write(&bnep_session_sem);
514 
515 	/* Delete network device */
516 	unregister_netdev(dev);
517 
518 	/* Wakeup user-space polling for socket errors */
519 	s->sock->sk->sk_err = EUNATCH;
520 
521 	wake_up_interruptible(sk_sleep(s->sock->sk));
522 
523 	/* Release the socket */
524 	fput(s->sock->file);
525 
526 	__bnep_unlink_session(s);
527 
528 	up_write(&bnep_session_sem);
529 	free_netdev(dev);
530 	return 0;
531 }
532 
533 static struct device *bnep_get_device(struct bnep_session *session)
534 {
535 	bdaddr_t *src = &bt_sk(session->sock->sk)->src;
536 	bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
537 	struct hci_dev *hdev;
538 	struct hci_conn *conn;
539 
540 	hdev = hci_get_route(dst, src);
541 	if (!hdev)
542 		return NULL;
543 
544 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
545 
546 	hci_dev_put(hdev);
547 
548 	return conn ? &conn->dev : NULL;
549 }
550 
551 static struct device_type bnep_type = {
552 	.name	= "bluetooth",
553 };
554 
555 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
556 {
557 	struct net_device *dev;
558 	struct bnep_session *s, *ss;
559 	u8 dst[ETH_ALEN], src[ETH_ALEN];
560 	int err;
561 
562 	BT_DBG("");
563 
564 	baswap((void *) dst, &bt_sk(sock->sk)->dst);
565 	baswap((void *) src, &bt_sk(sock->sk)->src);
566 
567 	/* session struct allocated as private part of net_device */
568 	dev = alloc_netdev(sizeof(struct bnep_session),
569 				(*req->device) ? req->device : "bnep%d",
570 				bnep_net_setup);
571 	if (!dev)
572 		return -ENOMEM;
573 
574 	down_write(&bnep_session_sem);
575 
576 	ss = __bnep_get_session(dst);
577 	if (ss && ss->state == BT_CONNECTED) {
578 		err = -EEXIST;
579 		goto failed;
580 	}
581 
582 	s = netdev_priv(dev);
583 
584 	/* This is rx header therefore addresses are swapped.
585 	 * ie. eh.h_dest is our local address. */
586 	memcpy(s->eh.h_dest,   &src, ETH_ALEN);
587 	memcpy(s->eh.h_source, &dst, ETH_ALEN);
588 	memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
589 
590 	s->dev   = dev;
591 	s->sock  = sock;
592 	s->role  = req->role;
593 	s->state = BT_CONNECTED;
594 
595 	s->msg.msg_flags = MSG_NOSIGNAL;
596 
597 #ifdef CONFIG_BT_BNEP_MC_FILTER
598 	/* Set default mc filter */
599 	set_bit(bnep_mc_hash(dev->broadcast), (ulong *) &s->mc_filter);
600 #endif
601 
602 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
603 	/* Set default protocol filter */
604 	bnep_set_default_proto_filter(s);
605 #endif
606 
607 	SET_NETDEV_DEV(dev, bnep_get_device(s));
608 	SET_NETDEV_DEVTYPE(dev, &bnep_type);
609 
610 	err = register_netdev(dev);
611 	if (err)
612 		goto failed;
613 
614 	__bnep_link_session(s);
615 
616 	s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name);
617 	if (IS_ERR(s->task)) {
618 		/* Session thread start failed, gotta cleanup. */
619 		unregister_netdev(dev);
620 		__bnep_unlink_session(s);
621 		err = PTR_ERR(s->task);
622 		goto failed;
623 	}
624 
625 	up_write(&bnep_session_sem);
626 	strcpy(req->device, dev->name);
627 	return 0;
628 
629 failed:
630 	up_write(&bnep_session_sem);
631 	free_netdev(dev);
632 	return err;
633 }
634 
635 int bnep_del_connection(struct bnep_conndel_req *req)
636 {
637 	struct bnep_session *s;
638 	int  err = 0;
639 
640 	BT_DBG("");
641 
642 	down_read(&bnep_session_sem);
643 
644 	s = __bnep_get_session(req->dst);
645 	if (s) {
646 		atomic_inc(&s->terminate);
647 		wake_up_process(s->task);
648 	} else
649 		err = -ENOENT;
650 
651 	up_read(&bnep_session_sem);
652 	return err;
653 }
654 
655 static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
656 {
657 	memset(ci, 0, sizeof(*ci));
658 	memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
659 	strcpy(ci->device, s->dev->name);
660 	ci->flags = s->flags;
661 	ci->state = s->state;
662 	ci->role  = s->role;
663 }
664 
665 int bnep_get_connlist(struct bnep_connlist_req *req)
666 {
667 	struct list_head *p;
668 	int err = 0, n = 0;
669 
670 	down_read(&bnep_session_sem);
671 
672 	list_for_each(p, &bnep_session_list) {
673 		struct bnep_session *s;
674 		struct bnep_conninfo ci;
675 
676 		s = list_entry(p, struct bnep_session, list);
677 
678 		__bnep_copy_ci(&ci, s);
679 
680 		if (copy_to_user(req->ci, &ci, sizeof(ci))) {
681 			err = -EFAULT;
682 			break;
683 		}
684 
685 		if (++n >= req->cnum)
686 			break;
687 
688 		req->ci++;
689 	}
690 	req->cnum = n;
691 
692 	up_read(&bnep_session_sem);
693 	return err;
694 }
695 
696 int bnep_get_conninfo(struct bnep_conninfo *ci)
697 {
698 	struct bnep_session *s;
699 	int err = 0;
700 
701 	down_read(&bnep_session_sem);
702 
703 	s = __bnep_get_session(ci->dst);
704 	if (s)
705 		__bnep_copy_ci(ci, s);
706 	else
707 		err = -ENOENT;
708 
709 	up_read(&bnep_session_sem);
710 	return err;
711 }
712 
713 static int __init bnep_init(void)
714 {
715 	char flt[50] = "";
716 
717 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
718 	strcat(flt, "protocol ");
719 #endif
720 
721 #ifdef CONFIG_BT_BNEP_MC_FILTER
722 	strcat(flt, "multicast");
723 #endif
724 
725 	BT_INFO("BNEP (Ethernet Emulation) ver %s", VERSION);
726 	if (flt[0])
727 		BT_INFO("BNEP filters: %s", flt);
728 
729 	bnep_sock_init();
730 	return 0;
731 }
732 
733 static void __exit bnep_exit(void)
734 {
735 	bnep_sock_cleanup();
736 }
737 
738 module_init(bnep_init);
739 module_exit(bnep_exit);
740 
741 module_param(compress_src, bool, 0644);
742 MODULE_PARM_DESC(compress_src, "Compress sources headers");
743 
744 module_param(compress_dst, bool, 0644);
745 MODULE_PARM_DESC(compress_dst, "Compress destination headers");
746 
747 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
748 MODULE_DESCRIPTION("Bluetooth BNEP ver " VERSION);
749 MODULE_VERSION(VERSION);
750 MODULE_LICENSE("GPL");
751 MODULE_ALIAS("bt-proto-4");
752