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

Cache object: 22a1298458b1ed40531f83a8cab1e06d


[ 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.