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