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 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 61 static void __bnep_link_session(struct bnep_session *s) 62 { 63 list_add(&s->list, &bnep_session_list); 64 } 65 66 static void __bnep_unlink_session(struct bnep_session *s) 67 { 68 list_del(&s->list); 69 } 70 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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