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