The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netbt/l2cap_upper.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $OpenBSD: l2cap_upper.c,v 1.2 2007/10/01 16:39:30 krw Exp $ */
    2 /* $NetBSD: l2cap_upper.c,v 1.8 2007/04/29 20:23:36 msaitoh Exp $ */
    3 
    4 /*-
    5  * Copyright (c) 2005 Iain Hibbert.
    6  * Copyright (c) 2006 Itronix Inc.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of Itronix Inc. may not be used to endorse
   18  *    or promote products derived from this software without specific
   19  *    prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
   25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   28  * ON ANY THEORY OF LIABILITY, WHETHER IN
   29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31  * POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/kernel.h>
   36 #include <sys/mbuf.h>
   37 #include <sys/proc.h>
   38 #include <sys/queue.h>
   39 #include <sys/socket.h>
   40 #include <sys/socketvar.h>
   41 #include <sys/systm.h>
   42 #include <sys/endian.h>
   43 
   44 #include <netbt/bluetooth.h>
   45 #include <netbt/hci.h>
   46 #include <netbt/l2cap.h>
   47 
   48 /*******************************************************************************
   49  *
   50  *      L2CAP Channel - Upper Protocol API
   51  */
   52 
   53 /*
   54  * l2cap_attach(handle, btproto, upper)
   55  *
   56  *      attach new l2cap_channel to handle, populate
   57  *      with reasonable defaults
   58  */
   59 int
   60 l2cap_attach(struct l2cap_channel **handle,
   61                 const struct btproto *proto, void *upper)
   62 {
   63         struct l2cap_channel *chan;
   64 
   65         KKASSERT(handle != NULL);
   66         KKASSERT(proto != NULL);
   67         KKASSERT(upper != NULL);
   68 
   69         chan = kmalloc(sizeof(*chan), M_BLUETOOTH, M_NOWAIT | M_ZERO);
   70         if (chan == NULL)
   71                 return ENOMEM;
   72 
   73         chan->lc_proto = proto;
   74         chan->lc_upper = upper;
   75 
   76         chan->lc_state = L2CAP_CLOSED;
   77 
   78         chan->lc_lcid = L2CAP_NULL_CID;
   79         chan->lc_rcid = L2CAP_NULL_CID;
   80 
   81         chan->lc_laddr.bt_len = sizeof(struct sockaddr_bt);
   82         chan->lc_laddr.bt_family = AF_BLUETOOTH;
   83         chan->lc_laddr.bt_psm = L2CAP_PSM_ANY;
   84 
   85         chan->lc_raddr.bt_len = sizeof(struct sockaddr_bt);
   86         chan->lc_raddr.bt_family = AF_BLUETOOTH;
   87         chan->lc_raddr.bt_psm = L2CAP_PSM_ANY;
   88 
   89         chan->lc_imtu = L2CAP_MTU_DEFAULT;
   90         chan->lc_omtu = L2CAP_MTU_DEFAULT;
   91         chan->lc_flush = L2CAP_FLUSH_TIMO_DEFAULT;
   92 
   93         memcpy(&chan->lc_iqos, &l2cap_default_qos, sizeof(l2cap_qos_t));
   94         memcpy(&chan->lc_oqos, &l2cap_default_qos, sizeof(l2cap_qos_t));
   95 
   96         *handle = chan;
   97         return 0;
   98 }
   99 
  100 /*
  101  * l2cap_bind(l2cap_channel, sockaddr)
  102  *
  103  *      set local address of channel
  104  */
  105 int
  106 l2cap_bind(struct l2cap_channel *chan, struct sockaddr_bt *addr)
  107 {
  108 
  109         memcpy(&chan->lc_laddr, addr, sizeof(struct sockaddr_bt));
  110         return 0;
  111 }
  112 
  113 /*
  114  * l2cap_sockaddr(l2cap_channel, sockaddr)
  115  *
  116  *      get local address of channel
  117  */
  118 int
  119 l2cap_sockaddr(struct l2cap_channel *chan, struct sockaddr_bt *addr)
  120 {
  121         memcpy(addr, &chan->lc_laddr, sizeof(struct sockaddr_bt));
  122         return 0;
  123 }
  124 
  125 /*
  126  * l2cap_connect(l2cap_channel, sockaddr)
  127  *
  128  *      Initiate a connection to destination. This corresponds to
  129  *      "Open Channel Request" in the L2CAP specification and will
  130  *      result in one of the following:
  131  *
  132  *              proto->connected(upper)
  133  *              proto->disconnected(upper, error)
  134  *
  135  *      and, optionally
  136  *              proto->connecting(upper)
  137  */
  138 int
  139 l2cap_connect(struct l2cap_channel *chan, struct sockaddr_bt *dest)
  140 {
  141         struct hci_unit *unit;
  142         int err;
  143 
  144         memcpy(&chan->lc_raddr, dest, sizeof(struct sockaddr_bt));
  145 
  146         if (L2CAP_PSM_INVALID(chan->lc_raddr.bt_psm))
  147                 return EINVAL;
  148 
  149         if (bdaddr_any(&chan->lc_raddr.bt_bdaddr))
  150                 return EDESTADDRREQ;
  151 
  152         /* set local address if it needs setting */
  153         if (bdaddr_any(&chan->lc_laddr.bt_bdaddr)) {
  154                 err = hci_route_lookup(&chan->lc_laddr.bt_bdaddr,
  155                                         &chan->lc_raddr.bt_bdaddr);
  156                 if (err)
  157                         return err;
  158         }
  159 
  160         unit = hci_unit_lookup(&chan->lc_laddr.bt_bdaddr);
  161         if (unit == NULL)
  162                 return EHOSTUNREACH;
  163 
  164         /* attach to active list */
  165         err = l2cap_cid_alloc(chan);
  166         if (err)
  167                 return err;
  168 
  169         /* open link to remote device */
  170         chan->lc_link = hci_acl_open(unit, &chan->lc_raddr.bt_bdaddr);
  171         if (chan->lc_link == NULL)
  172                 return EHOSTUNREACH;
  173 
  174         /* set the link mode */
  175         err = l2cap_setmode(chan);
  176         if (err == EINPROGRESS) {
  177                 chan->lc_state = L2CAP_WAIT_SEND_CONNECT_REQ;
  178                 (*chan->lc_proto->connecting)(chan->lc_upper);
  179                 return 0;
  180         }
  181         if (err)
  182                 goto fail;
  183 
  184         /*
  185          * We can queue a connect request now even though the link may
  186          * not yet be open; Our mode setting is assured, and the queue
  187          * will be started automatically at the right time.
  188          */
  189         chan->lc_state = L2CAP_WAIT_RECV_CONNECT_RSP;
  190         err = l2cap_send_connect_req(chan);
  191         if (err)
  192                 goto fail;
  193 
  194         return 0;
  195 
  196 fail:
  197         chan->lc_state = L2CAP_CLOSED;
  198         hci_acl_close(chan->lc_link, err);
  199         chan->lc_link = NULL;
  200         return err;
  201 }
  202 
  203 /*
  204  * l2cap_peeraddr(l2cap_channel, sockaddr)
  205  *
  206  *      get remote address of channel
  207  */
  208 int
  209 l2cap_peeraddr(struct l2cap_channel *chan, struct sockaddr_bt *addr)
  210 {
  211         memcpy(addr, &chan->lc_raddr, sizeof(struct sockaddr_bt));
  212         return 0;
  213 }
  214 
  215 /*
  216  * l2cap_disconnect(l2cap_channel, linger)
  217  *
  218  *      Initiate L2CAP disconnection. This corresponds to
  219  *      "Close Channel Request" in the L2CAP specification
  220  *      and will result in a call to
  221  *
  222  *              proto->disconnected(upper, error)
  223  *
  224  *      when the disconnection is complete. If linger is set,
  225  *      the call will not be made until data has flushed from
  226  *      the queue.
  227  */
  228 int
  229 l2cap_disconnect(struct l2cap_channel *chan, int linger)
  230 {
  231         int err = 0;
  232 
  233         if (chan->lc_state == L2CAP_CLOSED
  234             || chan->lc_state == L2CAP_WAIT_DISCONNECT)
  235                 return EINVAL;
  236 
  237         chan->lc_flags |= L2CAP_SHUTDOWN;
  238 
  239         /*
  240          * no need to do anything unless the queue is empty or
  241          * we are not lingering..
  242          */
  243         if ((IF_QEMPTY(&chan->lc_txq) && chan->lc_pending == 0)
  244             || linger == 0) {
  245                 chan->lc_state = L2CAP_WAIT_DISCONNECT;
  246                 err = l2cap_send_disconnect_req(chan);
  247                 if (err)
  248                         l2cap_close(chan, err);
  249         }
  250         return err;
  251 }
  252 
  253 /*
  254  * l2cap_detach(handle)
  255  *
  256  *      Detach l2cap channel from handle & close it down
  257  */
  258 int
  259 l2cap_detach(struct l2cap_channel **handle)
  260 {
  261         struct l2cap_channel *chan;
  262 
  263         chan = *handle;
  264         *handle = NULL;
  265 
  266         if (chan->lc_state != L2CAP_CLOSED)
  267                 l2cap_close(chan, 0);
  268 
  269         if (chan->lc_lcid != L2CAP_NULL_CID) {
  270                 LIST_REMOVE(chan, lc_ncid);
  271                 chan->lc_lcid = L2CAP_NULL_CID;
  272         }
  273 
  274         IF_DRAIN(&chan->lc_txq);
  275 
  276         /*
  277          * Could implement some kind of delayed expunge to make sure that the
  278          * CID is really dead before it becomes available for reuse?
  279          */
  280 
  281         kfree(chan, M_BLUETOOTH);
  282         return 0;
  283 }
  284 
  285 /*
  286  * l2cap_listen(l2cap_channel)
  287  *
  288  *      Use this channel as a listening post (until detached). This will
  289  *      result in calls to:
  290  *
  291  *              proto->newconn(upper, laddr, raddr)
  292  *
  293  *      for incoming connections matching the psm and local address of the
  294  *      channel (NULL psm/address are permitted and match any protocol/device).
  295  *
  296  *      The upper layer should create and return a new channel.
  297  *
  298  *      You cannot use this channel for anything else subsequent to this call
  299  */
  300 int
  301 l2cap_listen(struct l2cap_channel *chan)
  302 {
  303         struct l2cap_channel *used, *prev = NULL;
  304 
  305         if (chan->lc_lcid != L2CAP_NULL_CID)
  306                 return EINVAL;
  307 
  308         if (chan->lc_laddr.bt_psm != L2CAP_PSM_ANY
  309             && L2CAP_PSM_INVALID(chan->lc_laddr.bt_psm))
  310                 return EADDRNOTAVAIL;
  311 
  312         /*
  313          * This CID is irrelevant, as the channel is not stored on the active
  314          * list and the socket code does not allow operations on listening
  315          * sockets, but we set it so the detach code knows to LIST_REMOVE the
  316          * channel.
  317          */
  318         chan->lc_lcid = L2CAP_SIGNAL_CID;
  319 
  320         /*
  321          * The list of listening channels is stored in an order such that new
  322          * listeners dont usurp current listeners, but that specific listening
  323          * takes precedence over promiscuous, and the connect request code can
  324          * easily use the first matching entry.
  325          */
  326         LIST_FOREACH(used, &l2cap_listen_list, lc_ncid) {
  327                 if (used->lc_laddr.bt_psm < chan->lc_laddr.bt_psm)
  328                         break;
  329 
  330                 if (used->lc_laddr.bt_psm == chan->lc_laddr.bt_psm
  331                         && bdaddr_any(&used->lc_laddr.bt_bdaddr)
  332                         && !bdaddr_any(&chan->lc_laddr.bt_bdaddr))
  333                         break;
  334 
  335                 prev = used;
  336         }
  337 
  338         if (prev == NULL)
  339                 LIST_INSERT_HEAD(&l2cap_listen_list, chan, lc_ncid);
  340         else
  341                 LIST_INSERT_AFTER(prev, chan, lc_ncid);
  342 
  343         return 0;
  344 }
  345 
  346 /*
  347  * l2cap_send(l2cap_channel, mbuf)
  348  *
  349  *      Output SDU on channel described by channel. This corresponds
  350  *      to "Send Data Request" in the L2CAP specification. The upper
  351  *      layer will be notified when SDU's have completed sending by a
  352  *      call to:
  353  *
  354  *              proto->complete(upper, n)
  355  *
  356  *      (currently n == 1)
  357  *
  358  *      Note: I'm not sure how this will work out, but I think that
  359  *      if outgoing Retransmission Mode or Flow Control Mode is
  360  *      negotiated then this call will not be made until the SDU has
  361  *      been acknowleged by the peer L2CAP entity. For 'Best Effort'
  362  *      it will be made when the packet has cleared the controller
  363  *      buffers.
  364  *
  365  *      We only support Basic mode so far, so encapsulate with a
  366  *      B-Frame header and start sending if we are not already
  367  */
  368 int
  369 l2cap_send(struct l2cap_channel *chan, struct mbuf *m)
  370 {
  371         l2cap_hdr_t *hdr;
  372         int plen;
  373 
  374         if (chan->lc_state == L2CAP_CLOSED) {
  375                 m_freem(m);
  376                 return ENOTCONN;
  377         }
  378 
  379         plen = m->m_pkthdr.len;
  380 
  381         DPRINTFN(5, "send %d bytes on CID #%d (pending = %d)\n",
  382                 plen, chan->lc_lcid, chan->lc_pending);
  383 
  384         /* Encapsulate with B-Frame */
  385         M_PREPEND(m, sizeof(l2cap_hdr_t), MB_DONTWAIT);
  386         if (m == NULL)
  387                 return ENOMEM;
  388 
  389         hdr = mtod(m, l2cap_hdr_t *);
  390         hdr->length = htole16(plen);
  391         hdr->dcid = htole16(chan->lc_rcid);
  392 
  393         /* Queue it on our list */
  394         IF_ENQUEUE(&chan->lc_txq, m);
  395 
  396         /* If we are not sending, then start doing so */
  397         if (chan->lc_pending == 0)
  398                 return l2cap_start(chan);
  399 
  400         return 0;
  401 }
  402 
  403 /*
  404  * l2cap_setopt(l2cap_channel, opt, addr)
  405  *
  406  *      Apply configuration options to channel. This corresponds to
  407  *      "Configure Channel Request" in the L2CAP specification.
  408  *
  409  *      for SO_L2CAP_LM, the settings will take effect when the
  410  *      channel is established. If the channel is already open,
  411  *      a call to
  412  *              proto->linkmode(upper, new)
  413  *
  414  *      will be made when the change is complete.
  415  */
  416 int
  417 l2cap_setopt(struct l2cap_channel *chan, int opt, void *addr)
  418 {
  419         int mode, err = 0;
  420         uint16_t mtu;
  421 
  422         switch (opt) {
  423         case SO_L2CAP_IMTU:     /* set Incoming MTU */
  424                 mtu = *(uint16_t *)addr;
  425                 if (mtu < L2CAP_MTU_MINIMUM)
  426                         err = EINVAL;
  427                 else if (chan->lc_state == L2CAP_CLOSED)
  428                         chan->lc_imtu = mtu;
  429                 else
  430                         err = EBUSY;
  431 
  432                 break;
  433 
  434         case SO_L2CAP_LM:       /* set link mode */
  435                 mode = *(int *)addr;
  436                 mode &= (L2CAP_LM_SECURE | L2CAP_LM_ENCRYPT | L2CAP_LM_AUTH);
  437 
  438                 if (mode & L2CAP_LM_SECURE)
  439                         mode |= L2CAP_LM_ENCRYPT;
  440 
  441                 if (mode & L2CAP_LM_ENCRYPT)
  442                         mode |= L2CAP_LM_AUTH;
  443 
  444                 chan->lc_mode = mode;
  445 
  446                 if (chan->lc_state == L2CAP_OPEN)
  447                         err = l2cap_setmode(chan);
  448 
  449                 break;
  450 
  451         case SO_L2CAP_OQOS:     /* set Outgoing QoS flow spec */
  452         case SO_L2CAP_FLUSH:    /* set Outgoing Flush Timeout */
  453         default:
  454                 err = ENOPROTOOPT;
  455                 break;
  456         }
  457 
  458         return err;
  459 }
  460 
  461 
  462 /*
  463  * Used in l2cap_socket for set options, coming from socket.
  464  */
  465 int
  466 l2cap_setopt2(struct l2cap_channel *chan, int opt, struct socket *so,
  467     struct sockopt *sopt)
  468 {
  469         int mode, err = 0;
  470         uint16_t mtu;
  471 
  472         switch (opt) {
  473         case SO_L2CAP_IMTU:     /* set Incoming MTU */
  474                 err = soopt_to_kbuf(sopt, &mtu, sizeof(uint16_t),
  475                     sizeof(uint16_t)); 
  476                 if (err)
  477                         break;
  478 
  479                 if (mtu < L2CAP_MTU_MINIMUM)
  480                         err = EINVAL;
  481                 else if (chan->lc_state == L2CAP_CLOSED)
  482                         chan->lc_imtu = mtu;
  483                 else
  484                         err = EBUSY;
  485 
  486                 break;
  487 
  488         case SO_L2CAP_LM:       /* set link mode */
  489                 err = soopt_to_kbuf(sopt, &mode, sizeof(int), sizeof(int)); 
  490                 if (err)
  491                         break;
  492 
  493                 mode &= (L2CAP_LM_SECURE | L2CAP_LM_ENCRYPT | L2CAP_LM_AUTH);
  494 
  495                 if (mode & L2CAP_LM_SECURE)
  496                         mode |= L2CAP_LM_ENCRYPT;
  497                 if (mode & L2CAP_LM_ENCRYPT)
  498                         mode |= L2CAP_LM_AUTH;
  499                 chan->lc_mode = mode;
  500 
  501                 if (chan->lc_state == L2CAP_OPEN)
  502                         err = l2cap_setmode(chan);
  503 
  504                 break;
  505 
  506         case SO_L2CAP_OQOS:     /* set Outgoing QoS flow spec */
  507         case SO_L2CAP_FLUSH:    /* set Outgoing Flush Timeout */
  508         default:
  509                 err = ENOPROTOOPT;
  510                 break;
  511         }
  512         return err;
  513 }
  514 
  515 /*
  516  * l2cap_getopt(l2cap_channel, opt, addr)
  517  *
  518  *      Return configuration parameters.
  519  */
  520 int
  521 l2cap_getopt(struct l2cap_channel *chan, int opt, void *addr)
  522 {
  523 
  524         switch (opt) {
  525         case SO_L2CAP_IMTU:     /* get Incoming MTU */
  526                 *(uint16_t *)addr = chan->lc_imtu;
  527                 return sizeof(uint16_t);
  528 
  529         case SO_L2CAP_OMTU:     /* get Outgoing MTU */
  530                 *(uint16_t *)addr = chan->lc_omtu;
  531                 return sizeof(uint16_t);
  532 
  533         case SO_L2CAP_IQOS:     /* get Incoming QoS flow spec */
  534                 memcpy(addr, &chan->lc_iqos, sizeof(l2cap_qos_t));
  535                 return sizeof(l2cap_qos_t);
  536 
  537         case SO_L2CAP_OQOS:     /* get Outgoing QoS flow spec */
  538                 memcpy(addr, &chan->lc_oqos, sizeof(l2cap_qos_t));
  539                 return sizeof(l2cap_qos_t);
  540 
  541         case SO_L2CAP_FLUSH:    /* get Flush Timeout */
  542                 *(uint16_t *)addr = chan->lc_flush;
  543                 return sizeof(uint16_t);
  544 
  545         case SO_L2CAP_LM:       /* get link mode */
  546                 *(int *)addr = chan->lc_mode;
  547                 return sizeof(int);
  548 
  549         default:
  550                 break;
  551         }
  552 
  553         return 0;
  554 }

Cache object: 1875e97aaba836de56687684416d91ec


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.