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_signal.c

Version: -  FREEBSD  -  FREEBSD11  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: l2cap_signal.c,v 1.4 2008/02/24 21:42:03 uwe Exp $    */
    2 /*      $NetBSD: l2cap_signal.c,v 1.9 2007/11/10 23:12:23 plunky 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/systm.h>
   40 
   41 #include <netbt/bluetooth.h>
   42 #include <netbt/hci.h>
   43 #include <netbt/l2cap.h>
   44 
   45 /*******************************************************************************
   46  *
   47  *      L2CAP Signal processing
   48  */
   49 
   50 static void l2cap_recv_command_rej(struct mbuf *, struct hci_link *);
   51 static void l2cap_recv_connect_req(struct mbuf *, struct hci_link *);
   52 static void l2cap_recv_connect_rsp(struct mbuf *, struct hci_link *);
   53 static void l2cap_recv_config_req(struct mbuf *, struct hci_link *);
   54 static void l2cap_recv_config_rsp(struct mbuf *, struct hci_link *);
   55 static void l2cap_recv_disconnect_req(struct mbuf *, struct hci_link *);
   56 static void l2cap_recv_disconnect_rsp(struct mbuf *, struct hci_link *);
   57 static void l2cap_recv_info_req(struct mbuf *, struct hci_link *);
   58 static int l2cap_send_signal(struct hci_link *, uint8_t, uint8_t, uint16_t, void *);
   59 static int l2cap_send_command_rej(struct hci_link *, uint8_t, uint16_t, ...);
   60 
   61 /*
   62  * process incoming signal packets (CID 0x0001). Can contain multiple
   63  * requests/responses.
   64  */
   65 void
   66 l2cap_recv_signal(struct mbuf *m, struct hci_link *link)
   67 {
   68         l2cap_cmd_hdr_t cmd;
   69 
   70         for(;;) {
   71                 if (m->m_pkthdr.len == 0)
   72                         goto finish;
   73 
   74                 if (m->m_pkthdr.len < sizeof(cmd))
   75                         goto reject;
   76 
   77                 m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
   78                 cmd.length = letoh16(cmd.length);
   79 
   80                 if (m->m_pkthdr.len < sizeof(cmd) + cmd.length)
   81                         goto reject;
   82 
   83                 DPRINTFN(2, "(%s) code %d, ident %d, len %d\n",
   84                         device_xname(link->hl_unit->hci_dev),
   85                         cmd.code, cmd.ident, cmd.length);
   86 
   87                 switch (cmd.code) {
   88                 case L2CAP_COMMAND_REJ:
   89                         if (cmd.length > sizeof(l2cap_cmd_rej_cp))
   90                                 goto finish;
   91 
   92                         l2cap_recv_command_rej(m, link);
   93                         break;
   94 
   95                 case L2CAP_CONNECT_REQ:
   96                         if (cmd.length != sizeof(l2cap_con_req_cp))
   97                                 goto reject;
   98 
   99                         l2cap_recv_connect_req(m, link);
  100                         break;
  101 
  102                 case L2CAP_CONNECT_RSP:
  103                         if (cmd.length != sizeof(l2cap_con_rsp_cp))
  104                                 goto finish;
  105 
  106                         l2cap_recv_connect_rsp(m, link);
  107                         break;
  108 
  109                 case L2CAP_CONFIG_REQ:
  110                         l2cap_recv_config_req(m, link);
  111                         break;
  112 
  113                 case L2CAP_CONFIG_RSP:
  114                         l2cap_recv_config_rsp(m, link);
  115                         break;
  116 
  117                 case L2CAP_DISCONNECT_REQ:
  118                         if (cmd.length != sizeof(l2cap_discon_req_cp))
  119                                 goto reject;
  120 
  121                         l2cap_recv_disconnect_req(m, link);
  122                         break;
  123 
  124                 case L2CAP_DISCONNECT_RSP:
  125                         if (cmd.length != sizeof(l2cap_discon_rsp_cp))
  126                                 goto finish;
  127 
  128                         l2cap_recv_disconnect_rsp(m, link);
  129                         break;
  130 
  131                 case L2CAP_ECHO_REQ:
  132                         m_adj(m, sizeof(cmd) + cmd.length);
  133                         l2cap_send_signal(link, L2CAP_ECHO_RSP, cmd.ident,
  134                                         0, NULL);
  135                         break;
  136 
  137                 case L2CAP_ECHO_RSP:
  138                         m_adj(m, sizeof(cmd) + cmd.length);
  139                         break;
  140 
  141                 case L2CAP_INFO_REQ:
  142                         if (cmd.length != sizeof(l2cap_info_req_cp))
  143                                 goto reject;
  144 
  145                         l2cap_recv_info_req(m, link);
  146                         break;
  147 
  148                 case L2CAP_INFO_RSP:
  149                         m_adj(m, sizeof(cmd) + cmd.length);
  150                         break;
  151 
  152                 default:
  153                         goto reject;
  154                 }
  155         }
  156 
  157 #ifdef DIAGNOSTIC
  158         panic("impossible!");
  159 #endif
  160 
  161 reject:
  162         l2cap_send_command_rej(link, cmd.ident, L2CAP_REJ_NOT_UNDERSTOOD);
  163 finish:
  164         m_freem(m);
  165 }
  166 
  167 /*
  168  * Process Received Command Reject. For now we dont try to recover gracefully
  169  * from this, it probably means that the link is garbled or the other end is
  170  * insufficiently capable of handling normal traffic. (not *my* fault, no way!)
  171  */
  172 static void
  173 l2cap_recv_command_rej(struct mbuf *m, struct hci_link *link)
  174 {
  175         struct l2cap_req *req;
  176         struct l2cap_channel *chan;
  177         l2cap_cmd_hdr_t cmd;
  178         l2cap_cmd_rej_cp cp;
  179 
  180         m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
  181         m_adj(m, sizeof(cmd));
  182 
  183         cmd.length = letoh16(cmd.length);
  184 
  185         m_copydata(m, 0, cmd.length, (caddr_t)&cp);
  186         m_adj(m, cmd.length);
  187 
  188         req = l2cap_request_lookup(link, cmd.ident);
  189         if (req == NULL)
  190                 return;
  191 
  192         switch (letoh16(cp.reason)) {
  193         case L2CAP_REJ_NOT_UNDERSTOOD:
  194                 /*
  195                  * I dont know what to do, just move up the timeout
  196                  */
  197                 timeout_add(&req->lr_rtx, 0);
  198                 break;
  199 
  200         case L2CAP_REJ_MTU_EXCEEDED:
  201                 /*
  202                  * I didnt send any commands over L2CAP_MTU_MINIMUM size, but..
  203                  *
  204                  * XXX maybe we should resend this, instead?
  205                  */
  206                 link->hl_mtu = letoh16(cp.data[0]);
  207                 timeout_add(&req->lr_rtx, 0);
  208                 break;
  209 
  210         case L2CAP_REJ_INVALID_CID:
  211                 /*
  212                  * Well, if they dont have such a channel then our channel is
  213                  * most likely closed. Make it so.
  214                  */
  215                 chan = req->lr_chan;
  216                 l2cap_request_free(req);
  217                 if (chan != NULL && chan->lc_state != L2CAP_CLOSED)
  218                         l2cap_close(chan, ECONNABORTED);
  219 
  220                 break;
  221 
  222         default:
  223                 UNKNOWN(letoh16(cp.reason));
  224                 break;
  225         }
  226 }
  227 
  228 /*
  229  * Process Received Connect Request. Find listening channel matching
  230  * psm & addr and ask upper layer for a new channel.
  231  */
  232 static void
  233 l2cap_recv_connect_req(struct mbuf *m, struct hci_link *link)
  234 {
  235         struct sockaddr_bt laddr, raddr;
  236         struct l2cap_channel *chan, *new;
  237         l2cap_cmd_hdr_t cmd;
  238         l2cap_con_req_cp cp;
  239         int err;
  240 
  241         /* extract cmd */
  242         m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
  243         m_adj(m, sizeof(cmd));
  244 
  245         /* extract request */
  246         m_copydata(m, 0, sizeof(cp), (caddr_t)&cp);
  247         m_adj(m, sizeof(cp));
  248 
  249         cp.scid = letoh16(cp.scid);
  250         cp.psm = letoh16(cp.psm);
  251 
  252         memset(&laddr, 0, sizeof(struct sockaddr_bt));
  253         laddr.bt_len = sizeof(struct sockaddr_bt);
  254         laddr.bt_family = AF_BLUETOOTH;
  255         laddr.bt_psm = cp.psm;
  256         bdaddr_copy(&laddr.bt_bdaddr, &link->hl_unit->hci_bdaddr);
  257 
  258         memset(&raddr, 0, sizeof(struct sockaddr_bt));
  259         raddr.bt_len = sizeof(struct sockaddr_bt);
  260         raddr.bt_family = AF_BLUETOOTH;
  261         raddr.bt_psm = cp.psm;
  262         bdaddr_copy(&raddr.bt_bdaddr, &link->hl_bdaddr);
  263 
  264         LIST_FOREACH(chan, &l2cap_listen_list, lc_ncid) {
  265                 if (chan->lc_laddr.bt_psm != laddr.bt_psm
  266                     && chan->lc_laddr.bt_psm != L2CAP_PSM_ANY)
  267                         continue;
  268 
  269                 if (!bdaddr_same(&laddr.bt_bdaddr, &chan->lc_laddr.bt_bdaddr)
  270                     && bdaddr_any(&chan->lc_laddr.bt_bdaddr) == 0)
  271                         continue;
  272 
  273                 new= (*chan->lc_proto->newconn)(chan->lc_upper, &laddr, &raddr);
  274                 if (new == NULL)
  275                         continue;
  276 
  277                 err = l2cap_cid_alloc(new);
  278                 if (err) {
  279                         l2cap_send_connect_rsp(link, cmd.ident,
  280                                                 0, cp.scid,
  281                                                 L2CAP_NO_RESOURCES);
  282 
  283                         (*new->lc_proto->disconnected)(new->lc_upper, err);
  284                         return;
  285                 }
  286 
  287                 new->lc_link = hci_acl_open(link->hl_unit, &link->hl_bdaddr);
  288                 KASSERT(new->lc_link == link);
  289 
  290                 new->lc_rcid = cp.scid;
  291                 new->lc_ident = cmd.ident;
  292 
  293                 memcpy(&new->lc_laddr, &laddr, sizeof(struct sockaddr_bt));
  294                 memcpy(&new->lc_raddr, &raddr, sizeof(struct sockaddr_bt));
  295 
  296                 new->lc_mode = chan->lc_mode;
  297 
  298                 err = l2cap_setmode(new);
  299                 if (err == EINPROGRESS) {
  300                         new->lc_state = L2CAP_WAIT_SEND_CONNECT_RSP;
  301                         (*new->lc_proto->connecting)(new->lc_upper);
  302                         return;
  303                 }
  304                 if (err) {
  305                         new->lc_state = L2CAP_CLOSED;
  306                         hci_acl_close(link, err);
  307                         new->lc_link = NULL;
  308 
  309                         l2cap_send_connect_rsp(link, cmd.ident,
  310                                                 0, cp.scid,
  311                                                 L2CAP_NO_RESOURCES);
  312 
  313                         (*new->lc_proto->disconnected)(new->lc_upper, err);
  314                         return;
  315                 }
  316 
  317                 err = l2cap_send_connect_rsp(link, cmd.ident,
  318                                               new->lc_lcid, new->lc_rcid,
  319                                               L2CAP_SUCCESS);
  320                 if (err) {
  321                         l2cap_close(new, err);
  322                         return;
  323                 }
  324 
  325                 new->lc_state = L2CAP_WAIT_CONFIG;
  326                 new->lc_flags |= (L2CAP_WAIT_CONFIG_REQ | L2CAP_WAIT_CONFIG_RSP);
  327                 err = l2cap_send_config_req(new);
  328                 if (err)
  329                         l2cap_close(new, err);
  330 
  331                 return;
  332         }
  333 
  334         l2cap_send_connect_rsp(link, cmd.ident,
  335                                 0, cp.scid,
  336                                 L2CAP_PSM_NOT_SUPPORTED);
  337 }
  338 
  339 /*
  340  * Process Received Connect Response.
  341  */
  342 static void
  343 l2cap_recv_connect_rsp(struct mbuf *m, struct hci_link *link)
  344 {
  345         l2cap_cmd_hdr_t cmd;
  346         l2cap_con_rsp_cp cp;
  347         struct l2cap_req *req;
  348         struct l2cap_channel *chan;
  349 
  350         m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
  351         m_adj(m, sizeof(cmd));
  352 
  353         m_copydata(m, 0, sizeof(cp), (caddr_t)&cp);
  354         m_adj(m, sizeof(cp));
  355 
  356         cp.scid = letoh16(cp.scid);
  357         cp.dcid = letoh16(cp.dcid);
  358         cp.result = letoh16(cp.result);
  359 
  360         req = l2cap_request_lookup(link, cmd.ident);
  361         if (req == NULL || req->lr_code != L2CAP_CONNECT_REQ)
  362                 return;
  363 
  364         chan = req->lr_chan;
  365         if (chan != NULL && chan->lc_lcid != cp.scid)
  366                 return;
  367 
  368         if (chan == NULL || chan->lc_state != L2CAP_WAIT_RECV_CONNECT_RSP) {
  369                 l2cap_request_free(req);
  370                 return;
  371         }
  372 
  373         switch (cp.result) {
  374         case L2CAP_SUCCESS:
  375                 /*
  376                  * Ok, at this point we have a connection to the other party. We
  377                  * could indicate upstream that we are ready for business and
  378                  * wait for a "Configure Channel Request" but I'm not so sure
  379                  * that is required in our case - we will proceed directly to
  380                  * sending our config request. We set two state bits because in
  381                  * the config state we are waiting for requests and responses.
  382                  */
  383                 l2cap_request_free(req);
  384                 chan->lc_rcid = cp.dcid;
  385                 chan->lc_state = L2CAP_WAIT_CONFIG;
  386                 chan->lc_flags |= (L2CAP_WAIT_CONFIG_REQ | L2CAP_WAIT_CONFIG_RSP);
  387                 l2cap_send_config_req(chan);
  388                 break;
  389 
  390         case L2CAP_PENDING:
  391                 /* XXX dont release request, should start eRTX timeout? */
  392                 (*chan->lc_proto->connecting)(chan->lc_upper);
  393                 break;
  394 
  395         case L2CAP_PSM_NOT_SUPPORTED:
  396         case L2CAP_SECURITY_BLOCK:
  397         case L2CAP_NO_RESOURCES:
  398         default:
  399                 l2cap_request_free(req);
  400                 l2cap_close(chan, ECONNREFUSED);
  401                 break;
  402         }
  403 }
  404 
  405 /*
  406  * Process Received Config Request.
  407  */
  408 static void
  409 l2cap_recv_config_req(struct mbuf *m, struct hci_link *link)
  410 {
  411         uint8_t buf[L2CAP_MTU_MINIMUM];
  412         l2cap_cmd_hdr_t cmd;
  413         l2cap_cfg_req_cp cp;
  414         l2cap_cfg_opt_t opt;
  415         l2cap_cfg_opt_val_t val;
  416         l2cap_cfg_rsp_cp rp;
  417         struct l2cap_channel *chan;
  418         int left, len;
  419 
  420         m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
  421         m_adj(m, sizeof(cmd));
  422         left = letoh16(cmd.length);
  423 
  424         if (left < sizeof(cp))
  425                 goto reject;
  426 
  427         m_copydata(m, 0, sizeof(cp), (caddr_t)&cp);
  428         m_adj(m, sizeof(cp));
  429         left -= sizeof(cp);
  430 
  431         cp.dcid = letoh16(cp.dcid);
  432         cp.flags = letoh16(cp.flags);
  433 
  434         chan = l2cap_cid_lookup(cp.dcid);
  435         if (chan == NULL || chan->lc_link != link
  436             || chan->lc_state != L2CAP_WAIT_CONFIG
  437             || (chan->lc_flags & L2CAP_WAIT_CONFIG_REQ) == 0) {
  438                 /* XXX we should really accept reconfiguration requests */
  439                 l2cap_send_command_rej(link, cmd.ident, L2CAP_REJ_INVALID_CID,
  440                                         L2CAP_NULL_CID, cp.dcid);
  441                 goto out;
  442         }
  443 
  444         /* ready our response packet */
  445         rp.scid = htole16(chan->lc_rcid);
  446         rp.flags = 0;   /* "No Continuation" */
  447         rp.result = L2CAP_SUCCESS;
  448         len = sizeof(rp);
  449 
  450         /*
  451          * Process the packet. We build the return packet on the fly adding any
  452          * unacceptable parameters as we go. As we can only return one result,
  453          * unknown option takes precedence so we start our return packet anew
  454          * and ignore option values thereafter as they will be re-sent.
  455          *
  456          * Since we do not support enough options to make overflowing the min
  457          * MTU size an issue in normal use, we just reject config requests that
  458          * make that happen. This could be because options are repeated or the
  459          * packet is corrupted in some way.
  460          *
  461          * If unknown option types threaten to overflow the packet, we just
  462          * ignore them. We can deny them next time.
  463          */
  464         while (left > 0) {
  465                 if (left < sizeof(opt))
  466                         goto reject;
  467 
  468                 m_copydata(m, 0, sizeof(opt), (caddr_t)&opt);
  469                 m_adj(m, sizeof(opt));
  470                 left -= sizeof(opt);
  471 
  472                 if (left < opt.length)
  473                         goto reject;
  474 
  475                 switch(opt.type & L2CAP_OPT_HINT_MASK) {
  476                 case L2CAP_OPT_MTU:
  477                         if (rp.result == L2CAP_UNKNOWN_OPTION)
  478                                 break;
  479 
  480                         if (opt.length != L2CAP_OPT_MTU_SIZE)
  481                                 goto reject;
  482 
  483                         m_copydata(m, 0, L2CAP_OPT_MTU_SIZE, (caddr_t)&val);
  484                         val.mtu = letoh16(val.mtu);
  485 
  486                         /*
  487                          * XXX how do we know what the minimum acceptable MTU is
  488                          * for a channel? Spec says some profiles have a higher
  489                          * minimum but I have no way to find that out at this
  490                          * juncture..
  491                          */
  492                         if (val.mtu < L2CAP_MTU_MINIMUM) {
  493                                 if (len + sizeof(opt) + L2CAP_OPT_MTU_SIZE > sizeof(buf))
  494                                         goto reject;
  495 
  496                                 rp.result = L2CAP_UNACCEPTABLE_PARAMS;
  497                                 memcpy(buf + len, &opt, sizeof(opt));
  498                                 len += sizeof(opt);
  499                                 val.mtu = htole16(L2CAP_MTU_MINIMUM);
  500                                 memcpy(buf + len, &val, L2CAP_OPT_MTU_SIZE);
  501                                 len += L2CAP_OPT_MTU_SIZE;
  502                         } else
  503                                 chan->lc_omtu = val.mtu;
  504 
  505                         break;
  506 
  507                 case L2CAP_OPT_FLUSH_TIMO:
  508                         if (rp.result == L2CAP_UNKNOWN_OPTION)
  509                                 break;
  510 
  511                         if (opt.length != L2CAP_OPT_FLUSH_TIMO_SIZE)
  512                                 goto reject;
  513 
  514                         /*
  515                          * I think that this is informational only - he is
  516                          * informing us of the flush timeout he will be using.
  517                          * I dont think this affects us in any significant way,
  518                          * so just ignore this value for now.
  519                          */
  520                         break;
  521 
  522                 case L2CAP_OPT_QOS:
  523                         if (rp.result == L2CAP_UNKNOWN_OPTION)
  524                                 break;
  525 
  526                         if (opt.length != L2CAP_OPT_QOS_SIZE)
  527                                 goto reject;
  528 
  529                         m_copydata(m, 0, L2CAP_OPT_QOS_SIZE, (caddr_t)&val);
  530                         if (val.qos.service_type == L2CAP_QOS_NO_TRAFFIC ||
  531                             val.qos.service_type == L2CAP_QOS_BEST_EFFORT)
  532                                 /*
  533                                  * In accordance with the spec, we choose to
  534                                  * ignore the fields an provide no response.
  535                                  */
  536                                 break;
  537 
  538                         if (len + sizeof(opt) + L2CAP_OPT_QOS_SIZE > sizeof(buf))
  539                                 goto reject;
  540 
  541                         if (val.qos.service_type != L2CAP_QOS_GUARANTEED) {
  542                                 /*
  543                                  * Instead of sending an "unacceptable
  544                                  * parameters" response, treat this as an
  545                                  * unknown option and include the option
  546                                  * value in the response.
  547                                  */
  548                                 rp.result = L2CAP_UNKNOWN_OPTION;
  549                         } else {
  550                                 /*
  551                                  * According to the spec, we must return
  552                                  * specific values for wild card parameters.
  553                                  * I don't know what to return without lying,
  554                                  * so return "unacceptable parameters" and
  555                                  * specify the preferred service type as
  556                                  * "Best Effort".
  557                                  */
  558                                 rp.result = L2CAP_UNACCEPTABLE_PARAMS;
  559                                 val.qos.service_type = L2CAP_QOS_BEST_EFFORT;
  560                         }
  561 
  562                         memcpy(buf + len, &opt, sizeof(opt));
  563                         len += sizeof(opt);
  564                         memcpy(buf + len, &val, L2CAP_OPT_QOS_SIZE);
  565                         len += L2CAP_OPT_QOS_SIZE;
  566                         break;
  567 
  568                 default:
  569                         /* ignore hints */
  570                         if (opt.type & L2CAP_OPT_HINT_BIT)
  571                                 break;
  572 
  573                         /* unknown options supersede all else */
  574                         if (rp.result != L2CAP_UNKNOWN_OPTION) {
  575                                 rp.result = L2CAP_UNKNOWN_OPTION;
  576                                 len = sizeof(rp);
  577                         }
  578 
  579                         /* ignore if it doesn't fit */
  580                         if (len + sizeof(opt) > sizeof(buf))
  581                                 break;
  582 
  583                         /* return unknown option type, but no data */
  584                         buf[len++] = opt.type;
  585                         buf[len++] = 0;
  586                         break;
  587                 }
  588 
  589                 m_adj(m, opt.length);
  590                 left -= opt.length;
  591         }
  592 
  593         rp.result = htole16(rp.result);
  594         memcpy(buf, &rp, sizeof(rp));
  595         l2cap_send_signal(link, L2CAP_CONFIG_RSP, cmd.ident, len, buf);
  596 
  597         if ((cp.flags & L2CAP_OPT_CFLAG_BIT) == 0
  598             && rp.result == letoh16(L2CAP_SUCCESS)) {
  599 
  600                 chan->lc_flags &= ~L2CAP_WAIT_CONFIG_REQ;
  601 
  602                 if ((chan->lc_flags & L2CAP_WAIT_CONFIG_RSP) == 0) {
  603                         chan->lc_state = L2CAP_OPEN;
  604                         /* XXX how to distinguish REconfiguration? */
  605                         (*chan->lc_proto->connected)(chan->lc_upper);
  606                 }
  607         }
  608         return;
  609 
  610 reject:
  611         l2cap_send_command_rej(link, cmd.ident, L2CAP_REJ_NOT_UNDERSTOOD);
  612 out:
  613         m_adj(m, left);
  614 }
  615 
  616 /*
  617  * Process Received Config Response.
  618  */
  619 static void
  620 l2cap_recv_config_rsp(struct mbuf *m, struct hci_link *link)
  621 {
  622         l2cap_cmd_hdr_t cmd;
  623         l2cap_cfg_rsp_cp cp;
  624         l2cap_cfg_opt_t opt;
  625         l2cap_cfg_opt_val_t val;
  626         struct l2cap_req *req;
  627         struct l2cap_channel *chan;
  628         int left;
  629 
  630         m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
  631         m_adj(m, sizeof(cmd));
  632         left = letoh16(cmd.length);
  633 
  634         if (left < sizeof(cp))
  635                 goto out;
  636 
  637         m_copydata(m, 0, sizeof(cp), (caddr_t)&cp);
  638         m_adj(m, sizeof(cp));
  639         left -= sizeof(cp);
  640 
  641         cp.scid = letoh16(cp.scid);
  642         cp.flags = letoh16(cp.flags);
  643         cp.result = letoh16(cp.result);
  644 
  645         req = l2cap_request_lookup(link, cmd.ident);
  646         if (req == NULL || req->lr_code != L2CAP_CONFIG_REQ)
  647                 goto out;
  648 
  649         chan = req->lr_chan;
  650         if (chan != NULL && chan->lc_lcid != cp.scid)
  651                 goto out;
  652 
  653         l2cap_request_free(req);
  654 
  655         if (chan == NULL || chan->lc_state != L2CAP_WAIT_CONFIG
  656             || (chan->lc_flags & L2CAP_WAIT_CONFIG_RSP) == 0)
  657                 goto out;
  658 
  659         if ((cp.flags & L2CAP_OPT_CFLAG_BIT)) {
  660                 l2cap_cfg_req_cp rp;
  661 
  662                 /*
  663                  * They have more to tell us and want another ID to
  664                  * use, so send an empty config request
  665                  */
  666                 if (l2cap_request_alloc(chan, L2CAP_CONFIG_REQ))
  667                         goto discon;
  668 
  669                 rp.dcid = htole16(cp.scid);
  670                 rp.flags = 0;
  671 
  672                 if (l2cap_send_signal(link, L2CAP_CONFIG_REQ, link->hl_lastid,
  673                                         sizeof(rp), &rp))
  674                         goto discon;
  675         }
  676 
  677         switch(cp.result) {
  678         case L2CAP_SUCCESS:
  679                 /*
  680                  * If continuation flag was not set, our config request was
  681                  * accepted. We may have to wait for their config request to
  682                  * complete, so check that but otherwise we are open
  683                  *
  684                  * There may be 'advisory' values in the packet but we just
  685                  * ignore those..
  686                  */
  687                 if ((cp.flags & L2CAP_OPT_CFLAG_BIT) == 0) {
  688                         chan->lc_flags &= ~L2CAP_WAIT_CONFIG_RSP;
  689 
  690                         if ((chan->lc_flags & L2CAP_WAIT_CONFIG_REQ) == 0) {
  691                                 chan->lc_state = L2CAP_OPEN;
  692                                 /* XXX how to distinguish REconfiguration? */
  693                                 (*chan->lc_proto->connected)(chan->lc_upper);
  694                         }
  695                 }
  696                 goto out;
  697 
  698         case L2CAP_UNACCEPTABLE_PARAMS:
  699                 /*
  700                  * Packet contains unacceptable parameters with preferred values
  701                  */
  702                 while (left > 0) {
  703                         if (left < sizeof(opt))
  704                                 goto discon;
  705 
  706                         m_copydata(m, 0, sizeof(opt), (caddr_t)&opt);
  707                         m_adj(m, sizeof(opt));
  708                         left -= sizeof(opt);
  709 
  710                         if (left < opt.length)
  711                                 goto discon;
  712 
  713                         switch (opt.type) {
  714                         case L2CAP_OPT_MTU:
  715                                 if (opt.length != L2CAP_OPT_MTU_SIZE)
  716                                         goto discon;
  717 
  718                                 m_copydata(m, 0, L2CAP_OPT_MTU_SIZE, (caddr_t)&val);
  719                                 chan->lc_imtu = letoh16(val.mtu);
  720                                 if (chan->lc_imtu < L2CAP_MTU_MINIMUM)
  721                                         chan->lc_imtu = L2CAP_MTU_DEFAULT;
  722                                 break;
  723 
  724                         case L2CAP_OPT_FLUSH_TIMO:
  725                                 if (opt.length != L2CAP_OPT_FLUSH_TIMO_SIZE)
  726                                         goto discon;
  727 
  728                                 /*
  729                                  * Spec says: If we cannot honor proposed value,
  730                                  * either disconnect or try again with original
  731                                  * value. I can't really see why they want to
  732                                  * interfere with OUR flush timeout in any case
  733                                  * so we just punt for now.
  734                                  */
  735                                 goto discon;
  736 
  737                         case L2CAP_OPT_QOS:
  738                                 break;
  739 
  740                         default:
  741                                 UNKNOWN(opt.type);
  742                                 goto discon;
  743                         }
  744 
  745                         m_adj(m, opt.length);
  746                         left -= opt.length;
  747                 }
  748 
  749                 if ((cp.flags & L2CAP_OPT_CFLAG_BIT) == 0)
  750                         l2cap_send_config_req(chan);    /* no state change */
  751 
  752                 goto out;
  753 
  754         case L2CAP_REJECT:
  755                 goto discon;
  756 
  757         case L2CAP_UNKNOWN_OPTION:
  758                 /*
  759                  * Packet contains options not understood. Turn off unknown
  760                  * options by setting them to default values (means they will
  761                  * not be requested again).
  762                  *
  763                  * If our option was already off then fail (paranoia?)
  764                  *
  765                  * XXX Should we consider that options were set for a reason?
  766                  */
  767                 while (left > 0) {
  768                         if (left < sizeof(opt))
  769                                 goto discon;
  770 
  771                         m_copydata(m, 0, sizeof(opt), (caddr_t)&opt);
  772                         m_adj(m, sizeof(opt));
  773                         left -= sizeof(opt);
  774 
  775                         if (left < opt.length)
  776                                 goto discon;
  777 
  778                         m_adj(m, opt.length);
  779                         left -= opt.length;
  780 
  781                         switch(opt.type) {
  782                         case L2CAP_OPT_MTU:
  783                                 if (chan->lc_imtu == L2CAP_MTU_DEFAULT)
  784                                         goto discon;
  785 
  786                                 chan->lc_imtu = L2CAP_MTU_DEFAULT;
  787                                 break;
  788 
  789                         case L2CAP_OPT_FLUSH_TIMO:
  790                                 if (chan->lc_flush == L2CAP_FLUSH_TIMO_DEFAULT)
  791                                         goto discon;
  792 
  793                                 chan->lc_flush = L2CAP_FLUSH_TIMO_DEFAULT;
  794                                 break;
  795 
  796                         case L2CAP_OPT_QOS:
  797                                 break;
  798 
  799                         default:
  800                                 UNKNOWN(opt.type);
  801                                 goto discon;
  802                         }
  803                 }
  804 
  805                 if ((cp.flags & L2CAP_OPT_CFLAG_BIT) == 0)
  806                         l2cap_send_config_req(chan);    /* no state change */
  807 
  808                 goto out;
  809 
  810         default:
  811                 UNKNOWN(cp.result);
  812                 goto discon;
  813         }
  814 
  815         DPRINTF("how did I get here!?\n");
  816 
  817 discon:
  818         l2cap_send_disconnect_req(chan);
  819         l2cap_close(chan, ECONNABORTED);
  820 
  821 out:
  822         m_adj(m, left);
  823 }
  824 
  825 /*
  826  * Process Received Disconnect Request. We must validate scid and dcid
  827  * just in case but otherwise this connection is finished.
  828  */
  829 static void
  830 l2cap_recv_disconnect_req(struct mbuf *m, struct hci_link *link)
  831 {
  832         l2cap_cmd_hdr_t cmd;
  833         l2cap_discon_req_cp cp;
  834         l2cap_discon_rsp_cp rp;
  835         struct l2cap_channel *chan;
  836 
  837         m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
  838         m_adj(m, sizeof(cmd));
  839 
  840         m_copydata(m, 0, sizeof(cp), (caddr_t)&cp);
  841         m_adj(m, sizeof(cp));
  842 
  843         cp.scid = letoh16(cp.scid);
  844         cp.dcid = letoh16(cp.dcid);
  845 
  846         chan = l2cap_cid_lookup(cp.dcid);
  847         if (chan == NULL || chan->lc_link != link || chan->lc_rcid != cp.scid) {
  848                 l2cap_send_command_rej(link, cmd.ident, L2CAP_REJ_INVALID_CID,
  849                                         cp.dcid, cp.scid);
  850                 return;
  851         }
  852 
  853         rp.dcid = htole16(chan->lc_lcid);
  854         rp.scid = htole16(chan->lc_rcid);
  855         l2cap_send_signal(link, L2CAP_DISCONNECT_RSP, cmd.ident,
  856                                 sizeof(rp), &rp);
  857 
  858         if (chan->lc_state != L2CAP_CLOSED)
  859                 l2cap_close(chan, ECONNRESET);
  860 }
  861 
  862 /*
  863  * Process Received Disconnect Response. We must validate scid and dcid but
  864  * unless we were waiting for this signal, ignore it.
  865  */
  866 static void
  867 l2cap_recv_disconnect_rsp(struct mbuf *m, struct hci_link *link)
  868 {
  869         l2cap_cmd_hdr_t cmd;
  870         l2cap_discon_rsp_cp cp;
  871         struct l2cap_req *req;
  872         struct l2cap_channel *chan;
  873 
  874         m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
  875         m_adj(m, sizeof(cmd));
  876 
  877         m_copydata(m, 0, sizeof(cp), (caddr_t)&cp);
  878         m_adj(m, sizeof(cp));
  879 
  880         cp.scid = letoh16(cp.scid);
  881         cp.dcid = letoh16(cp.dcid);
  882 
  883         req = l2cap_request_lookup(link, cmd.ident);
  884         if (req == NULL || req->lr_code != L2CAP_DISCONNECT_REQ)
  885                 return;
  886 
  887         chan = req->lr_chan;
  888         if (chan == NULL
  889             || chan->lc_lcid != cp.scid
  890             || chan->lc_rcid != cp.dcid)
  891                 return;
  892 
  893         l2cap_request_free(req);
  894 
  895         if (chan->lc_state != L2CAP_WAIT_DISCONNECT)
  896                 return;
  897 
  898         l2cap_close(chan, 0);
  899 }
  900 
  901 /*
  902  * Process Received Info Request. We must respond but alas dont
  903  * support anything as yet so thats easy.
  904  */
  905 static void
  906 l2cap_recv_info_req(struct mbuf *m, struct hci_link *link)
  907 {
  908         l2cap_cmd_hdr_t cmd;
  909         l2cap_info_req_cp cp;
  910         l2cap_info_rsp_cp rp;
  911 
  912         m_copydata(m, 0, sizeof(cmd), (caddr_t)&cmd);
  913         m_adj(m, sizeof(cmd));
  914 
  915         m_copydata(m, 0, sizeof(cp), (caddr_t)&cp);
  916         m_adj(m, sizeof(cp));
  917 
  918         switch(letoh16(cp.type)) {
  919         case L2CAP_CONNLESS_MTU:
  920         case L2CAP_EXTENDED_FEATURES:
  921         default:
  922                 rp.type = cp.type;
  923                 rp.result = htole16(L2CAP_NOT_SUPPORTED);
  924 
  925                 l2cap_send_signal(link, L2CAP_INFO_RSP, cmd.ident,
  926                                         sizeof(rp), &rp);
  927                 break;
  928         }
  929 }
  930 
  931 /*
  932  * Construct signal and wrap in C-Frame for link.
  933  */
  934 static int
  935 l2cap_send_signal(struct hci_link *link, uint8_t code, uint8_t ident,
  936                         uint16_t length, void *data)
  937 {
  938         struct mbuf *m;
  939         l2cap_hdr_t *hdr;
  940         l2cap_cmd_hdr_t *cmd;
  941 
  942 #ifdef DIAGNOSTIC
  943         if (link == NULL)
  944                 return ENETDOWN;
  945 
  946         if (sizeof(l2cap_cmd_hdr_t) + length > link->hl_mtu)
  947                 printf("(%s) exceeding L2CAP Signal MTU for link!\n",
  948                     device_xname(link->hl_unit->hci_dev));
  949 #endif
  950 
  951         m = m_gethdr(M_DONTWAIT, MT_DATA);
  952         if (m == NULL)
  953                 return ENOMEM;
  954 
  955         hdr = mtod(m, l2cap_hdr_t *);
  956         cmd = (l2cap_cmd_hdr_t *)(hdr + 1);
  957 
  958         m->m_len = m->m_pkthdr.len = MHLEN;
  959 
  960         /* Command Data */
  961         if (length > 0)
  962                 m_copyback(m, sizeof(*hdr) + sizeof(*cmd), length, data);
  963 
  964         /* Command Header */
  965         cmd->code = code;
  966         cmd->ident = ident;
  967         cmd->length = htole16(length);
  968         length += sizeof(*cmd);
  969 
  970         /* C-Frame Header */
  971         hdr->length = htole16(length);
  972         hdr->dcid = htole16(L2CAP_SIGNAL_CID);
  973         length += sizeof(*hdr);
  974 
  975         if (m->m_pkthdr.len != MAX(MHLEN, length)) {
  976                 m_freem(m);
  977                 return ENOMEM;
  978         }
  979 
  980         m->m_pkthdr.len = length;
  981         m->m_len = MIN(length, MHLEN);
  982 
  983         DPRINTFN(2, "(%s) code %d, ident %d, len %d\n",
  984                 device_xname(link->hl_unit->hci_dev), code, ident, length);
  985 
  986         return hci_acl_send(m, link, NULL);
  987 }
  988 
  989 /*
  990  * Send Command Reject packet.
  991  */
  992 static int
  993 l2cap_send_command_rej(struct hci_link *link, uint8_t ident,
  994                         uint16_t reason, ...)
  995 {
  996         l2cap_cmd_rej_cp cp;
  997         int len = 0;
  998         va_list ap;
  999 
 1000         va_start(ap, reason);
 1001 
 1002         cp.reason = htole16(reason);
 1003 
 1004         switch (reason) {
 1005         case L2CAP_REJ_NOT_UNDERSTOOD:
 1006                 len = 2;
 1007                 break;
 1008 
 1009         case L2CAP_REJ_MTU_EXCEEDED:
 1010                 len = 4;
 1011                 cp.data[0] = va_arg(ap, int);           /* SigMTU */
 1012                 cp.data[0] = htole16(cp.data[0]);
 1013                 break;
 1014 
 1015         case L2CAP_REJ_INVALID_CID:
 1016                 len = 6;
 1017                 cp.data[0] = va_arg(ap, int);           /* dcid */
 1018                 cp.data[0] = htole16(cp.data[0]);
 1019                 cp.data[1] = va_arg(ap, int);           /* scid */
 1020                 cp.data[1] = htole16(cp.data[1]);
 1021                 break;
 1022 
 1023         default:
 1024                 UNKNOWN(reason);
 1025                 return EINVAL;
 1026         }
 1027 
 1028         va_end(ap);
 1029 
 1030         return l2cap_send_signal(link, L2CAP_COMMAND_REJ, ident, len, &cp);
 1031 }
 1032 
 1033 /*
 1034  * Send Connect Request
 1035  */
 1036 int
 1037 l2cap_send_connect_req(struct l2cap_channel *chan)
 1038 {
 1039         l2cap_con_req_cp cp;
 1040         int err;
 1041 
 1042         err = l2cap_request_alloc(chan, L2CAP_CONNECT_REQ);
 1043         if (err)
 1044                 return err;
 1045 
 1046         cp.psm = htole16(chan->lc_raddr.bt_psm);
 1047         cp.scid = htole16(chan->lc_lcid);
 1048 
 1049         return l2cap_send_signal(chan->lc_link, L2CAP_CONNECT_REQ,
 1050                                 chan->lc_link->hl_lastid, sizeof(cp), &cp);
 1051 }
 1052 
 1053 /*
 1054  * Send Config Request
 1055  *
 1056  * For outgoing config request, we only put options in the packet if they
 1057  * differ from the default and would have to be actioned. We dont support
 1058  * enough option types to make overflowing SigMTU an issue so it can all
 1059  * go in one packet.
 1060  */
 1061 int
 1062 l2cap_send_config_req(struct l2cap_channel *chan)
 1063 {
 1064         l2cap_cfg_req_cp *cp;
 1065         l2cap_cfg_opt_t *opt;
 1066         l2cap_cfg_opt_val_t *val;
 1067         uint8_t *next, buf[L2CAP_MTU_MINIMUM];
 1068         int err;
 1069 
 1070         err = l2cap_request_alloc(chan, L2CAP_CONFIG_REQ);
 1071         if (err)
 1072                 return err;
 1073 
 1074         /* Config Header (4 octets) */
 1075         cp = (l2cap_cfg_req_cp *)buf;
 1076         cp->dcid = htole16(chan->lc_rcid);
 1077         cp->flags = 0;  /* "No Continuation" */
 1078 
 1079         next = buf + sizeof(l2cap_cfg_req_cp);
 1080 
 1081         /* Incoming MTU (4 octets) */
 1082         if (chan->lc_imtu != L2CAP_MTU_DEFAULT) {
 1083                 opt = (l2cap_cfg_opt_t *)next;
 1084                 opt->type = L2CAP_OPT_MTU;
 1085                 opt->length = L2CAP_OPT_MTU_SIZE;
 1086 
 1087                 val = (l2cap_cfg_opt_val_t *)(opt + 1);
 1088                 val->mtu = htole16(chan->lc_imtu);
 1089 
 1090                 next += sizeof(l2cap_cfg_opt_t) + L2CAP_OPT_MTU_SIZE;
 1091         }
 1092 
 1093         /* Flush Timeout (4 octets) */
 1094         if (chan->lc_flush != L2CAP_FLUSH_TIMO_DEFAULT) {
 1095                 opt = (l2cap_cfg_opt_t *)next;
 1096                 opt->type = L2CAP_OPT_FLUSH_TIMO;
 1097                 opt->length = L2CAP_OPT_FLUSH_TIMO_SIZE;
 1098 
 1099                 val = (l2cap_cfg_opt_val_t *)(opt + 1);
 1100                 val->flush_timo = htole16(chan->lc_flush);
 1101 
 1102                 next += sizeof(l2cap_cfg_opt_t) + L2CAP_OPT_FLUSH_TIMO_SIZE;
 1103         }
 1104 
 1105         /* Outgoing QoS Flow (24 octets) */
 1106         /* Retransmission & Flow Control (11 octets) */
 1107         /*
 1108          * From here we need to start paying attention to SigMTU as we have
 1109          * possibly overflowed the minimum supported..
 1110          */
 1111 
 1112         return l2cap_send_signal(chan->lc_link, L2CAP_CONFIG_REQ,
 1113                                     chan->lc_link->hl_lastid, (int)(next - buf), buf);
 1114 }
 1115 
 1116 /*
 1117  * Send Disconnect Request
 1118  */
 1119 int
 1120 l2cap_send_disconnect_req(struct l2cap_channel *chan)
 1121 {
 1122         l2cap_discon_req_cp cp;
 1123         int err;
 1124 
 1125         err = l2cap_request_alloc(chan, L2CAP_DISCONNECT_REQ);
 1126         if (err)
 1127                 return err;
 1128 
 1129         cp.dcid = htole16(chan->lc_rcid);
 1130         cp.scid = htole16(chan->lc_lcid);
 1131 
 1132         return l2cap_send_signal(chan->lc_link, L2CAP_DISCONNECT_REQ,
 1133                                     chan->lc_link->hl_lastid, sizeof(cp), &cp);
 1134 }
 1135 
 1136 /*
 1137  * Send Connect Response
 1138  */
 1139 int
 1140 l2cap_send_connect_rsp(struct hci_link *link, uint8_t ident, uint16_t dcid,
 1141     uint16_t scid, uint16_t result)
 1142 {
 1143         l2cap_con_rsp_cp cp;
 1144 
 1145         memset(&cp, 0, sizeof(cp));
 1146         cp.dcid = htole16(dcid);
 1147         cp.scid = htole16(scid);
 1148         cp.result = htole16(result);
 1149 
 1150         return l2cap_send_signal(link, L2CAP_CONNECT_RSP, ident, sizeof(cp), &cp);
 1151 }

Cache object: 0d42f48c7067b303e8bfb9a1bd504a5a


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