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