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

Cache object: a3502c600df1a68841d54cc3f3a84039


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