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/netgraph/bluetooth/socket/ng_btsocket_l2cap.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 /*
    2  * ng_btsocket_l2cap.c
    3  */
    4 
    5 /*-
    6  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    7  *
    8  * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $Id: ng_btsocket_l2cap.c,v 1.16 2003/09/14 23:29:06 max Exp $
   33  * $FreeBSD$
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/bitstring.h>
   39 #include <sys/domain.h>
   40 #include <sys/endian.h>
   41 #include <sys/errno.h>
   42 #include <sys/filedesc.h>
   43 #include <sys/ioccom.h>
   44 #include <sys/kernel.h>
   45 #include <sys/lock.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/mutex.h>
   49 #include <sys/protosw.h>
   50 #include <sys/queue.h>
   51 #include <sys/socket.h>
   52 #include <sys/socketvar.h>
   53 #include <sys/sysctl.h>
   54 #include <sys/taskqueue.h>
   55 
   56 #include <net/vnet.h>
   57 
   58 #include <netgraph/ng_message.h>
   59 #include <netgraph/netgraph.h>
   60 #include <netgraph/bluetooth/include/ng_bluetooth.h>
   61 #include <netgraph/bluetooth/include/ng_hci.h>
   62 #include <netgraph/bluetooth/include/ng_l2cap.h>
   63 #include <netgraph/bluetooth/include/ng_btsocket.h>
   64 #include <netgraph/bluetooth/include/ng_btsocket_l2cap.h>
   65 
   66 /* MALLOC define */
   67 #ifdef NG_SEPARATE_MALLOC
   68 static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_L2CAP, "netgraph_btsocks_l2cap",
   69                 "Netgraph Bluetooth L2CAP sockets");
   70 #else
   71 #define M_NETGRAPH_BTSOCKET_L2CAP M_NETGRAPH
   72 #endif /* NG_SEPARATE_MALLOC */
   73 
   74 /* Netgraph node methods */
   75 static ng_constructor_t ng_btsocket_l2cap_node_constructor;
   76 static ng_rcvmsg_t      ng_btsocket_l2cap_node_rcvmsg;
   77 static ng_shutdown_t    ng_btsocket_l2cap_node_shutdown;
   78 static ng_newhook_t     ng_btsocket_l2cap_node_newhook;
   79 static ng_connect_t     ng_btsocket_l2cap_node_connect;
   80 static ng_rcvdata_t     ng_btsocket_l2cap_node_rcvdata;
   81 static ng_disconnect_t  ng_btsocket_l2cap_node_disconnect;
   82 
   83 static void             ng_btsocket_l2cap_input   (void *, int);
   84 static void             ng_btsocket_l2cap_rtclean (void *, int);
   85 
   86 /* Netgraph type descriptor */
   87 static struct ng_type   typestruct = {
   88         .version =      NG_ABI_VERSION,
   89         .name =         NG_BTSOCKET_L2CAP_NODE_TYPE,
   90         .constructor =  ng_btsocket_l2cap_node_constructor,
   91         .rcvmsg =       ng_btsocket_l2cap_node_rcvmsg,
   92         .shutdown =     ng_btsocket_l2cap_node_shutdown,
   93         .newhook =      ng_btsocket_l2cap_node_newhook,
   94         .connect =      ng_btsocket_l2cap_node_connect,
   95         .rcvdata =      ng_btsocket_l2cap_node_rcvdata,
   96         .disconnect =   ng_btsocket_l2cap_node_disconnect,
   97 };
   98 
   99 /* Globals */
  100 extern int                                      ifqmaxlen;
  101 static u_int32_t                                ng_btsocket_l2cap_debug_level;
  102 static node_p                                   ng_btsocket_l2cap_node;
  103 static struct ng_bt_itemq                       ng_btsocket_l2cap_queue;
  104 static struct mtx                               ng_btsocket_l2cap_queue_mtx;
  105 static struct task                              ng_btsocket_l2cap_queue_task;
  106 static LIST_HEAD(, ng_btsocket_l2cap_pcb)       ng_btsocket_l2cap_sockets;
  107 static struct mtx                               ng_btsocket_l2cap_sockets_mtx;
  108 static LIST_HEAD(, ng_btsocket_l2cap_rtentry)   ng_btsocket_l2cap_rt;
  109 static struct mtx                               ng_btsocket_l2cap_rt_mtx;
  110 static struct task                              ng_btsocket_l2cap_rt_task;
  111 static struct timeval                           ng_btsocket_l2cap_lasttime;
  112 static int                                      ng_btsocket_l2cap_curpps;
  113 
  114 /* Sysctl tree */
  115 SYSCTL_DECL(_net_bluetooth_l2cap_sockets);
  116 static SYSCTL_NODE(_net_bluetooth_l2cap_sockets, OID_AUTO, seq,
  117     CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
  118     "Bluetooth SEQPACKET L2CAP sockets family");
  119 SYSCTL_UINT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, debug_level,
  120         CTLFLAG_RW,
  121         &ng_btsocket_l2cap_debug_level, NG_BTSOCKET_WARN_LEVEL,
  122         "Bluetooth SEQPACKET L2CAP sockets debug level");
  123 SYSCTL_UINT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, queue_len,
  124         CTLFLAG_RD,
  125         &ng_btsocket_l2cap_queue.len, 0,
  126         "Bluetooth SEQPACKET L2CAP sockets input queue length");
  127 SYSCTL_UINT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, queue_maxlen,
  128         CTLFLAG_RD,
  129         &ng_btsocket_l2cap_queue.maxlen, 0,
  130         "Bluetooth SEQPACKET L2CAP sockets input queue max. length");
  131 SYSCTL_UINT(_net_bluetooth_l2cap_sockets_seq, OID_AUTO, queue_drops,
  132         CTLFLAG_RD,
  133         &ng_btsocket_l2cap_queue.drops, 0,
  134         "Bluetooth SEQPACKET L2CAP sockets input queue drops");
  135 
  136 /* Debug */
  137 #define NG_BTSOCKET_L2CAP_INFO \
  138         if (ng_btsocket_l2cap_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
  139             ppsratecheck(&ng_btsocket_l2cap_lasttime, &ng_btsocket_l2cap_curpps, 1)) \
  140                 printf
  141 
  142 #define NG_BTSOCKET_L2CAP_WARN \
  143         if (ng_btsocket_l2cap_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
  144             ppsratecheck(&ng_btsocket_l2cap_lasttime, &ng_btsocket_l2cap_curpps, 1)) \
  145                 printf
  146 
  147 #define NG_BTSOCKET_L2CAP_ERR \
  148         if (ng_btsocket_l2cap_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
  149             ppsratecheck(&ng_btsocket_l2cap_lasttime, &ng_btsocket_l2cap_curpps, 1)) \
  150                 printf
  151 
  152 #define NG_BTSOCKET_L2CAP_ALERT \
  153         if (ng_btsocket_l2cap_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
  154             ppsratecheck(&ng_btsocket_l2cap_lasttime, &ng_btsocket_l2cap_curpps, 1)) \
  155                 printf
  156 
  157 /* 
  158  * Netgraph message processing routines
  159  */
  160 
  161 static int ng_btsocket_l2cap_process_l2ca_con_req_rsp
  162         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  163 static int ng_btsocket_l2cap_process_l2ca_con_rsp_rsp
  164         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  165 static int ng_btsocket_l2cap_process_l2ca_con_ind
  166         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  167 
  168 static int ng_btsocket_l2cap_process_l2ca_cfg_req_rsp
  169         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  170 static int ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp
  171         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  172 static int ng_btsocket_l2cap_process_l2ca_cfg_ind
  173         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  174 
  175 static int ng_btsocket_l2cap_process_l2ca_discon_rsp
  176         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  177 static int ng_btsocket_l2cap_process_l2ca_discon_ind
  178         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  179 
  180 static int ng_btsocket_l2cap_process_l2ca_write_rsp
  181         (struct ng_mesg *, ng_btsocket_l2cap_rtentry_p);
  182 
  183 /*
  184  * Send L2CA_xxx messages to the lower layer
  185  */
  186 
  187 static int  ng_btsocket_l2cap_send_l2ca_con_req
  188         (ng_btsocket_l2cap_pcb_p);
  189 static int  ng_btsocket_l2cap_send_l2ca_con_rsp_req
  190         (u_int32_t, ng_btsocket_l2cap_rtentry_p, bdaddr_p, int, int, int, int);
  191 static int  ng_btsocket_l2cap_send_l2ca_cfg_req
  192         (ng_btsocket_l2cap_pcb_p);
  193 static int  ng_btsocket_l2cap_send_l2ca_cfg_rsp
  194         (ng_btsocket_l2cap_pcb_p);
  195 static int  ng_btsocket_l2cap_send_l2ca_discon_req
  196         (u_int32_t, ng_btsocket_l2cap_pcb_p);
  197 
  198 static int ng_btsocket_l2cap_send2
  199         (ng_btsocket_l2cap_pcb_p);
  200 
  201 /* 
  202  * Timeout processing routines
  203  */
  204 
  205 static void ng_btsocket_l2cap_timeout         (ng_btsocket_l2cap_pcb_p);
  206 static void ng_btsocket_l2cap_untimeout       (ng_btsocket_l2cap_pcb_p);
  207 static void ng_btsocket_l2cap_process_timeout (void *);
  208 
  209 /* 
  210  * Other stuff 
  211  */
  212 
  213 static ng_btsocket_l2cap_pcb_p     ng_btsocket_l2cap_pcb_by_addr(bdaddr_p, int);
  214 static ng_btsocket_l2cap_pcb_p     ng_btsocket_l2cap_pcb_by_token(u_int32_t);
  215 static ng_btsocket_l2cap_pcb_p     ng_btsocket_l2cap_pcb_by_cid (bdaddr_p, int,int);
  216 static int                         ng_btsocket_l2cap_result2errno(int);
  217 
  218 static int ng_btsock_l2cap_addrtype_to_linktype(int addrtype);
  219 
  220 #define ng_btsocket_l2cap_wakeup_input_task() \
  221         taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_queue_task)
  222 
  223 #define ng_btsocket_l2cap_wakeup_route_task() \
  224         taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_rt_task)
  225 
  226 int ng_btsock_l2cap_addrtype_to_linktype(int addrtype)
  227 {
  228         switch(addrtype){
  229         case BDADDR_LE_PUBLIC:
  230                 return NG_HCI_LINK_LE_PUBLIC;
  231         case BDADDR_LE_RANDOM:
  232                 return NG_HCI_LINK_LE_RANDOM;
  233         default:
  234                 return NG_HCI_LINK_ACL;
  235         }
  236 }
  237 
  238 /*****************************************************************************
  239  *****************************************************************************
  240  **                        Netgraph node interface
  241  *****************************************************************************
  242  *****************************************************************************/
  243 
  244 /*
  245  * Netgraph node constructor. Do not allow to create node of this type.
  246  */
  247 
  248 static int
  249 ng_btsocket_l2cap_node_constructor(node_p node)
  250 {
  251         return (EINVAL);
  252 } /* ng_btsocket_l2cap_node_constructor */
  253 
  254 /*
  255  * Do local shutdown processing. Let old node go and create new fresh one.
  256  */
  257 
  258 static int
  259 ng_btsocket_l2cap_node_shutdown(node_p node)
  260 {
  261         int     error = 0;
  262 
  263         NG_NODE_UNREF(node);
  264 
  265         /* Create new node */
  266         error = ng_make_node_common(&typestruct, &ng_btsocket_l2cap_node);
  267         if (error != 0) {
  268                 NG_BTSOCKET_L2CAP_ALERT(
  269 "%s: Could not create Netgraph node, error=%d\n", __func__, error);
  270 
  271                 ng_btsocket_l2cap_node = NULL;
  272 
  273                 return (error);
  274         }
  275 
  276         error = ng_name_node(ng_btsocket_l2cap_node,
  277                                 NG_BTSOCKET_L2CAP_NODE_TYPE);
  278         if (error != 0) {
  279                 NG_BTSOCKET_L2CAP_ALERT(
  280 "%s: Could not name Netgraph node, error=%d\n", __func__, error);
  281 
  282                 NG_NODE_UNREF(ng_btsocket_l2cap_node);
  283                 ng_btsocket_l2cap_node = NULL;
  284 
  285                 return (error);
  286         }
  287                 
  288         return (0);
  289 } /* ng_btsocket_l2cap_node_shutdown */
  290 
  291 /*
  292  * We allow any hook to be connected to the node.
  293  */
  294 
  295 static int
  296 ng_btsocket_l2cap_node_newhook(node_p node, hook_p hook, char const *name)
  297 {
  298         return (0);
  299 } /* ng_btsocket_l2cap_node_newhook */
  300 
  301 /* 
  302  * Just say "YEP, that's OK by me!"
  303  */
  304 
  305 static int
  306 ng_btsocket_l2cap_node_connect(hook_p hook)
  307 {
  308         NG_HOOK_SET_PRIVATE(hook, NULL);
  309         NG_HOOK_REF(hook); /* Keep extra reference to the hook */
  310 
  311 #if 0
  312         NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
  313         NG_HOOK_FORCE_QUEUE(hook);
  314 #endif
  315 
  316         return (0);
  317 } /* ng_btsocket_l2cap_node_connect */
  318 
  319 /*
  320  * Hook disconnection. Schedule route cleanup task
  321  */
  322 
  323 static int
  324 ng_btsocket_l2cap_node_disconnect(hook_p hook)
  325 {
  326         /*
  327          * If hook has private information than we must have this hook in
  328          * the routing table and must schedule cleaning for the routing table.
  329          * Otherwise hook was connected but we never got "hook_info" message,
  330          * so we have never added this hook to the routing table and it save
  331          * to just delete it.
  332          */
  333 
  334         if (NG_HOOK_PRIVATE(hook) != NULL)
  335                 return (ng_btsocket_l2cap_wakeup_route_task());
  336 
  337         NG_HOOK_UNREF(hook); /* Remove extra reference */
  338 
  339         return (0);
  340 } /* ng_btsocket_l2cap_node_disconnect */
  341 
  342 /*
  343  * Process incoming messages 
  344  */
  345 
  346 static int
  347 ng_btsocket_l2cap_node_rcvmsg(node_p node, item_p item, hook_p hook)
  348 {
  349         struct ng_mesg  *msg = NGI_MSG(item); /* item still has message */
  350         int              error = 0;
  351 
  352         if (msg != NULL && msg->header.typecookie == NGM_L2CAP_COOKIE) {
  353                 mtx_lock(&ng_btsocket_l2cap_queue_mtx);
  354                 if (NG_BT_ITEMQ_FULL(&ng_btsocket_l2cap_queue)) {
  355                         NG_BTSOCKET_L2CAP_ERR(
  356 "%s: Input queue is full (msg)\n", __func__);
  357 
  358                         NG_BT_ITEMQ_DROP(&ng_btsocket_l2cap_queue);
  359                         NG_FREE_ITEM(item);
  360                         error = ENOBUFS;
  361                 } else {
  362                         if (hook != NULL) {
  363                                 NG_HOOK_REF(hook);
  364                                 NGI_SET_HOOK(item, hook);
  365                         }
  366 
  367                         NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_l2cap_queue, item);
  368                         error = ng_btsocket_l2cap_wakeup_input_task();
  369                 }
  370                 mtx_unlock(&ng_btsocket_l2cap_queue_mtx);
  371         } else {
  372                 NG_FREE_ITEM(item);
  373                 error = EINVAL;
  374         }
  375 
  376         return (error);
  377 } /* ng_btsocket_l2cap_node_rcvmsg */
  378 
  379 /*
  380  * Receive data on a hook
  381  */
  382 
  383 static int
  384 ng_btsocket_l2cap_node_rcvdata(hook_p hook, item_p item)
  385 {
  386         int     error = 0;
  387 
  388         mtx_lock(&ng_btsocket_l2cap_queue_mtx);
  389         if (NG_BT_ITEMQ_FULL(&ng_btsocket_l2cap_queue)) {
  390                 NG_BTSOCKET_L2CAP_ERR(
  391 "%s: Input queue is full (data)\n", __func__);
  392 
  393                 NG_BT_ITEMQ_DROP(&ng_btsocket_l2cap_queue);
  394                 NG_FREE_ITEM(item);
  395                 error = ENOBUFS;
  396         } else {
  397                 NG_HOOK_REF(hook);
  398                 NGI_SET_HOOK(item, hook);
  399 
  400                 NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_l2cap_queue, item);
  401                 error = ng_btsocket_l2cap_wakeup_input_task();
  402         }
  403         mtx_unlock(&ng_btsocket_l2cap_queue_mtx);
  404 
  405         return (error);
  406 } /* ng_btsocket_l2cap_node_rcvdata */
  407 
  408 /*
  409  * Process L2CA_Connect respose. Socket layer must have initiated connection,
  410  * so we have to have a socket associated with message token.
  411  */
  412 
  413 static int
  414 ng_btsocket_l2cap_process_l2ca_con_req_rsp(struct ng_mesg *msg,
  415                 ng_btsocket_l2cap_rtentry_p rt)
  416 {
  417         ng_l2cap_l2ca_con_op    *op = NULL;
  418         ng_btsocket_l2cap_pcb_t *pcb = NULL;
  419         int                      error = 0;
  420 
  421         if (msg->header.arglen != sizeof(*op))
  422                 return (EMSGSIZE);
  423 
  424         op = (ng_l2cap_l2ca_con_op *)(msg->data);
  425 
  426         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
  427 
  428         /* Look for the socket with the token */
  429         pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
  430         if (pcb == NULL) {
  431                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  432                 return (ENOENT);
  433         }
  434 
  435         mtx_lock(&pcb->pcb_mtx);
  436 
  437         NG_BTSOCKET_L2CAP_INFO(
  438 "%s: Got L2CA_Connect response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
  439 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, status=%d, " \
  440 "state=%d\n",   __func__, msg->header.token,
  441                 pcb->src.b[5], pcb->src.b[4], pcb->src.b[3],
  442                 pcb->src.b[2], pcb->src.b[1], pcb->src.b[0],
  443                 pcb->dst.b[5], pcb->dst.b[4], pcb->dst.b[3],
  444                 pcb->dst.b[2], pcb->dst.b[1], pcb->dst.b[0],
  445                 pcb->psm, op->lcid, op->result, op->status,
  446                 pcb->state);
  447 
  448         if (pcb->state != NG_BTSOCKET_L2CAP_CONNECTING) {
  449                 mtx_unlock(&pcb->pcb_mtx);
  450                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  451 
  452                 return (ENOENT);
  453         }
  454 
  455         ng_btsocket_l2cap_untimeout(pcb);
  456 
  457         if (op->result == NG_L2CAP_PENDING) {
  458                 ng_btsocket_l2cap_timeout(pcb);
  459                 mtx_unlock(&pcb->pcb_mtx);
  460                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  461 
  462                 return (0);
  463         }
  464 
  465         if (op->result == NG_L2CAP_SUCCESS){
  466                 if((pcb->idtype == NG_L2CAP_L2CA_IDTYPE_ATT)||
  467                    (pcb->idtype == NG_L2CAP_L2CA_IDTYPE_SMP)){
  468                         pcb->encryption = op->encryption;                                       pcb->cid = op->lcid;    
  469                         if(pcb->need_encrypt && !(pcb->encryption)){
  470                                 ng_btsocket_l2cap_timeout(pcb);
  471                                 pcb->state = NG_BTSOCKET_L2CAP_W4_ENC_CHANGE;
  472                         }else{
  473                                 pcb->state = NG_BTSOCKET_L2CAP_OPEN;
  474                                 soisconnected(pcb->so);
  475                         }
  476                 }else{
  477                         /*
  478                          * Channel is now open, so update local channel ID and 
  479                          * start configuration process. Source and destination
  480                          * addresses as well as route must be already set.
  481                          */
  482                         
  483                         pcb->cid = op->lcid;
  484                         pcb->encryption = op->encryption;
  485                         error = ng_btsocket_l2cap_send_l2ca_cfg_req(pcb);
  486                         if (error != 0) {
  487                                 /* Send disconnect request with "zero" token */
  488                                 ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
  489                                 
  490                                 /* ... and close the socket */
  491                                 pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
  492                                 soisdisconnected(pcb->so);
  493                         } else {
  494                                 pcb->cfg_state = NG_BTSOCKET_L2CAP_CFG_IN_SENT;
  495                                 pcb->state = NG_BTSOCKET_L2CAP_CONFIGURING;
  496                                 
  497                                 ng_btsocket_l2cap_timeout(pcb);
  498                         }
  499                 }
  500         } else {
  501                 /*
  502                  * We have failed to open connection, so convert result
  503                  * code to "errno" code and disconnect the socket. Channel
  504                  * already has been closed.
  505                  */
  506 
  507                 pcb->so->so_error = ng_btsocket_l2cap_result2errno(op->result);
  508                 pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
  509                 soisdisconnected(pcb->so); 
  510         }
  511         mtx_unlock(&pcb->pcb_mtx);
  512         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  513 
  514         return (error);
  515 } /* ng_btsocket_l2cap_process_l2ca_con_req_rsp */
  516 
  517 /*
  518  * Process L2CA_ConnectRsp response
  519  */
  520 
  521 static int
  522 ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(struct ng_mesg *msg,
  523                 ng_btsocket_l2cap_rtentry_p rt)
  524 {
  525         ng_l2cap_l2ca_con_rsp_op        *op = NULL;
  526         ng_btsocket_l2cap_pcb_t         *pcb = NULL;
  527 
  528         if (msg->header.arglen != sizeof(*op)) 
  529                 return (EMSGSIZE);
  530 
  531         op = (ng_l2cap_l2ca_con_rsp_op *)(msg->data);
  532 
  533         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
  534 
  535         /* Look for the socket with the token */
  536         pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
  537         if (pcb == NULL) {
  538                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  539                 return (ENOENT);
  540         }
  541 
  542         mtx_lock(&pcb->pcb_mtx);
  543 
  544         NG_BTSOCKET_L2CAP_INFO(
  545 "%s: Got L2CA_ConnectRsp response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
  546 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, state=%d\n",
  547                 __func__, msg->header.token,
  548                 pcb->src.b[5], pcb->src.b[4], pcb->src.b[3],
  549                 pcb->src.b[2], pcb->src.b[1], pcb->src.b[0],
  550                 pcb->dst.b[5], pcb->dst.b[4], pcb->dst.b[3],
  551                 pcb->dst.b[2], pcb->dst.b[1], pcb->dst.b[0],
  552                 pcb->psm, pcb->cid, op->result, pcb->state);
  553 
  554         if (pcb->state != NG_BTSOCKET_L2CAP_CONNECTING) {
  555                 mtx_unlock(&pcb->pcb_mtx);
  556                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  557 
  558                 return (ENOENT);
  559         }
  560 
  561         ng_btsocket_l2cap_untimeout(pcb);
  562 
  563         /* Check the result and disconnect the socket on failure */
  564         if (op->result != NG_L2CAP_SUCCESS) {
  565                 /* Close the socket - channel already closed */
  566                 pcb->so->so_error = ng_btsocket_l2cap_result2errno(op->result);
  567                 pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
  568                 soisdisconnected(pcb->so);
  569         } else {
  570                 /* Move to CONFIGURING state and wait for CONFIG_IND */
  571                 pcb->cfg_state = 0;
  572                 pcb->state = NG_BTSOCKET_L2CAP_CONFIGURING;
  573                 ng_btsocket_l2cap_timeout(pcb);
  574         }
  575 
  576         mtx_unlock(&pcb->pcb_mtx);
  577         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  578 
  579         return (0);
  580 } /* ng_btsocket_process_l2ca_con_rsp_rsp */
  581 
  582 /*
  583  * Process L2CA_Connect indicator. Find socket that listens on address 
  584  * and PSM. Find exact or closest match. Create new socket and initiate 
  585  * connection.
  586  */
  587 
  588 static int
  589 ng_btsocket_l2cap_process_l2ca_con_ind(struct ng_mesg *msg,
  590                 ng_btsocket_l2cap_rtentry_p rt)
  591 {
  592         ng_l2cap_l2ca_con_ind_ip        *ip = NULL;
  593         ng_btsocket_l2cap_pcb_t         *pcb = NULL, *pcb1 = NULL;
  594         int                              error = 0;
  595         u_int32_t                        token = 0;
  596         u_int16_t                        result = 0;
  597 
  598         if (msg->header.arglen != sizeof(*ip))
  599                 return (EMSGSIZE);
  600 
  601         ip = (ng_l2cap_l2ca_con_ind_ip *)(msg->data);
  602 
  603         NG_BTSOCKET_L2CAP_INFO(
  604 "%s: Got L2CA_Connect indicator, src bdaddr=%x:%x:%x:%x:%x:%x, " \
  605 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, ident=%d\n",
  606                 __func__,
  607                 rt->src.b[5], rt->src.b[4], rt->src.b[3],
  608                 rt->src.b[2], rt->src.b[1], rt->src.b[0],
  609                 ip->bdaddr.b[5], ip->bdaddr.b[4], ip->bdaddr.b[3],
  610                 ip->bdaddr.b[2], ip->bdaddr.b[1], ip->bdaddr.b[0],
  611                 ip->psm, ip->lcid, ip->ident);
  612 
  613         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
  614 
  615         pcb = ng_btsocket_l2cap_pcb_by_addr(&rt->src, ip->psm);
  616         if (pcb != NULL) {
  617                 struct socket *so1;
  618 
  619                 mtx_lock(&pcb->pcb_mtx);
  620 
  621                 CURVNET_SET(pcb->so->so_vnet);
  622                 so1 = sonewconn(pcb->so, 0);
  623                 CURVNET_RESTORE();
  624                 if (so1 == NULL) {
  625                         result = NG_L2CAP_NO_RESOURCES;
  626                         goto respond;
  627                 }
  628 
  629                 /*
  630                  * If we got here than we have created new socket. So complete 
  631                  * connection. If we we listening on specific address then copy 
  632                  * source address from listening socket, otherwise copy source 
  633                  * address from hook's routing information.
  634                  */
  635 
  636                 pcb1 = so2l2cap_pcb(so1);
  637                 KASSERT((pcb1 != NULL),
  638 ("%s: pcb1 == NULL\n", __func__));
  639 
  640                 mtx_lock(&pcb1->pcb_mtx);
  641 
  642                 if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(pcb->src)) != 0)
  643                         bcopy(&pcb->src, &pcb1->src, sizeof(pcb1->src));
  644                 else
  645                         bcopy(&rt->src, &pcb1->src, sizeof(pcb1->src));
  646 
  647                 pcb1->flags &= ~NG_BTSOCKET_L2CAP_CLIENT;
  648 
  649                 bcopy(&ip->bdaddr, &pcb1->dst, sizeof(pcb1->dst));
  650                 pcb1->psm = ip->psm;
  651                 pcb1->cid = ip->lcid;
  652                 pcb1->rt = rt;
  653 
  654                 /* Copy socket settings */
  655                 pcb1->imtu = pcb->imtu;
  656                 bcopy(&pcb->oflow, &pcb1->oflow, sizeof(pcb1->oflow));
  657                 pcb1->flush_timo = pcb->flush_timo;
  658 
  659                 token = pcb1->token;
  660         } else
  661                 /* Nobody listens on requested BDADDR/PSM */
  662                 result = NG_L2CAP_PSM_NOT_SUPPORTED;
  663 
  664 respond:
  665         error = ng_btsocket_l2cap_send_l2ca_con_rsp_req(token, rt,
  666                                                         &ip->bdaddr,
  667                                                         ip->ident, ip->lcid,
  668                                                         result,ip->linktype);
  669         if (pcb1 != NULL) {
  670                 if (error != 0) {
  671                         pcb1->so->so_error = error;
  672                         pcb1->state = NG_BTSOCKET_L2CAP_CLOSED;
  673                         soisdisconnected(pcb1->so);
  674                 } else {
  675                         pcb1->state = NG_BTSOCKET_L2CAP_CONNECTING;
  676                         soisconnecting(pcb1->so);
  677 
  678                         ng_btsocket_l2cap_timeout(pcb1);
  679                 }
  680 
  681                 mtx_unlock(&pcb1->pcb_mtx);
  682         }
  683 
  684         if (pcb != NULL)
  685                 mtx_unlock(&pcb->pcb_mtx);
  686 
  687         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  688 
  689         return (error);
  690 } /* ng_btsocket_l2cap_process_l2ca_con_ind */
  691 /*Encryption Change*/
  692 static int ng_btsocket_l2cap_process_l2ca_enc_change(struct ng_mesg *msg, ng_btsocket_l2cap_rtentry_p rt)
  693 {
  694         ng_l2cap_l2ca_enc_chg_op        *op = NULL;
  695         ng_btsocket_l2cap_pcb_t         *pcb = NULL;
  696 
  697         if (msg->header.arglen != sizeof(*op))
  698                 return (EMSGSIZE);
  699 
  700         op = (ng_l2cap_l2ca_enc_chg_op *)(msg->data);
  701 
  702         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
  703 
  704         pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, op->lcid,
  705                                            op->idtype);
  706         if (pcb == NULL) {
  707                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  708                 return (ENOENT);
  709         }
  710 
  711         mtx_lock(&pcb->pcb_mtx);
  712         pcb->encryption = op->result;
  713 
  714         if(pcb->need_encrypt){
  715                 ng_btsocket_l2cap_untimeout(pcb);               
  716                 if(pcb->state != NG_BTSOCKET_L2CAP_W4_ENC_CHANGE){
  717                         NG_BTSOCKET_L2CAP_WARN("%s: Invalid pcb status %d",
  718                                                __func__, pcb->state);
  719                 }else if(pcb->encryption){
  720                         pcb->state = NG_BTSOCKET_L2CAP_OPEN;
  721                         soisconnected(pcb->so);
  722                 }else{
  723                         pcb->so->so_error = EPERM;
  724                         ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
  725                         pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
  726                         soisdisconnected(pcb->so);
  727                 }
  728         }
  729         mtx_unlock(&pcb->pcb_mtx);
  730         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  731 
  732         return 0;
  733 }
  734 /*
  735  * Process L2CA_Config response
  736  */
  737 
  738 static int
  739 ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(struct ng_mesg *msg,
  740                 ng_btsocket_l2cap_rtentry_p rt)
  741 {
  742         ng_l2cap_l2ca_cfg_op    *op = NULL;
  743         ng_btsocket_l2cap_pcb_p  pcb = NULL;
  744 
  745         if (msg->header.arglen != sizeof(*op))
  746                 return (EMSGSIZE);
  747 
  748         op = (ng_l2cap_l2ca_cfg_op *)(msg->data);
  749 
  750         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
  751 
  752         /* 
  753          * Socket must have issued a Configure request, so we must have a 
  754          * socket that wants to be configured. Use Netgraph message token 
  755          * to find it
  756          */
  757 
  758         pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
  759         if (pcb == NULL) {
  760                 /*
  761                  * XXX FIXME what to do here? We could not find a
  762                  * socket with requested token. We even can not send
  763                  * Disconnect, because we do not know channel ID
  764                  */
  765 
  766                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  767                 return (ENOENT);
  768         }
  769 
  770         mtx_lock(&pcb->pcb_mtx);
  771 
  772         NG_BTSOCKET_L2CAP_INFO(
  773 "%s: Got L2CA_Config response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
  774 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, state=%d, " \
  775 "cfg_state=%x\n",
  776                 __func__, msg->header.token,
  777                 pcb->src.b[5], pcb->src.b[4], pcb->src.b[3],
  778                 pcb->src.b[2], pcb->src.b[1], pcb->src.b[0],
  779                 pcb->dst.b[5], pcb->dst.b[4], pcb->dst.b[3],
  780                 pcb->dst.b[2], pcb->dst.b[1], pcb->dst.b[0],
  781                 pcb->psm, pcb->cid, op->result, pcb->state, pcb->cfg_state);
  782 
  783         if (pcb->state != NG_BTSOCKET_L2CAP_CONFIGURING) {
  784                 mtx_unlock(&pcb->pcb_mtx);
  785                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  786 
  787                 return (ENOENT);
  788         }
  789 
  790         if (op->result == NG_L2CAP_SUCCESS) {
  791                 /*
  792                  * XXX FIXME Actually set flush and link timeout.
  793                  * Set QoS here if required. Resolve conficts (flush_timo). 
  794                  * Save incoming MTU (peer's outgoing MTU) and outgoing flow 
  795                  * spec.
  796                  */
  797 
  798                 pcb->imtu = op->imtu;
  799                 bcopy(&op->oflow, &pcb->oflow, sizeof(pcb->oflow));
  800                 pcb->flush_timo = op->flush_timo;
  801 
  802                 /*
  803                  * We have configured incoming side, so record it and check 
  804                  * if configuration is complete. If complete then mark socket
  805                  * as connected, otherwise wait for the peer.
  806                  */
  807 
  808                 pcb->cfg_state &= ~NG_BTSOCKET_L2CAP_CFG_IN_SENT;
  809                 pcb->cfg_state |= NG_BTSOCKET_L2CAP_CFG_IN;
  810 
  811                 if (pcb->cfg_state == NG_BTSOCKET_L2CAP_CFG_BOTH) {
  812                         /* Configuration complete - mark socket as open */
  813                         ng_btsocket_l2cap_untimeout(pcb);
  814                         pcb->state = NG_BTSOCKET_L2CAP_OPEN;
  815                         soisconnected(pcb->so); 
  816                 } 
  817         } else {
  818                 /*
  819                  * Something went wrong. Could be unacceptable parameters,
  820                  * reject or unknown option. That's too bad, but we will
  821                  * not negotiate. Send Disconnect and close the channel.
  822                  */
  823 
  824                 ng_btsocket_l2cap_untimeout(pcb);
  825 
  826                 switch (op->result) {
  827                 case NG_L2CAP_UNACCEPTABLE_PARAMS:
  828                 case NG_L2CAP_UNKNOWN_OPTION:
  829                         pcb->so->so_error = EINVAL;
  830                         break;
  831 
  832                 default:
  833                         pcb->so->so_error = ECONNRESET;
  834                         break;
  835                 }
  836 
  837                 /* Send disconnect with "zero" token */
  838                 ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
  839 
  840                 /* ... and close the socket */
  841                 pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
  842                 soisdisconnected(pcb->so);
  843         }
  844 
  845         mtx_unlock(&pcb->pcb_mtx);
  846         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  847 
  848         return (0);
  849 } /* ng_btsocket_l2cap_process_l2ca_cfg_req_rsp */
  850 
  851 /*
  852  * Process L2CA_ConfigRsp response
  853  */
  854 
  855 static int
  856 ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(struct ng_mesg *msg,
  857                 ng_btsocket_l2cap_rtentry_p rt)
  858 {
  859         ng_l2cap_l2ca_cfg_rsp_op        *op = NULL;
  860         ng_btsocket_l2cap_pcb_t         *pcb = NULL;
  861         int                              error = 0;
  862 
  863         if (msg->header.arglen != sizeof(*op))
  864                 return (EMSGSIZE);
  865 
  866         op = (ng_l2cap_l2ca_cfg_rsp_op *)(msg->data);
  867 
  868         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
  869 
  870         /* Look for the socket with the token */
  871         pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
  872         if (pcb == NULL) {
  873                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  874                 return (ENOENT);
  875         }
  876 
  877         mtx_lock(&pcb->pcb_mtx);
  878 
  879         NG_BTSOCKET_L2CAP_INFO(
  880 "%s: Got L2CA_ConfigRsp response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
  881 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, state=%d, " \
  882 "cfg_state=%x\n",
  883                 __func__, msg->header.token,
  884                 pcb->src.b[5], pcb->src.b[4], pcb->src.b[3],
  885                 pcb->src.b[2], pcb->src.b[1], pcb->src.b[0],
  886                 pcb->dst.b[5], pcb->dst.b[4], pcb->dst.b[3],
  887                 pcb->dst.b[2], pcb->dst.b[1], pcb->dst.b[0],
  888                 pcb->psm, pcb->cid, op->result, pcb->state, pcb->cfg_state);
  889 
  890         if (pcb->state != NG_BTSOCKET_L2CAP_CONFIGURING) {
  891                 mtx_unlock(&pcb->pcb_mtx);
  892                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  893 
  894                 return (ENOENT);
  895         }
  896 
  897         /* Check the result and disconnect socket of failure */
  898         if (op->result != NG_L2CAP_SUCCESS)
  899                 goto disconnect;
  900 
  901         /*
  902          * Now we done with remote side configuration. Configure local 
  903          * side if we have not done it yet.
  904          */
  905 
  906         pcb->cfg_state &= ~NG_BTSOCKET_L2CAP_CFG_OUT_SENT;
  907         pcb->cfg_state |= NG_BTSOCKET_L2CAP_CFG_OUT;
  908 
  909         if (pcb->cfg_state == NG_BTSOCKET_L2CAP_CFG_BOTH) {
  910                 /* Configuration complete - mask socket as open */
  911                 ng_btsocket_l2cap_untimeout(pcb);
  912                 pcb->state = NG_BTSOCKET_L2CAP_OPEN;
  913                 soisconnected(pcb->so);
  914         } else {
  915                 if (!(pcb->cfg_state & NG_BTSOCKET_L2CAP_CFG_IN_SENT)) {
  916                         /* Send L2CA_Config request - incoming path */
  917                         error = ng_btsocket_l2cap_send_l2ca_cfg_req(pcb);
  918                         if (error != 0)
  919                                 goto disconnect;
  920 
  921                         pcb->cfg_state |= NG_BTSOCKET_L2CAP_CFG_IN_SENT;
  922                 }
  923         }
  924 
  925         mtx_unlock(&pcb->pcb_mtx);
  926         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  927 
  928         return (error);
  929 
  930 disconnect:
  931         ng_btsocket_l2cap_untimeout(pcb);
  932 
  933         /* Send disconnect with "zero" token */
  934         ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
  935 
  936         /* ... and close the socket */
  937         pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
  938         soisdisconnected(pcb->so);
  939 
  940         mtx_unlock(&pcb->pcb_mtx);
  941         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  942 
  943         return (error);
  944 } /* ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp */
  945 
  946 /*
  947  * Process L2CA_Config indicator
  948  */
  949 
  950 static int
  951 ng_btsocket_l2cap_process_l2ca_cfg_ind(struct ng_mesg *msg,
  952                 ng_btsocket_l2cap_rtentry_p rt)
  953 {
  954         ng_l2cap_l2ca_cfg_ind_ip        *ip = NULL;
  955         ng_btsocket_l2cap_pcb_t         *pcb = NULL;
  956         int                              error = 0;
  957 
  958         if (msg->header.arglen != sizeof(*ip))
  959                 return (EMSGSIZE);
  960 
  961         ip = (ng_l2cap_l2ca_cfg_ind_ip *)(msg->data);
  962 
  963         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
  964 
  965         /* Check for the open socket that has given channel ID */
  966         pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, ip->lcid,
  967                                            NG_L2CAP_L2CA_IDTYPE_BREDR);
  968         if (pcb == NULL) {
  969                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  970                 return (ENOENT);
  971         }
  972 
  973         mtx_lock(&pcb->pcb_mtx);
  974 
  975         NG_BTSOCKET_L2CAP_INFO(
  976 "%s: Got L2CA_Config indicator, src bdaddr=%x:%x:%x:%x:%x:%x, " \
  977 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, state=%d, cfg_state=%x\n",
  978                 __func__,
  979                 pcb->src.b[5], pcb->src.b[4], pcb->src.b[3],
  980                 pcb->src.b[2], pcb->src.b[1], pcb->src.b[0],
  981                 pcb->dst.b[5], pcb->dst.b[4], pcb->dst.b[3],
  982                 pcb->dst.b[2], pcb->dst.b[1], pcb->dst.b[0],
  983                 pcb->psm, pcb->cid, pcb->state, pcb->cfg_state);
  984 
  985         /* XXX FIXME re-configuration on open socket */
  986         if (pcb->state != NG_BTSOCKET_L2CAP_CONFIGURING) {
  987                 mtx_unlock(&pcb->pcb_mtx);
  988                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
  989 
  990                 return (ENOENT);
  991         }
  992 
  993         /*
  994          * XXX FIXME Actually set flush and link timeout. Set QoS here if
  995          * required. Resolve conficts (flush_timo). Note outgoing MTU (peer's 
  996          * incoming MTU) and incoming flow spec.
  997          */
  998 
  999         pcb->omtu = ip->omtu;
 1000         bcopy(&ip->iflow, &pcb->iflow, sizeof(pcb->iflow));
 1001         pcb->flush_timo = ip->flush_timo;
 1002 
 1003         /*
 1004          * Send L2CA_Config response to our peer and check for the errors, 
 1005          * if any send disconnect to close the channel. 
 1006          */
 1007 
 1008         if (!(pcb->cfg_state & NG_BTSOCKET_L2CAP_CFG_OUT_SENT)) {
 1009                 error = ng_btsocket_l2cap_send_l2ca_cfg_rsp(pcb);
 1010                 if (error != 0) {
 1011                         ng_btsocket_l2cap_untimeout(pcb);
 1012 
 1013                         pcb->so->so_error = error;
 1014 
 1015                         /* Send disconnect with "zero" token */
 1016                         ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
 1017 
 1018                         /* ... and close the socket */
 1019                         pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
 1020                         soisdisconnected(pcb->so);
 1021                 } else
 1022                         pcb->cfg_state |= NG_BTSOCKET_L2CAP_CFG_OUT_SENT;
 1023         }
 1024 
 1025         mtx_unlock(&pcb->pcb_mtx);
 1026         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1027 
 1028         return (error);
 1029 } /* ng_btsocket_l2cap_process_l2cap_cfg_ind */
 1030 
 1031 /*
 1032  * Process L2CA_Disconnect response
 1033  */
 1034 
 1035 static int
 1036 ng_btsocket_l2cap_process_l2ca_discon_rsp(struct ng_mesg *msg,
 1037                 ng_btsocket_l2cap_rtentry_p rt)
 1038 {
 1039         ng_l2cap_l2ca_discon_op *op = NULL;
 1040         ng_btsocket_l2cap_pcb_t *pcb = NULL;
 1041 
 1042         /* Check message */
 1043         if (msg->header.arglen != sizeof(*op))
 1044                 return (EMSGSIZE);
 1045 
 1046         op = (ng_l2cap_l2ca_discon_op *)(msg->data);
 1047 
 1048         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 1049 
 1050         /*
 1051          * Socket layer must have issued L2CA_Disconnect request, so there 
 1052          * must be a socket that wants to be disconnected. Use Netgraph 
 1053          * message token to find it.
 1054          */
 1055 
 1056         pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
 1057         if (pcb == NULL) {
 1058                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1059                 return (0);
 1060         }
 1061 
 1062         mtx_lock(&pcb->pcb_mtx);
 1063 
 1064         /* XXX Close socket no matter what op->result says */
 1065         if (pcb->state != NG_BTSOCKET_L2CAP_CLOSED) {
 1066                 NG_BTSOCKET_L2CAP_INFO(
 1067 "%s: Got L2CA_Disconnect response, token=%d, src bdaddr=%x:%x:%x:%x:%x:%x, " \
 1068 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, state=%d\n",
 1069                         __func__, msg->header.token,
 1070                         pcb->src.b[5], pcb->src.b[4], pcb->src.b[3],
 1071                         pcb->src.b[2], pcb->src.b[1], pcb->src.b[0],
 1072                         pcb->dst.b[5], pcb->dst.b[4], pcb->dst.b[3],
 1073                         pcb->dst.b[2], pcb->dst.b[1], pcb->dst.b[0],
 1074                         pcb->psm, pcb->cid, op->result, pcb->state);
 1075 
 1076                 ng_btsocket_l2cap_untimeout(pcb);
 1077 
 1078                 pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
 1079                 soisdisconnected(pcb->so);
 1080         }
 1081 
 1082         mtx_unlock(&pcb->pcb_mtx);
 1083         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1084 
 1085         return (0);
 1086 } /* ng_btsocket_l2cap_process_l2ca_discon_rsp */
 1087 
 1088 /*
 1089  * Process L2CA_Disconnect indicator
 1090  */
 1091 
 1092 static int
 1093 ng_btsocket_l2cap_process_l2ca_discon_ind(struct ng_mesg *msg,
 1094                 ng_btsocket_l2cap_rtentry_p rt)
 1095 {
 1096         ng_l2cap_l2ca_discon_ind_ip     *ip = NULL;
 1097         ng_btsocket_l2cap_pcb_t         *pcb = NULL;
 1098 
 1099         /* Check message */
 1100         if (msg->header.arglen != sizeof(*ip))
 1101                 return (EMSGSIZE);
 1102 
 1103         ip = (ng_l2cap_l2ca_discon_ind_ip *)(msg->data);
 1104 
 1105         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 1106 
 1107         /* Look for the socket with given channel ID */
 1108         pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, ip->lcid,
 1109                                            ip->idtype);
 1110         if (pcb == NULL) {
 1111                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1112                 return (0);
 1113         }
 1114 
 1115         /*
 1116          * Channel has already been destroyed, so disconnect the socket 
 1117          * and be done with it. If there was any pending request we can
 1118          * not do anything here anyway.
 1119          */
 1120 
 1121         mtx_lock(&pcb->pcb_mtx);
 1122 
 1123         NG_BTSOCKET_L2CAP_INFO(
 1124 "%s: Got L2CA_Disconnect indicator, src bdaddr=%x:%x:%x:%x:%x:%x, " \
 1125 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, state=%d\n",
 1126                 __func__,
 1127                 pcb->src.b[5], pcb->src.b[4], pcb->src.b[3],
 1128                 pcb->src.b[2], pcb->src.b[1], pcb->src.b[0],
 1129                 pcb->dst.b[5], pcb->dst.b[4], pcb->dst.b[3],
 1130                 pcb->dst.b[2], pcb->dst.b[1], pcb->dst.b[0],
 1131                 pcb->psm, pcb->cid, pcb->state);
 1132 
 1133         if (pcb->flags & NG_BTSOCKET_L2CAP_TIMO)
 1134                 ng_btsocket_l2cap_untimeout(pcb);
 1135 
 1136         pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
 1137         soisdisconnected(pcb->so);
 1138 
 1139         mtx_unlock(&pcb->pcb_mtx);
 1140         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1141 
 1142         return (0);
 1143 } /* ng_btsocket_l2cap_process_l2ca_discon_ind */
 1144 
 1145 /*
 1146  * Process L2CA_Write response
 1147  */
 1148 
 1149 static int 
 1150 ng_btsocket_l2cap_process_l2ca_write_rsp(struct ng_mesg *msg,
 1151                 ng_btsocket_l2cap_rtentry_p rt)
 1152 {
 1153         ng_l2cap_l2ca_write_op  *op = NULL;
 1154         ng_btsocket_l2cap_pcb_t *pcb = NULL;
 1155 
 1156         /* Check message */
 1157         if (msg->header.arglen != sizeof(*op))
 1158                 return (EMSGSIZE);
 1159 
 1160         op = (ng_l2cap_l2ca_write_op *)(msg->data);
 1161 
 1162         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 1163 
 1164         /* Look for the socket with given token */
 1165         pcb = ng_btsocket_l2cap_pcb_by_token(msg->header.token);
 1166         if (pcb == NULL) {
 1167                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1168                 return (ENOENT);
 1169         }
 1170 
 1171         mtx_lock(&pcb->pcb_mtx);
 1172 
 1173         NG_BTSOCKET_L2CAP_INFO(
 1174 "%s: Got L2CA_Write response, src bdaddr=%x:%x:%x:%x:%x:%x, " \
 1175 "dst bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, lcid=%d, result=%d, length=%d, " \
 1176 "state=%d\n",           __func__,
 1177                         pcb->src.b[5], pcb->src.b[4], pcb->src.b[3],
 1178                         pcb->src.b[2], pcb->src.b[1], pcb->src.b[0],
 1179                         pcb->dst.b[5], pcb->dst.b[4], pcb->dst.b[3],
 1180                         pcb->dst.b[2], pcb->dst.b[1], pcb->dst.b[0],
 1181                         pcb->psm, pcb->cid, op->result, op->length,
 1182                         pcb->state);
 1183 
 1184         if (pcb->state != NG_BTSOCKET_L2CAP_OPEN) {
 1185                 mtx_unlock(&pcb->pcb_mtx);
 1186                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1187 
 1188                 return (ENOENT);
 1189         }
 1190 
 1191         ng_btsocket_l2cap_untimeout(pcb);
 1192 
 1193         /*
 1194          * Check if we have more data to send
 1195          */
 1196         sbdroprecord(&pcb->so->so_snd);
 1197         if (sbavail(&pcb->so->so_snd) > 0) {
 1198                 if (ng_btsocket_l2cap_send2(pcb) == 0)
 1199                         ng_btsocket_l2cap_timeout(pcb);
 1200                 else
 1201                         sbdroprecord(&pcb->so->so_snd); /* XXX */
 1202         }
 1203 
 1204         /*
 1205          * Now set the result, drop packet from the socket send queue and 
 1206          * ask for more (wakeup sender)
 1207          */
 1208 
 1209         pcb->so->so_error = ng_btsocket_l2cap_result2errno(op->result);
 1210         sowwakeup(pcb->so);
 1211 
 1212         mtx_unlock(&pcb->pcb_mtx);
 1213         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1214 
 1215         return (0);
 1216 } /* ng_btsocket_l2cap_process_l2ca_write_rsp */
 1217 
 1218 /*
 1219  * Send L2CA_Connect request
 1220  */
 1221 
 1222 static int
 1223 ng_btsocket_l2cap_send_l2ca_con_req(ng_btsocket_l2cap_pcb_p pcb)
 1224 {
 1225         struct ng_mesg          *msg = NULL;
 1226         ng_l2cap_l2ca_con_ip    *ip = NULL;
 1227         int                      error = 0;
 1228 
 1229         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 1230 
 1231         if (pcb->rt == NULL || 
 1232             pcb->rt->hook == NULL || NG_HOOK_NOT_VALID(pcb->rt->hook))
 1233                 return (ENETDOWN); 
 1234 
 1235         NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CON,
 1236                 sizeof(*ip), M_NOWAIT);
 1237         if (msg == NULL)
 1238                 return (ENOMEM);
 1239 
 1240         msg->header.token = pcb->token;
 1241 
 1242         ip = (ng_l2cap_l2ca_con_ip *)(msg->data);
 1243         bcopy(&pcb->dst, &ip->bdaddr, sizeof(ip->bdaddr));
 1244         ip->psm = pcb->psm;
 1245         ip->linktype = ng_btsock_l2cap_addrtype_to_linktype(pcb->dsttype);
 1246         ip->idtype = pcb->idtype;
 1247         NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg,pcb->rt->hook, 0);
 1248 
 1249         return (error);
 1250 } /* ng_btsocket_l2cap_send_l2ca_con_req */
 1251 
 1252 /*
 1253  * Send L2CA_Connect response
 1254  */
 1255 
 1256 static int
 1257 ng_btsocket_l2cap_send_l2ca_con_rsp_req(u_int32_t token,
 1258                 ng_btsocket_l2cap_rtentry_p rt, bdaddr_p dst, int ident, 
 1259                                         int lcid, int result, int linktype)
 1260 {
 1261         struct ng_mesg                  *msg = NULL;
 1262         ng_l2cap_l2ca_con_rsp_ip        *ip = NULL;
 1263         int                              error = 0;
 1264 
 1265         if (rt == NULL || rt->hook == NULL || NG_HOOK_NOT_VALID(rt->hook))
 1266                 return (ENETDOWN); 
 1267 
 1268         NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CON_RSP,
 1269                 sizeof(*ip), M_NOWAIT);
 1270         if (msg == NULL)
 1271                 return (ENOMEM);
 1272 
 1273         msg->header.token = token;
 1274 
 1275         ip = (ng_l2cap_l2ca_con_rsp_ip *)(msg->data);
 1276         bcopy(dst, &ip->bdaddr, sizeof(ip->bdaddr));
 1277         ip->ident = ident;
 1278         ip->lcid = lcid;
 1279         ip->linktype = linktype;
 1280         ip->result = result;
 1281         ip->status = 0;
 1282 
 1283         NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg, rt->hook, 0);
 1284 
 1285         return (error);
 1286 } /* ng_btsocket_l2cap_send_l2ca_con_rsp_req */
 1287 
 1288 /*
 1289  * Send L2CA_Config request
 1290  */
 1291 
 1292 static int
 1293 ng_btsocket_l2cap_send_l2ca_cfg_req(ng_btsocket_l2cap_pcb_p pcb)
 1294 {
 1295         struct ng_mesg          *msg = NULL;
 1296         ng_l2cap_l2ca_cfg_ip    *ip = NULL;
 1297         int                      error = 0;
 1298 
 1299         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 1300 
 1301         if (pcb->rt == NULL || 
 1302             pcb->rt->hook == NULL || NG_HOOK_NOT_VALID(pcb->rt->hook))
 1303                 return (ENETDOWN); 
 1304 
 1305         NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CFG,
 1306                 sizeof(*ip), M_NOWAIT);
 1307         if (msg == NULL)
 1308                 return (ENOMEM);
 1309 
 1310         msg->header.token = pcb->token;
 1311 
 1312         ip = (ng_l2cap_l2ca_cfg_ip *)(msg->data);
 1313         ip->lcid = pcb->cid;
 1314         ip->imtu = pcb->imtu;
 1315         bcopy(&pcb->oflow, &ip->oflow, sizeof(ip->oflow));
 1316         ip->flush_timo = pcb->flush_timo;
 1317         ip->link_timo = pcb->link_timo;
 1318 
 1319         NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg,pcb->rt->hook, 0);
 1320 
 1321         return (error);
 1322 } /* ng_btsocket_l2cap_send_l2ca_cfg_req */
 1323 
 1324 /*
 1325  * Send L2CA_Config response
 1326  */
 1327 
 1328 static int
 1329 ng_btsocket_l2cap_send_l2ca_cfg_rsp(ng_btsocket_l2cap_pcb_p pcb)
 1330 {
 1331         struct ng_mesg                  *msg = NULL;
 1332         ng_l2cap_l2ca_cfg_rsp_ip        *ip = NULL;
 1333         int                              error = 0;
 1334 
 1335         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 1336 
 1337         if (pcb->rt == NULL || 
 1338             pcb->rt->hook == NULL || NG_HOOK_NOT_VALID(pcb->rt->hook))
 1339                 return (ENETDOWN); 
 1340 
 1341         NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_CFG_RSP,
 1342                 sizeof(*ip), M_NOWAIT);
 1343         if (msg == NULL)
 1344                 return (ENOMEM);
 1345 
 1346         msg->header.token = pcb->token;
 1347 
 1348         ip = (ng_l2cap_l2ca_cfg_rsp_ip *)(msg->data);
 1349         ip->lcid = pcb->cid;
 1350         ip->omtu = pcb->omtu;
 1351         bcopy(&pcb->iflow, &ip->iflow, sizeof(ip->iflow));
 1352 
 1353         NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg, pcb->rt->hook, 0);
 1354 
 1355         return (error);
 1356 } /* ng_btsocket_l2cap_send_l2ca_cfg_rsp */
 1357 
 1358 /*
 1359  * Send L2CA_Disconnect request
 1360  */
 1361 
 1362 static int
 1363 ng_btsocket_l2cap_send_l2ca_discon_req(u_int32_t token,
 1364                 ng_btsocket_l2cap_pcb_p pcb)
 1365 {
 1366         struct ng_mesg          *msg = NULL;
 1367         ng_l2cap_l2ca_discon_ip *ip = NULL;
 1368         int                      error = 0;
 1369 
 1370         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 1371 
 1372         if (pcb->rt == NULL || 
 1373             pcb->rt->hook == NULL || NG_HOOK_NOT_VALID(pcb->rt->hook))
 1374                 return (ENETDOWN); 
 1375 
 1376         NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_L2CA_DISCON,
 1377                 sizeof(*ip), M_NOWAIT);
 1378         if (msg == NULL)
 1379                 return (ENOMEM);
 1380 
 1381         msg->header.token = token;
 1382 
 1383         ip = (ng_l2cap_l2ca_discon_ip *)(msg->data);
 1384         ip->lcid = pcb->cid;
 1385         ip->idtype = pcb->idtype;
 1386 
 1387         NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_node, msg,pcb->rt->hook, 0);
 1388 
 1389         return (error);
 1390 } /* ng_btsocket_l2cap_send_l2ca_discon_req */
 1391 
 1392 /*****************************************************************************
 1393  *****************************************************************************
 1394  **                              Socket interface
 1395  *****************************************************************************
 1396  *****************************************************************************/
 1397 
 1398 /*
 1399  * L2CAP sockets data input routine
 1400  */
 1401 
 1402 static void
 1403 ng_btsocket_l2cap_data_input(struct mbuf *m, hook_p hook)
 1404 {
 1405         ng_l2cap_hdr_t                  *hdr = NULL;
 1406         ng_l2cap_clt_hdr_t              *clt_hdr = NULL;
 1407         ng_btsocket_l2cap_pcb_t         *pcb = NULL;
 1408         ng_btsocket_l2cap_rtentry_t     *rt = NULL;
 1409         uint16_t idtype;
 1410 
 1411         if (hook == NULL) {
 1412                 NG_BTSOCKET_L2CAP_ALERT(
 1413 "%s: Invalid source hook for L2CAP data packet\n", __func__);
 1414                 goto drop;
 1415         }
 1416 
 1417         rt = (ng_btsocket_l2cap_rtentry_t *) NG_HOOK_PRIVATE(hook);
 1418         if (rt == NULL) {
 1419                 NG_BTSOCKET_L2CAP_ALERT(
 1420 "%s: Could not find out source bdaddr for L2CAP data packet\n", __func__);
 1421                 goto drop;
 1422         }
 1423 
 1424         m = m_pullup(m, sizeof(uint16_t));
 1425         idtype = *mtod(m, uint16_t *);
 1426         m_adj(m, sizeof(uint16_t));
 1427 
 1428         /* Make sure we can access header */
 1429         if (m->m_pkthdr.len < sizeof(*hdr)) {
 1430                 NG_BTSOCKET_L2CAP_ERR(
 1431 "%s: L2CAP data packet too small, len=%d\n", __func__, m->m_pkthdr.len);
 1432                 goto drop;
 1433         }
 1434 
 1435         if (m->m_len < sizeof(*hdr)) { 
 1436                 m = m_pullup(m, sizeof(*hdr));
 1437                 if (m == NULL)
 1438                         goto drop;
 1439         }
 1440 
 1441         /* Strip L2CAP packet header and verify packet length */
 1442         hdr = mtod(m, ng_l2cap_hdr_t *);
 1443         m_adj(m, sizeof(*hdr));
 1444 
 1445         if (hdr->length != m->m_pkthdr.len) {
 1446                 NG_BTSOCKET_L2CAP_ERR(
 1447 "%s: Bad L2CAP data packet length, len=%d, length=%d\n",
 1448                         __func__, m->m_pkthdr.len, hdr->length);
 1449                 goto drop;
 1450         }
 1451 
 1452         /*
 1453          * Now process packet. Two cases:
 1454          *
 1455          * 1) Normal packet (cid != 2) then find connected socket and append
 1456          *    mbuf to the socket queue. Wakeup socket.
 1457          *
 1458          * 2) Broadcast packet (cid == 2) then find all sockets that connected
 1459          *    to the given PSM and have SO_BROADCAST bit set and append mbuf
 1460          *    to the socket queue. Wakeup socket.
 1461          */
 1462 
 1463         NG_BTSOCKET_L2CAP_INFO(
 1464 "%s: Received L2CAP data packet: src bdaddr=%x:%x:%x:%x:%x:%x, " \
 1465 "dcid=%d, length=%d\n",
 1466                 __func__, 
 1467                 rt->src.b[5], rt->src.b[4], rt->src.b[3],
 1468                 rt->src.b[2], rt->src.b[1], rt->src.b[0],
 1469                 hdr->dcid, hdr->length);
 1470 
 1471         if ((hdr->dcid >= NG_L2CAP_FIRST_CID) ||
 1472             (idtype == NG_L2CAP_L2CA_IDTYPE_ATT)||
 1473             (idtype == NG_L2CAP_L2CA_IDTYPE_SMP)
 1474             ){
 1475                 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 1476 
 1477                 /* Normal packet: find connected socket */
 1478                 pcb = ng_btsocket_l2cap_pcb_by_cid(&rt->src, hdr->dcid,idtype);
 1479                 if (pcb == NULL) {
 1480                         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1481                         goto drop;
 1482                 }
 1483 
 1484                 mtx_lock(&pcb->pcb_mtx);
 1485 
 1486                 if (pcb->state != NG_BTSOCKET_L2CAP_OPEN) {
 1487                         NG_BTSOCKET_L2CAP_ERR(
 1488 "%s: No connected socket found, src bdaddr=%x:%x:%x:%x:%x:%x, dcid=%d, " \
 1489 "state=%d\n",                   __func__,
 1490                                 rt->src.b[5], rt->src.b[4], rt->src.b[3],
 1491                                 rt->src.b[2], rt->src.b[1], rt->src.b[0],
 1492                                 hdr->dcid, pcb->state);
 1493 
 1494                         mtx_unlock(&pcb->pcb_mtx);
 1495                         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1496                         goto drop;
 1497                 }
 1498 
 1499                 /* Check packet size against socket's incoming MTU */
 1500                 if (hdr->length > pcb->imtu) {
 1501                         NG_BTSOCKET_L2CAP_ERR(
 1502 "%s: L2CAP data packet too big, src bdaddr=%x:%x:%x:%x:%x:%x, " \
 1503 "dcid=%d, length=%d, imtu=%d\n",
 1504                                 __func__, 
 1505                                 rt->src.b[5], rt->src.b[4], rt->src.b[3],
 1506                                 rt->src.b[2], rt->src.b[1], rt->src.b[0],
 1507                                 hdr->dcid, hdr->length, pcb->imtu);
 1508 
 1509                         mtx_unlock(&pcb->pcb_mtx);
 1510                         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1511                         goto drop;
 1512                 }
 1513 
 1514                 /* Check if we have enough space in socket receive queue */
 1515                 if (m->m_pkthdr.len > sbspace(&pcb->so->so_rcv)) {
 1516                         /* 
 1517                          * This is really bad. Receive queue on socket does
 1518                          * not have enough space for the packet. We do not 
 1519                          * have any other choice but drop the packet. L2CAP 
 1520                          * does not provide any flow control.
 1521                          */
 1522 
 1523                         NG_BTSOCKET_L2CAP_ERR(
 1524 "%s: Not enough space in socket receive queue. Dropping L2CAP data packet, " \
 1525 "src bdaddr=%x:%x:%x:%x:%x:%x, dcid=%d, len=%d, space=%ld\n",
 1526                                 __func__,
 1527                                 rt->src.b[5], rt->src.b[4], rt->src.b[3],
 1528                                 rt->src.b[2], rt->src.b[1], rt->src.b[0],
 1529                                 hdr->dcid, m->m_pkthdr.len,
 1530                                 sbspace(&pcb->so->so_rcv));
 1531 
 1532                         mtx_unlock(&pcb->pcb_mtx);
 1533                         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1534                         goto drop;
 1535                 }
 1536 
 1537                 /* Append packet to the socket receive queue and wakeup */
 1538                 sbappendrecord(&pcb->so->so_rcv, m);
 1539                 m = NULL;
 1540 
 1541                 sorwakeup(pcb->so);
 1542 
 1543                 mtx_unlock(&pcb->pcb_mtx);
 1544                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1545         } else if (hdr->dcid == NG_L2CAP_CLT_CID) {
 1546                 /* Broadcast packet: give packet to all sockets  */
 1547 
 1548                 /* Check packet size against connectionless MTU */
 1549                 if (hdr->length > NG_L2CAP_MTU_DEFAULT) {
 1550                         NG_BTSOCKET_L2CAP_ERR(
 1551 "%s: Connectionless L2CAP data packet too big, " \
 1552 "src bdaddr=%x:%x:%x:%x:%x:%x, length=%d\n",
 1553                                 __func__,
 1554                                 rt->src.b[5], rt->src.b[4], rt->src.b[3],
 1555                                 rt->src.b[2], rt->src.b[1], rt->src.b[0],
 1556                                 hdr->length);
 1557                         goto drop;
 1558                 }
 1559 
 1560                 /* Make sure we can access connectionless header */
 1561                 if (m->m_pkthdr.len < sizeof(*clt_hdr)) {
 1562                         NG_BTSOCKET_L2CAP_ERR(
 1563 "%s: Can not get L2CAP connectionless packet header, " \
 1564 "src bdaddr=%x:%x:%x:%x:%x:%x, length=%d\n",
 1565                                 __func__,
 1566                                 rt->src.b[5], rt->src.b[4], rt->src.b[3],
 1567                                 rt->src.b[2], rt->src.b[1], rt->src.b[0],
 1568                                 hdr->length);
 1569                         goto drop;
 1570                 }
 1571 
 1572                 if (m->m_len < sizeof(*clt_hdr)) {
 1573                         m = m_pullup(m, sizeof(*clt_hdr));
 1574                         if (m == NULL)
 1575                                 goto drop;
 1576                 }
 1577 
 1578                 /* Strip connectionless header and deliver packet */
 1579                 clt_hdr = mtod(m, ng_l2cap_clt_hdr_t *);
 1580                 m_adj(m, sizeof(*clt_hdr));
 1581 
 1582                 NG_BTSOCKET_L2CAP_INFO(
 1583 "%s: Got L2CAP connectionless data packet, " \
 1584 "src bdaddr=%x:%x:%x:%x:%x:%x, psm=%d, length=%d\n",
 1585                         __func__,
 1586                         rt->src.b[5], rt->src.b[4], rt->src.b[3],
 1587                         rt->src.b[2], rt->src.b[1], rt->src.b[0],
 1588                         clt_hdr->psm, hdr->length);
 1589 
 1590                 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 1591 
 1592                 LIST_FOREACH(pcb, &ng_btsocket_l2cap_sockets, next) {
 1593                         struct mbuf     *copy = NULL;
 1594 
 1595                         mtx_lock(&pcb->pcb_mtx);
 1596 
 1597                         if (bcmp(&rt->src, &pcb->src, sizeof(pcb->src)) != 0 ||
 1598                             pcb->psm != clt_hdr->psm || 
 1599                             pcb->state != NG_BTSOCKET_L2CAP_OPEN || 
 1600                             (pcb->so->so_options & SO_BROADCAST) == 0 || 
 1601                             m->m_pkthdr.len > sbspace(&pcb->so->so_rcv))
 1602                                 goto next;
 1603 
 1604                         /*
 1605                          * Create a copy of the packet and append it to the 
 1606                          * socket's queue. If m_dup() failed - no big deal
 1607                          * it is a broadcast traffic after all
 1608                          */
 1609 
 1610                         copy = m_dup(m, M_NOWAIT);
 1611                         if (copy != NULL) {
 1612                                 sbappendrecord(&pcb->so->so_rcv, copy);
 1613                                 sorwakeup(pcb->so);
 1614                         }
 1615 next:
 1616                         mtx_unlock(&pcb->pcb_mtx);
 1617                 }
 1618 
 1619                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1620         }
 1621 drop:
 1622         NG_FREE_M(m); /* checks for m != NULL */
 1623 } /* ng_btsocket_l2cap_data_input */
 1624 
 1625 /*
 1626  * L2CAP sockets default message input routine
 1627  */
 1628 
 1629 static void
 1630 ng_btsocket_l2cap_default_msg_input(struct ng_mesg *msg, hook_p hook)
 1631 {
 1632         switch (msg->header.cmd) {
 1633         case NGM_L2CAP_NODE_HOOK_INFO: {
 1634                 ng_btsocket_l2cap_rtentry_t     *rt = NULL;
 1635                 ng_l2cap_node_hook_info_ep *ep =
 1636                   (ng_l2cap_node_hook_info_ep *)msg->data;
 1637                 if (hook == NULL || msg->header.arglen != sizeof(*ep))
 1638                         break;
 1639 
 1640                 if (bcmp(&ep->addr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
 1641                         break;
 1642 
 1643                 mtx_lock(&ng_btsocket_l2cap_rt_mtx);
 1644 
 1645                 rt = (ng_btsocket_l2cap_rtentry_t *) NG_HOOK_PRIVATE(hook);
 1646                 if (rt == NULL) {
 1647                         rt = malloc(sizeof(*rt),
 1648                                 M_NETGRAPH_BTSOCKET_L2CAP, M_NOWAIT|M_ZERO);
 1649                         if (rt == NULL) {
 1650                                 mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
 1651                                 break;
 1652                         }
 1653 
 1654                         LIST_INSERT_HEAD(&ng_btsocket_l2cap_rt, rt, next);
 1655 
 1656                         NG_HOOK_SET_PRIVATE(hook, rt);
 1657                 }
 1658 
 1659                 bcopy(&ep->addr, &rt->src, sizeof(rt->src));
 1660                 rt->hook = hook;
 1661 
 1662                 mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
 1663 
 1664                 NG_BTSOCKET_L2CAP_INFO(
 1665 "%s: Updating hook \"%s\", src bdaddr=%x:%x:%x:%x:%x:%x\n",
 1666                         __func__, NG_HOOK_NAME(hook), 
 1667                         rt->src.b[5], rt->src.b[4], rt->src.b[3], 
 1668                         rt->src.b[2], rt->src.b[1], rt->src.b[0]);
 1669                 } break;
 1670 
 1671         default:
 1672                 NG_BTSOCKET_L2CAP_WARN(
 1673 "%s: Unknown message, cmd=%d\n", __func__, msg->header.cmd);
 1674                 break;
 1675         }
 1676 
 1677         NG_FREE_MSG(msg); /* Checks for msg != NULL */
 1678 } /* ng_btsocket_l2cap_default_msg_input */
 1679 
 1680 /*
 1681  * L2CAP sockets L2CA message input routine
 1682  */
 1683 
 1684 static void
 1685 ng_btsocket_l2cap_l2ca_msg_input(struct ng_mesg *msg, hook_p hook)
 1686 {
 1687         ng_btsocket_l2cap_rtentry_p     rt = NULL;
 1688 
 1689         if (hook == NULL) {
 1690                 NG_BTSOCKET_L2CAP_ALERT(
 1691 "%s: Invalid source hook for L2CA message\n", __func__);
 1692                 goto drop;
 1693         }
 1694 
 1695         rt = (ng_btsocket_l2cap_rtentry_p) NG_HOOK_PRIVATE(hook);
 1696         if (rt == NULL) {
 1697                 NG_BTSOCKET_L2CAP_ALERT(
 1698 "%s: Could not find out source bdaddr for L2CA message\n", __func__);
 1699                 goto drop;
 1700         }
 1701 
 1702         switch (msg->header.cmd) {
 1703         case NGM_L2CAP_L2CA_CON: /* L2CA_Connect response */
 1704                 ng_btsocket_l2cap_process_l2ca_con_req_rsp(msg, rt);
 1705                 break;
 1706 
 1707         case NGM_L2CAP_L2CA_CON_RSP: /* L2CA_ConnectRsp response */
 1708                 ng_btsocket_l2cap_process_l2ca_con_rsp_rsp(msg, rt);
 1709                 break;
 1710 
 1711         case NGM_L2CAP_L2CA_CON_IND: /* L2CA_Connect indicator */
 1712                 ng_btsocket_l2cap_process_l2ca_con_ind(msg, rt);
 1713                 break;
 1714 
 1715         case NGM_L2CAP_L2CA_CFG: /* L2CA_Config response */
 1716                 ng_btsocket_l2cap_process_l2ca_cfg_req_rsp(msg, rt);
 1717                 break;
 1718 
 1719         case NGM_L2CAP_L2CA_CFG_RSP: /* L2CA_ConfigRsp response */
 1720                 ng_btsocket_l2cap_process_l2ca_cfg_rsp_rsp(msg, rt);
 1721                 break;
 1722 
 1723         case NGM_L2CAP_L2CA_CFG_IND: /* L2CA_Config indicator */
 1724                 ng_btsocket_l2cap_process_l2ca_cfg_ind(msg, rt);
 1725                 break;
 1726 
 1727         case NGM_L2CAP_L2CA_DISCON: /* L2CA_Disconnect response */
 1728                 ng_btsocket_l2cap_process_l2ca_discon_rsp(msg, rt);
 1729                 break;
 1730 
 1731         case NGM_L2CAP_L2CA_DISCON_IND: /* L2CA_Disconnect indicator */
 1732                 ng_btsocket_l2cap_process_l2ca_discon_ind(msg, rt);
 1733                 break;
 1734 
 1735         case NGM_L2CAP_L2CA_WRITE: /* L2CA_Write response */
 1736                 ng_btsocket_l2cap_process_l2ca_write_rsp(msg, rt);
 1737                 break;
 1738         case NGM_L2CAP_L2CA_ENC_CHANGE:
 1739                 ng_btsocket_l2cap_process_l2ca_enc_change(msg, rt);
 1740 
 1741                 break;
 1742         /* XXX FIXME add other L2CA messages */
 1743 
 1744         default:
 1745                 NG_BTSOCKET_L2CAP_WARN(
 1746 "%s: Unknown L2CA message, cmd=%d\n", __func__, msg->header.cmd);
 1747                 break;
 1748         }
 1749 drop:
 1750         NG_FREE_MSG(msg);
 1751 } /* ng_btsocket_l2cap_l2ca_msg_input */
 1752 
 1753 /*
 1754  * L2CAP sockets input routine
 1755  */
 1756 
 1757 static void
 1758 ng_btsocket_l2cap_input(void *context, int pending)
 1759 {
 1760         item_p  item = NULL;
 1761         hook_p  hook = NULL;
 1762 
 1763         for (;;) {
 1764                 mtx_lock(&ng_btsocket_l2cap_queue_mtx);
 1765                 NG_BT_ITEMQ_DEQUEUE(&ng_btsocket_l2cap_queue, item);
 1766                 mtx_unlock(&ng_btsocket_l2cap_queue_mtx);
 1767 
 1768                 if (item == NULL)
 1769                         break;
 1770 
 1771                 NGI_GET_HOOK(item, hook);
 1772                 if (hook != NULL && NG_HOOK_NOT_VALID(hook))
 1773                         goto drop;
 1774 
 1775                 switch(item->el_flags & NGQF_TYPE) {
 1776                 case NGQF_DATA: {
 1777                         struct mbuf     *m = NULL;
 1778 
 1779                         NGI_GET_M(item, m);
 1780                         ng_btsocket_l2cap_data_input(m, hook);
 1781                         } break;
 1782 
 1783                 case NGQF_MESG: {
 1784                         struct ng_mesg  *msg = NULL;
 1785 
 1786                         NGI_GET_MSG(item, msg);
 1787 
 1788                         switch (msg->header.cmd) {
 1789                         case NGM_L2CAP_L2CA_CON:
 1790                         case NGM_L2CAP_L2CA_CON_RSP:
 1791                         case NGM_L2CAP_L2CA_CON_IND:
 1792                         case NGM_L2CAP_L2CA_CFG:
 1793                         case NGM_L2CAP_L2CA_CFG_RSP:
 1794                         case NGM_L2CAP_L2CA_CFG_IND: 
 1795                         case NGM_L2CAP_L2CA_DISCON:
 1796                         case NGM_L2CAP_L2CA_DISCON_IND:
 1797                         case NGM_L2CAP_L2CA_WRITE:
 1798                         case NGM_L2CAP_L2CA_ENC_CHANGE:
 1799                         /* XXX FIXME add other L2CA messages */
 1800                                 ng_btsocket_l2cap_l2ca_msg_input(msg, hook);
 1801                                 break;
 1802 
 1803                         default:
 1804                                 ng_btsocket_l2cap_default_msg_input(msg, hook);
 1805                                 break;
 1806                         }
 1807                         } break;
 1808 
 1809                 default:
 1810                         KASSERT(0,
 1811 ("%s: invalid item type=%ld\n", __func__, (item->el_flags & NGQF_TYPE)));
 1812                         break;
 1813                 }
 1814 drop:
 1815                 if (hook != NULL)
 1816                         NG_HOOK_UNREF(hook);
 1817 
 1818                 NG_FREE_ITEM(item);
 1819         }
 1820 } /* ng_btsocket_l2cap_input */
 1821 
 1822 /*
 1823  * Route cleanup task. Gets scheduled when hook is disconnected. Here we 
 1824  * will find all sockets that use "invalid" hook and disconnect them.
 1825  */
 1826 
 1827 static void
 1828 ng_btsocket_l2cap_rtclean(void *context, int pending)
 1829 {
 1830         ng_btsocket_l2cap_pcb_p         pcb = NULL, pcb_next = NULL;
 1831         ng_btsocket_l2cap_rtentry_p     rt = NULL;
 1832 
 1833         mtx_lock(&ng_btsocket_l2cap_rt_mtx);
 1834         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 1835 
 1836         /*
 1837          * First disconnect all sockets that use "invalid" hook
 1838          */
 1839 
 1840         for (pcb = LIST_FIRST(&ng_btsocket_l2cap_sockets); pcb != NULL; ) {
 1841                 mtx_lock(&pcb->pcb_mtx);
 1842                 pcb_next = LIST_NEXT(pcb, next);
 1843 
 1844                 if (pcb->rt != NULL &&
 1845                     pcb->rt->hook != NULL && NG_HOOK_NOT_VALID(pcb->rt->hook)) {
 1846                         if (pcb->flags & NG_BTSOCKET_L2CAP_TIMO)
 1847                                 ng_btsocket_l2cap_untimeout(pcb);
 1848 
 1849                         pcb->so->so_error = ENETDOWN;
 1850                         pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
 1851                         soisdisconnected(pcb->so);
 1852 
 1853                         pcb->token = 0;
 1854                         pcb->cid = 0;
 1855                         pcb->rt = NULL;
 1856                 }
 1857 
 1858                 mtx_unlock(&pcb->pcb_mtx);
 1859                 pcb = pcb_next;
 1860         }
 1861 
 1862         /*
 1863          * Now cleanup routing table
 1864          */
 1865 
 1866         for (rt = LIST_FIRST(&ng_btsocket_l2cap_rt); rt != NULL; ) {
 1867                 ng_btsocket_l2cap_rtentry_p     rt_next = LIST_NEXT(rt, next);
 1868 
 1869                 if (rt->hook != NULL && NG_HOOK_NOT_VALID(rt->hook)) {
 1870                         LIST_REMOVE(rt, next);
 1871 
 1872                         NG_HOOK_SET_PRIVATE(rt->hook, NULL);
 1873                         NG_HOOK_UNREF(rt->hook); /* Remove extra reference */
 1874 
 1875                         bzero(rt, sizeof(*rt));
 1876                         free(rt, M_NETGRAPH_BTSOCKET_L2CAP);
 1877                 }
 1878 
 1879                 rt = rt_next;
 1880         }
 1881 
 1882         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 1883         mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
 1884 } /* ng_btsocket_l2cap_rtclean */
 1885 
 1886 /*
 1887  * Initialize everything
 1888  */
 1889 
 1890 static void
 1891 ng_btsocket_l2cap_init(void *arg __unused)
 1892 {
 1893         int     error = 0;
 1894 
 1895         ng_btsocket_l2cap_node = NULL;
 1896         ng_btsocket_l2cap_debug_level = NG_BTSOCKET_WARN_LEVEL;
 1897 
 1898         /* Register Netgraph node type */
 1899         error = ng_newtype(&typestruct);
 1900         if (error != 0) {
 1901                 NG_BTSOCKET_L2CAP_ALERT(
 1902 "%s: Could not register Netgraph node type, error=%d\n", __func__, error);
 1903 
 1904                 return;
 1905         }
 1906 
 1907         /* Create Netgrapg node */
 1908         error = ng_make_node_common(&typestruct, &ng_btsocket_l2cap_node);
 1909         if (error != 0) {
 1910                 NG_BTSOCKET_L2CAP_ALERT(
 1911 "%s: Could not create Netgraph node, error=%d\n", __func__, error);
 1912 
 1913                 ng_btsocket_l2cap_node = NULL;
 1914 
 1915                 return;
 1916         }
 1917 
 1918         error = ng_name_node(ng_btsocket_l2cap_node,
 1919                                 NG_BTSOCKET_L2CAP_NODE_TYPE);
 1920         if (error != 0) {
 1921                 NG_BTSOCKET_L2CAP_ALERT(
 1922 "%s: Could not name Netgraph node, error=%d\n", __func__, error);
 1923 
 1924                 NG_NODE_UNREF(ng_btsocket_l2cap_node);
 1925                 ng_btsocket_l2cap_node = NULL;
 1926 
 1927                 return;
 1928         }
 1929 
 1930         /* Create input queue */
 1931         NG_BT_ITEMQ_INIT(&ng_btsocket_l2cap_queue, ifqmaxlen);
 1932         mtx_init(&ng_btsocket_l2cap_queue_mtx,
 1933                 "btsocks_l2cap_queue_mtx", NULL, MTX_DEF);
 1934         TASK_INIT(&ng_btsocket_l2cap_queue_task, 0,
 1935                 ng_btsocket_l2cap_input, NULL);
 1936 
 1937         /* Create list of sockets */
 1938         LIST_INIT(&ng_btsocket_l2cap_sockets);
 1939         mtx_init(&ng_btsocket_l2cap_sockets_mtx,
 1940                 "btsocks_l2cap_sockets_mtx", NULL, MTX_DEF);
 1941 
 1942         /* Routing table */
 1943         LIST_INIT(&ng_btsocket_l2cap_rt);
 1944         mtx_init(&ng_btsocket_l2cap_rt_mtx,
 1945                 "btsocks_l2cap_rt_mtx", NULL, MTX_DEF);
 1946         TASK_INIT(&ng_btsocket_l2cap_rt_task, 0,
 1947                 ng_btsocket_l2cap_rtclean, NULL);
 1948 } /* ng_btsocket_l2cap_init */
 1949 SYSINIT(ng_btsocket_l2cap_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
 1950     ng_btsocket_l2cap_init, NULL);
 1951 
 1952 /*
 1953  * Abort connection on socket
 1954  */
 1955 
 1956 void
 1957 ng_btsocket_l2cap_abort(struct socket *so)
 1958 {
 1959         so->so_error = ECONNABORTED;
 1960 
 1961         (void)ng_btsocket_l2cap_disconnect(so);
 1962 } /* ng_btsocket_l2cap_abort */
 1963 
 1964 void
 1965 ng_btsocket_l2cap_close(struct socket *so)
 1966 {
 1967 
 1968         (void)ng_btsocket_l2cap_disconnect(so);
 1969 } /* ng_btsocket_l2cap_close */
 1970 
 1971 /*
 1972  * Accept connection on socket. Nothing to do here, socket must be connected
 1973  * and ready, so just return peer address and be done with it.
 1974  */
 1975 
 1976 int
 1977 ng_btsocket_l2cap_accept(struct socket *so, struct sockaddr **nam)
 1978 {
 1979         if (ng_btsocket_l2cap_node == NULL) 
 1980                 return (EINVAL);
 1981 
 1982         return (ng_btsocket_l2cap_peeraddr(so, nam));
 1983 } /* ng_btsocket_l2cap_accept */
 1984 
 1985 /*
 1986  * Create and attach new socket
 1987  */
 1988 
 1989 int
 1990 ng_btsocket_l2cap_attach(struct socket *so, int proto, struct thread *td)
 1991 {
 1992         static u_int32_t        token = 0;
 1993         ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so);
 1994         int                     error;
 1995 
 1996         /* Check socket and protocol */
 1997         if (ng_btsocket_l2cap_node == NULL) 
 1998                 return (EPROTONOSUPPORT);
 1999         if (so->so_type != SOCK_SEQPACKET)
 2000                 return (ESOCKTNOSUPPORT);
 2001 
 2002 #if 0 /* XXX sonewconn() calls "pru_attach" with proto == 0 */
 2003         if (proto != 0) 
 2004                 if (proto != BLUETOOTH_PROTO_L2CAP)
 2005                         return (EPROTONOSUPPORT);
 2006 #endif /* XXX */
 2007 
 2008         if (pcb != NULL)
 2009                 return (EISCONN);
 2010 
 2011         /* Reserve send and receive space if it is not reserved yet */
 2012         if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
 2013                 error = soreserve(so, NG_BTSOCKET_L2CAP_SENDSPACE,
 2014                                         NG_BTSOCKET_L2CAP_RECVSPACE);
 2015                 if (error != 0)
 2016                         return (error);
 2017         }
 2018 
 2019         /* Allocate the PCB */
 2020         pcb = malloc(sizeof(*pcb),
 2021                 M_NETGRAPH_BTSOCKET_L2CAP, M_NOWAIT | M_ZERO);
 2022         if (pcb == NULL)
 2023                 return (ENOMEM);
 2024 
 2025         /* Link the PCB and the socket */
 2026         so->so_pcb = (caddr_t) pcb;
 2027         pcb->so = so;
 2028         pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
 2029 
 2030         /* Initialize PCB */
 2031         pcb->imtu = pcb->omtu = NG_L2CAP_MTU_DEFAULT;
 2032 
 2033         /* Default flow */
 2034         pcb->iflow.flags = 0x0;
 2035         pcb->iflow.service_type = NG_HCI_SERVICE_TYPE_BEST_EFFORT;
 2036         pcb->iflow.token_rate = 0xffffffff; /* maximum */
 2037         pcb->iflow.token_bucket_size = 0xffffffff; /* maximum */
 2038         pcb->iflow.peak_bandwidth = 0x00000000; /* maximum */
 2039         pcb->iflow.latency = 0xffffffff; /* don't care */
 2040         pcb->iflow.delay_variation = 0xffffffff; /* don't care */
 2041 
 2042         bcopy(&pcb->iflow, &pcb->oflow, sizeof(pcb->oflow));
 2043 
 2044         pcb->flush_timo = NG_L2CAP_FLUSH_TIMO_DEFAULT;
 2045         pcb->link_timo = NG_L2CAP_LINK_TIMO_DEFAULT;
 2046 
 2047         /*
 2048          * XXX Mark PCB mutex as DUPOK to prevent "duplicated lock of
 2049          * the same type" message. When accepting new L2CAP connection 
 2050          * ng_btsocket_l2cap_process_l2ca_con_ind() holds both PCB mutexes 
 2051          * for "old" (accepting) PCB and "new" (created) PCB.
 2052          */
 2053                 
 2054         mtx_init(&pcb->pcb_mtx, "btsocks_l2cap_pcb_mtx", NULL,
 2055                 MTX_DEF|MTX_DUPOK);
 2056         callout_init_mtx(&pcb->timo, &pcb->pcb_mtx, 0);
 2057 
 2058         /*
 2059          * Add the PCB to the list
 2060          * 
 2061          * XXX FIXME VERY IMPORTANT!
 2062          *
 2063          * This is totally FUBAR. We could get here in two cases:
 2064          *
 2065          * 1) When user calls socket()
 2066          * 2) When we need to accept new incoming connection and call 
 2067          *    sonewconn()
 2068          *
 2069          * In the first case we must acquire ng_btsocket_l2cap_sockets_mtx.
 2070          * In the second case we hold ng_btsocket_l2cap_sockets_mtx already.
 2071          * So we now need to distinguish between these cases. From reading
 2072          * /sys/kern/uipc_socket.c we can find out that sonewconn() calls
 2073          * pru_attach with proto == 0 and td == NULL. For now use this fact
 2074          * to figure out if we were called from socket() or from sonewconn().
 2075          */
 2076 
 2077         if (td != NULL)
 2078                 mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 2079         else
 2080                 mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
 2081 
 2082         /* Set PCB token. Use ng_btsocket_l2cap_sockets_mtx for protection */
 2083         if (++ token == 0)
 2084                 token ++;
 2085 
 2086         pcb->token = token;
 2087 
 2088         LIST_INSERT_HEAD(&ng_btsocket_l2cap_sockets, pcb, next);
 2089 
 2090         if (td != NULL)
 2091                 mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 2092 
 2093         return (0);
 2094 } /* ng_btsocket_l2cap_attach */
 2095 
 2096 /*
 2097  * Bind socket
 2098  */
 2099 
 2100 int
 2101 ng_btsocket_l2cap_bind(struct socket *so, struct sockaddr *nam, 
 2102                 struct thread *td)
 2103 {
 2104         ng_btsocket_l2cap_pcb_t *pcb = NULL;
 2105         struct sockaddr_l2cap   *sa = (struct sockaddr_l2cap *) nam;
 2106         int                      psm, error = 0;
 2107 
 2108         if (ng_btsocket_l2cap_node == NULL) 
 2109                 return (EINVAL);
 2110 
 2111         /* Verify address */
 2112         if (sa == NULL)
 2113                 return (EINVAL);
 2114         if (sa->l2cap_family != AF_BLUETOOTH)
 2115                 return (EAFNOSUPPORT);
 2116         /*For the time being, Not support LE binding.*/
 2117         if ((sa->l2cap_len != sizeof(*sa))&&
 2118             (sa->l2cap_len != sizeof(struct sockaddr_l2cap_compat)))
 2119                 return (EINVAL);
 2120 
 2121         psm = le16toh(sa->l2cap_psm);
 2122 
 2123         /* 
 2124          * Check if other socket has this address already (look for exact
 2125          * match PSM and bdaddr) and assign socket address if it's available.
 2126          *
 2127          * Note: socket can be bound to ANY PSM (zero) thus allowing several
 2128          * channels with the same PSM between the same pair of BD_ADDR'es.
 2129          */
 2130 
 2131         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 2132 
 2133         LIST_FOREACH(pcb, &ng_btsocket_l2cap_sockets, next)
 2134                 if (psm != 0 && psm == pcb->psm &&
 2135                     bcmp(&pcb->src, &sa->l2cap_bdaddr, sizeof(bdaddr_t)) == 0)
 2136                         break;
 2137 
 2138         if (pcb == NULL) {
 2139                 /* Set socket address */
 2140                 pcb = so2l2cap_pcb(so);
 2141                 if (pcb != NULL) {
 2142                         bcopy(&sa->l2cap_bdaddr, &pcb->src, sizeof(pcb->src));
 2143                         pcb->psm = psm;
 2144                 } else
 2145                         error = EINVAL;
 2146         } else
 2147                 error = EADDRINUSE;
 2148 
 2149         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 2150 
 2151         return (error);
 2152 } /* ng_btsocket_l2cap_bind */
 2153 
 2154 /*
 2155  * Connect socket
 2156  */
 2157 
 2158 int
 2159 ng_btsocket_l2cap_connect(struct socket *so, struct sockaddr *nam, 
 2160                 struct thread *td)
 2161 {
 2162         ng_btsocket_l2cap_pcb_t         *pcb = so2l2cap_pcb(so);
 2163         struct sockaddr_l2cap_compat    *sal = (struct sockaddr_l2cap_compat *) nam;
 2164         struct sockaddr_l2cap *sa  = (struct sockaddr_l2cap *)nam;
 2165         struct sockaddr_l2cap  ba;
 2166         ng_btsocket_l2cap_rtentry_t     *rt = NULL;
 2167         int                              have_src, error = 0;
 2168         int idtype = NG_L2CAP_L2CA_IDTYPE_BREDR;
 2169         /* Check socket */
 2170         if (pcb == NULL)
 2171                 return (EINVAL);
 2172         if (ng_btsocket_l2cap_node == NULL) 
 2173                 return (EINVAL);
 2174         if (pcb->state == NG_BTSOCKET_L2CAP_CONNECTING)
 2175                 return (EINPROGRESS);
 2176 
 2177         /* Verify address */
 2178         if (sa == NULL)
 2179                 return (EINVAL);
 2180         if (sa->l2cap_family != AF_BLUETOOTH)
 2181                 return (EAFNOSUPPORT);
 2182         if (sa->l2cap_len == sizeof(*sal)){
 2183                 bcopy(sal, &ba, sizeof(*sal));
 2184                 sa = &ba;
 2185                 sa->l2cap_len = sizeof(*sa);
 2186                 sa->l2cap_bdaddr_type = BDADDR_BREDR;
 2187         }
 2188         if (sa->l2cap_len != sizeof(*sa))
 2189                 return (EINVAL);
 2190         if ((sa->l2cap_psm &&  sa->l2cap_cid))
 2191                 return EINVAL;
 2192         if (bcmp(&sa->l2cap_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
 2193                 return (EDESTADDRREQ);
 2194         if((sa->l2cap_bdaddr_type == BDADDR_BREDR)&&
 2195            (sa->l2cap_psm == 0))
 2196                 return EDESTADDRREQ;
 2197         if(sa->l2cap_bdaddr_type != BDADDR_BREDR){
 2198                 if(sa->l2cap_cid == NG_L2CAP_ATT_CID){
 2199                         idtype = NG_L2CAP_L2CA_IDTYPE_ATT;
 2200                 }else if (sa->l2cap_cid == NG_L2CAP_SMP_CID){
 2201                         idtype =NG_L2CAP_L2CA_IDTYPE_SMP;
 2202                 }else{
 2203                         //if cid == 0 idtype = NG_L2CAP_L2CA_IDTYPE_LE;
 2204                         // Not supported yet
 2205                         return EINVAL;
 2206                 }
 2207         }
 2208         if (pcb->psm != 0 && pcb->psm != le16toh(sa->l2cap_psm))
 2209                 return (EINVAL);
 2210         /*
 2211          * Routing. Socket should be bound to some source address. The source
 2212          * address can be ANY. Destination address must be set and it must not
 2213          * be ANY. If source address is ANY then find first rtentry that has
 2214          * src != dst.
 2215          */
 2216 
 2217         mtx_lock(&ng_btsocket_l2cap_rt_mtx);
 2218         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 2219         mtx_lock(&pcb->pcb_mtx);
 2220 
 2221         /* Send destination address and PSM */
 2222         bcopy(&sa->l2cap_bdaddr, &pcb->dst, sizeof(pcb->dst));
 2223         pcb->psm = le16toh(sa->l2cap_psm);
 2224         pcb->dsttype = sa->l2cap_bdaddr_type;
 2225         pcb->cid = 0;
 2226         pcb->idtype = idtype;
 2227         pcb->rt = NULL;
 2228         have_src = bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(pcb->src));
 2229 
 2230         LIST_FOREACH(rt, &ng_btsocket_l2cap_rt, next) {
 2231                 if (rt->hook == NULL || NG_HOOK_NOT_VALID(rt->hook))
 2232                         continue;
 2233 
 2234                 /* Match src and dst */
 2235                 if (have_src) {
 2236                         if (bcmp(&pcb->src, &rt->src, sizeof(rt->src)) == 0)
 2237                                 break;
 2238                 } else {
 2239                         if (bcmp(&pcb->dst, &rt->src, sizeof(rt->src)) != 0)
 2240                                 break;
 2241                 }
 2242         }
 2243 
 2244         if (rt != NULL) {
 2245                 pcb->rt = rt;
 2246 
 2247                 if (!have_src){
 2248                         bcopy(&rt->src, &pcb->src, sizeof(pcb->src));
 2249                         pcb->srctype =
 2250                           (sa->l2cap_bdaddr_type == BDADDR_BREDR)?
 2251                           BDADDR_BREDR : BDADDR_LE_PUBLIC;
 2252                 }
 2253         } else
 2254                 error = EHOSTUNREACH;
 2255 
 2256         /*
 2257          * Send L2CA_Connect request 
 2258          */
 2259 
 2260         if (error == 0) {       
 2261                 error = ng_btsocket_l2cap_send_l2ca_con_req(pcb);
 2262                 if (error == 0) {
 2263                         pcb->flags |= NG_BTSOCKET_L2CAP_CLIENT;
 2264                         pcb->state = NG_BTSOCKET_L2CAP_CONNECTING;
 2265                         soisconnecting(pcb->so);
 2266 
 2267                         ng_btsocket_l2cap_timeout(pcb);
 2268                 }
 2269         }
 2270 
 2271         mtx_unlock(&pcb->pcb_mtx);
 2272         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 2273         mtx_unlock(&ng_btsocket_l2cap_rt_mtx);
 2274 
 2275         return (error);
 2276 } /* ng_btsocket_l2cap_connect */
 2277 
 2278 /*
 2279  * Process ioctl's calls on socket
 2280  */
 2281 
 2282 int
 2283 ng_btsocket_l2cap_control(struct socket *so, u_long cmd, void *data,
 2284                 struct ifnet *ifp, struct thread *td)
 2285 {
 2286         return (EINVAL);
 2287 } /* ng_btsocket_l2cap_control */
 2288 
 2289 /*
 2290  * Process getsockopt/setsockopt system calls
 2291  */
 2292 
 2293 int
 2294 ng_btsocket_l2cap_ctloutput(struct socket *so, struct sockopt *sopt)
 2295 {
 2296         ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so);
 2297         int                     error = 0;
 2298         ng_l2cap_cfg_opt_val_t  v;
 2299 
 2300         if (pcb == NULL)
 2301                 return (EINVAL);
 2302         if (ng_btsocket_l2cap_node == NULL) 
 2303                 return (EINVAL);
 2304 
 2305         if (sopt->sopt_level != SOL_L2CAP)
 2306                 return (0);
 2307 
 2308         mtx_lock(&pcb->pcb_mtx);
 2309 
 2310         switch (sopt->sopt_dir) {
 2311         case SOPT_GET:
 2312                 switch (sopt->sopt_name) {
 2313                 case SO_L2CAP_IMTU: /* get incoming MTU */
 2314                         error = sooptcopyout(sopt, &pcb->imtu,
 2315                                                 sizeof(pcb->imtu));
 2316                         break;
 2317 
 2318                 case SO_L2CAP_OMTU: /* get outgoing (peer incoming) MTU */
 2319                         error = sooptcopyout(sopt, &pcb->omtu,
 2320                                                 sizeof(pcb->omtu));
 2321                         break;
 2322 
 2323                 case SO_L2CAP_IFLOW: /* get incoming flow spec. */
 2324                         error = sooptcopyout(sopt, &pcb->iflow,
 2325                                                 sizeof(pcb->iflow));
 2326                         break;
 2327 
 2328                 case SO_L2CAP_OFLOW: /* get outgoing flow spec. */
 2329                         error = sooptcopyout(sopt, &pcb->oflow,
 2330                                                 sizeof(pcb->oflow));
 2331                         break;
 2332 
 2333                 case SO_L2CAP_FLUSH: /* get flush timeout */
 2334                         error = sooptcopyout(sopt, &pcb->flush_timo,
 2335                                                 sizeof(pcb->flush_timo));
 2336                         break;
 2337                 case SO_L2CAP_ENCRYPTED: /* get encrypt required */
 2338                         error = sooptcopyout(sopt, &pcb->need_encrypt,
 2339                                                 sizeof(pcb->need_encrypt));
 2340                         break;
 2341 
 2342                 default:
 2343                         error = ENOPROTOOPT;
 2344                         break;
 2345                 }
 2346                 break;
 2347 
 2348         case SOPT_SET:
 2349                 /*
 2350                  * XXX
 2351                  * We do not allow to change these parameters while socket is 
 2352                  * connected or we are in the process of creating a connection.
 2353                  * May be this should indicate re-configuration of the open 
 2354                  * channel?
 2355                  */
 2356 
 2357                 if (pcb->state != NG_BTSOCKET_L2CAP_CLOSED) {
 2358                         error = EACCES;
 2359                         break;
 2360                 }
 2361 
 2362                 switch (sopt->sopt_name) {
 2363                 case SO_L2CAP_IMTU: /* set incoming MTU */
 2364                         error = sooptcopyin(sopt, &v, sizeof(v), sizeof(v.mtu));
 2365                         if (error == 0)
 2366                                 pcb->imtu = v.mtu;
 2367                         break;
 2368 
 2369                 case SO_L2CAP_OFLOW: /* set outgoing flow spec. */
 2370                         error = sooptcopyin(sopt, &v, sizeof(v),sizeof(v.flow));
 2371                         if (error == 0)
 2372                                 bcopy(&v.flow, &pcb->oflow, sizeof(pcb->oflow));
 2373                         break;
 2374 
 2375                 case SO_L2CAP_FLUSH: /* set flush timeout */
 2376                         error = sooptcopyin(sopt, &v, sizeof(v),
 2377                                                 sizeof(v.flush_timo));
 2378                         if (error == 0)
 2379                                 pcb->flush_timo = v.flush_timo;
 2380                         break;
 2381                 case SO_L2CAP_ENCRYPTED: /*set connect encryption opt*/
 2382                         if((pcb->state != NG_BTSOCKET_L2CAP_OPEN) &&
 2383                            (pcb->state != NG_BTSOCKET_L2CAP_W4_ENC_CHANGE)){
 2384                                 error = sooptcopyin(sopt, &v, sizeof(v),
 2385                                                     sizeof(v.encryption));
 2386                                 if(error == 0)
 2387                                         pcb->need_encrypt = (v.encryption)?1:0;
 2388                         }else{
 2389                                 error = EINVAL;
 2390                         }
 2391                         break;
 2392                 default:
 2393                         error = ENOPROTOOPT;
 2394                         break;
 2395                 }
 2396                 break;
 2397 
 2398         default:
 2399                 error = EINVAL;
 2400                 break;
 2401         }
 2402 
 2403         mtx_unlock(&pcb->pcb_mtx);
 2404 
 2405         return (error);
 2406 } /* ng_btsocket_l2cap_ctloutput */
 2407 
 2408 /*
 2409  * Detach and destroy socket
 2410  */
 2411 
 2412 void
 2413 ng_btsocket_l2cap_detach(struct socket *so)
 2414 {
 2415         ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so);
 2416 
 2417         KASSERT(pcb != NULL, ("ng_btsocket_l2cap_detach: pcb == NULL"));
 2418 
 2419         if (ng_btsocket_l2cap_node == NULL) 
 2420                 return;
 2421 
 2422         mtx_lock(&ng_btsocket_l2cap_sockets_mtx);
 2423         mtx_lock(&pcb->pcb_mtx);
 2424 
 2425         /* XXX what to do with pending request? */
 2426         if (pcb->flags & NG_BTSOCKET_L2CAP_TIMO)
 2427                 ng_btsocket_l2cap_untimeout(pcb);
 2428 
 2429         if (pcb->state != NG_BTSOCKET_L2CAP_CLOSED &&
 2430             pcb->state != NG_BTSOCKET_L2CAP_DISCONNECTING)
 2431                 /* Send disconnect request with "zero" token */
 2432                 ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
 2433 
 2434         pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
 2435 
 2436         LIST_REMOVE(pcb, next);
 2437 
 2438         mtx_unlock(&pcb->pcb_mtx);
 2439         mtx_unlock(&ng_btsocket_l2cap_sockets_mtx);
 2440 
 2441         mtx_destroy(&pcb->pcb_mtx);
 2442         bzero(pcb, sizeof(*pcb));
 2443         free(pcb, M_NETGRAPH_BTSOCKET_L2CAP);
 2444 
 2445         soisdisconnected(so);
 2446         so->so_pcb = NULL;
 2447 } /* ng_btsocket_l2cap_detach */
 2448 
 2449 /*
 2450  * Disconnect socket
 2451  */
 2452 
 2453 int
 2454 ng_btsocket_l2cap_disconnect(struct socket *so)
 2455 {
 2456         ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so);
 2457         int                     error = 0;
 2458 
 2459         if (pcb == NULL)
 2460                 return (EINVAL);
 2461         if (ng_btsocket_l2cap_node == NULL) 
 2462                 return (EINVAL);
 2463 
 2464         mtx_lock(&pcb->pcb_mtx);
 2465 
 2466         if (pcb->state == NG_BTSOCKET_L2CAP_DISCONNECTING) {
 2467                 mtx_unlock(&pcb->pcb_mtx);
 2468                 return (EINPROGRESS);
 2469         }
 2470 
 2471         if (pcb->state != NG_BTSOCKET_L2CAP_CLOSED) {
 2472                 /* XXX FIXME what to do with pending request? */
 2473                 if (pcb->flags & NG_BTSOCKET_L2CAP_TIMO)
 2474                         ng_btsocket_l2cap_untimeout(pcb);
 2475 
 2476                 error = ng_btsocket_l2cap_send_l2ca_discon_req(pcb->token, pcb);
 2477                 if (error == 0) {
 2478                         pcb->state = NG_BTSOCKET_L2CAP_DISCONNECTING;
 2479                         soisdisconnecting(so);
 2480 
 2481                         ng_btsocket_l2cap_timeout(pcb);
 2482                 }
 2483 
 2484                 /* XXX FIXME what to do if error != 0 */
 2485         }
 2486 
 2487         mtx_unlock(&pcb->pcb_mtx);
 2488 
 2489         return (error);
 2490 } /* ng_btsocket_l2cap_disconnect */
 2491 
 2492 /*
 2493  * Listen on socket
 2494  */
 2495 
 2496 int
 2497 ng_btsocket_l2cap_listen(struct socket *so, int backlog, struct thread *td)
 2498 {
 2499         ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so);
 2500         int error;
 2501 
 2502         SOCK_LOCK(so);
 2503         error = solisten_proto_check(so);
 2504         if (error != 0)
 2505                 goto out;
 2506         if (pcb == NULL) {
 2507                 solisten_proto_abort(so);
 2508                 error = EINVAL;
 2509                 goto out;
 2510         }
 2511         if (ng_btsocket_l2cap_node == NULL) {
 2512                 solisten_proto_abort(so);
 2513                 error = EINVAL;
 2514                 goto out;
 2515         }
 2516         if (pcb->psm == 0) {
 2517                 solisten_proto_abort(so);
 2518                 error = EADDRNOTAVAIL;
 2519                 goto out;
 2520         }
 2521         solisten_proto(so, backlog);
 2522 out:
 2523         SOCK_UNLOCK(so);
 2524         return (error);
 2525 } /* ng_btsocket_listen */
 2526 
 2527 /*
 2528  * Get peer address
 2529  */
 2530 
 2531 int
 2532 ng_btsocket_l2cap_peeraddr(struct socket *so, struct sockaddr **nam)
 2533 {
 2534         ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so);
 2535         struct sockaddr_l2cap   sa;
 2536 
 2537         if (pcb == NULL)
 2538                 return (EINVAL);
 2539         if (ng_btsocket_l2cap_node == NULL) 
 2540                 return (EINVAL);
 2541 
 2542         bcopy(&pcb->dst, &sa.l2cap_bdaddr, sizeof(sa.l2cap_bdaddr));
 2543         sa.l2cap_psm = htole16(pcb->psm);
 2544         sa.l2cap_len = sizeof(sa);
 2545         sa.l2cap_family = AF_BLUETOOTH;
 2546         switch(pcb->idtype){
 2547         case NG_L2CAP_L2CA_IDTYPE_ATT:
 2548                 sa.l2cap_cid = NG_L2CAP_ATT_CID;
 2549                 break;
 2550         case NG_L2CAP_L2CA_IDTYPE_SMP:
 2551                 sa.l2cap_cid = NG_L2CAP_SMP_CID;
 2552                 break;
 2553         default:
 2554                 sa.l2cap_cid = 0;
 2555                 break;
 2556         }
 2557         sa.l2cap_bdaddr_type = pcb->dsttype;
 2558         *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
 2559 
 2560         return ((*nam == NULL)? ENOMEM : 0);
 2561 } /* ng_btsocket_l2cap_peeraddr */
 2562 
 2563 /*
 2564  * Send data to socket
 2565  */
 2566 
 2567 int
 2568 ng_btsocket_l2cap_send(struct socket *so, int flags, struct mbuf *m,
 2569                 struct sockaddr *nam, struct mbuf *control, struct thread *td)
 2570 {
 2571         ng_btsocket_l2cap_pcb_t *pcb = so2l2cap_pcb(so);
 2572         int                      error = 0;
 2573 
 2574         if (ng_btsocket_l2cap_node == NULL) {
 2575                 error = ENETDOWN;
 2576                 goto drop;
 2577         }
 2578 
 2579         /* Check socket and input */
 2580         if (pcb == NULL || m == NULL || control != NULL) {
 2581                 error = EINVAL;
 2582                 goto drop;
 2583         }
 2584 
 2585         mtx_lock(&pcb->pcb_mtx);
 2586 
 2587         /* Make sure socket is connected */
 2588         if (pcb->state != NG_BTSOCKET_L2CAP_OPEN) {
 2589                 mtx_unlock(&pcb->pcb_mtx);
 2590                 error = ENOTCONN;
 2591                 goto drop;
 2592         }
 2593 
 2594         /* Check route */
 2595         if (pcb->rt == NULL ||
 2596             pcb->rt->hook == NULL || NG_HOOK_NOT_VALID(pcb->rt->hook)) {
 2597                 mtx_unlock(&pcb->pcb_mtx);
 2598                 error = ENETDOWN;
 2599                 goto drop;
 2600         }
 2601 
 2602         /* Check packet size against outgoing (peer's incoming) MTU) */
 2603         if (m->m_pkthdr.len > pcb->omtu) {
 2604                 NG_BTSOCKET_L2CAP_ERR(
 2605 "%s: Packet too big, len=%d, omtu=%d\n", __func__, m->m_pkthdr.len, pcb->omtu);
 2606 
 2607                 mtx_unlock(&pcb->pcb_mtx);
 2608                 error = EMSGSIZE;
 2609                 goto drop;
 2610         }
 2611 
 2612         /*
 2613          * First put packet on socket send queue. Then check if we have
 2614          * pending timeout. If we do not have timeout then we must send
 2615          * packet and schedule timeout. Otherwise do nothing and wait for
 2616          * L2CA_WRITE_RSP.
 2617          */
 2618 
 2619         sbappendrecord(&pcb->so->so_snd, m);
 2620         m = NULL;
 2621 
 2622         if (!(pcb->flags & NG_BTSOCKET_L2CAP_TIMO)) {
 2623                 error = ng_btsocket_l2cap_send2(pcb);
 2624                 if (error == 0)
 2625                         ng_btsocket_l2cap_timeout(pcb);
 2626                 else
 2627                         sbdroprecord(&pcb->so->so_snd); /* XXX */
 2628         }
 2629 
 2630         mtx_unlock(&pcb->pcb_mtx);
 2631 drop:
 2632         NG_FREE_M(m); /* checks for != NULL */
 2633         NG_FREE_M(control);
 2634 
 2635         return (error);
 2636 } /* ng_btsocket_l2cap_send */
 2637 
 2638 /*
 2639  * Send first packet in the socket queue to the L2CAP layer
 2640  */
 2641 
 2642 static int
 2643 ng_btsocket_l2cap_send2(ng_btsocket_l2cap_pcb_p pcb)
 2644 {
 2645         struct  mbuf            *m = NULL;
 2646         ng_l2cap_l2ca_hdr_t     *hdr = NULL;
 2647         int                      error = 0;
 2648 
 2649         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 2650 
 2651         if (sbavail(&pcb->so->so_snd) == 0)
 2652                 return (EINVAL); /* XXX */
 2653 
 2654         m = m_dup(pcb->so->so_snd.sb_mb, M_NOWAIT);
 2655         if (m == NULL)
 2656                 return (ENOBUFS);
 2657 
 2658         /* Create L2CA packet header */
 2659         M_PREPEND(m, sizeof(*hdr), M_NOWAIT);
 2660         if (m != NULL)
 2661                 if (m->m_len < sizeof(*hdr))
 2662                         m = m_pullup(m, sizeof(*hdr));
 2663 
 2664         if (m == NULL) {
 2665                 NG_BTSOCKET_L2CAP_ERR(
 2666 "%s: Failed to create L2CA packet header\n", __func__);
 2667 
 2668                 return (ENOBUFS);
 2669         }
 2670 
 2671         hdr = mtod(m, ng_l2cap_l2ca_hdr_t *);
 2672         hdr->token = pcb->token;
 2673         hdr->length = m->m_pkthdr.len - sizeof(*hdr);
 2674         hdr->lcid = pcb->cid;
 2675         hdr->idtype = pcb->idtype;
 2676         NG_BTSOCKET_L2CAP_INFO(
 2677 "%s: Sending packet: len=%d, length=%d, lcid=%d, token=%d, state=%d\n",
 2678                 __func__, m->m_pkthdr.len, hdr->length, hdr->lcid, 
 2679                 hdr->token, pcb->state);
 2680 
 2681         /*
 2682          * If we got here than we have successfully creates new L2CAP 
 2683          * data packet and now we can send it to the L2CAP layer
 2684          */
 2685 
 2686         NG_SEND_DATA_ONLY(error, pcb->rt->hook, m);
 2687 
 2688         return (error);
 2689 } /* ng_btsocket_l2cap_send2 */
 2690 
 2691 /*
 2692  * Get socket address
 2693  */
 2694 
 2695 int
 2696 ng_btsocket_l2cap_sockaddr(struct socket *so, struct sockaddr **nam)
 2697 {
 2698         ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so);
 2699         struct sockaddr_l2cap   sa;
 2700 
 2701         if (pcb == NULL)
 2702                 return (EINVAL);
 2703         if (ng_btsocket_l2cap_node == NULL) 
 2704                 return (EINVAL);
 2705 
 2706         bcopy(&pcb->src, &sa.l2cap_bdaddr, sizeof(sa.l2cap_bdaddr));
 2707         sa.l2cap_psm = htole16(pcb->psm);
 2708         sa.l2cap_len = sizeof(sa);
 2709         sa.l2cap_family = AF_BLUETOOTH;
 2710         sa.l2cap_cid = 0;
 2711         sa.l2cap_bdaddr_type = pcb->srctype;
 2712 
 2713         *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
 2714 
 2715         return ((*nam == NULL)? ENOMEM : 0);
 2716 } /* ng_btsocket_l2cap_sockaddr */
 2717 
 2718 /*****************************************************************************
 2719  *****************************************************************************
 2720  **                              Misc. functions
 2721  *****************************************************************************
 2722  *****************************************************************************/
 2723 
 2724 /*
 2725  * Look for the socket that listens on given PSM and bdaddr. Returns exact or
 2726  * close match (if any). Caller must hold ng_btsocket_l2cap_sockets_mtx.
 2727  */
 2728 
 2729 static ng_btsocket_l2cap_pcb_p
 2730 ng_btsocket_l2cap_pcb_by_addr(bdaddr_p bdaddr, int psm)
 2731 {
 2732         ng_btsocket_l2cap_pcb_p p = NULL, p1 = NULL;
 2733 
 2734         mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
 2735 
 2736         LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next) {
 2737                 if (p->so == NULL || !SOLISTENING(p->so) || p->psm != psm)
 2738                         continue;
 2739 
 2740                 if (bcmp(&p->src, bdaddr, sizeof(p->src)) == 0)
 2741                         break;
 2742 
 2743                 if (bcmp(&p->src, NG_HCI_BDADDR_ANY, sizeof(p->src)) == 0)
 2744                         p1 = p;
 2745         }
 2746 
 2747         return ((p != NULL)? p : p1);
 2748 } /* ng_btsocket_l2cap_pcb_by_addr */
 2749 
 2750 /*
 2751  * Look for the socket that has given token.
 2752  * Caller must hold ng_btsocket_l2cap_sockets_mtx.
 2753  */
 2754 
 2755 static ng_btsocket_l2cap_pcb_p
 2756 ng_btsocket_l2cap_pcb_by_token(u_int32_t token)
 2757 {
 2758         ng_btsocket_l2cap_pcb_p p = NULL;
 2759 
 2760         if (token == 0)
 2761                 return (NULL);
 2762 
 2763         mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
 2764 
 2765         LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next)
 2766                 if (p->token == token)
 2767                         break;
 2768 
 2769         return (p);
 2770 } /* ng_btsocket_l2cap_pcb_by_token */
 2771 
 2772 /*
 2773  * Look for the socket that assigned to given source address and channel ID.
 2774  * Caller must hold ng_btsocket_l2cap_sockets_mtx
 2775  */
 2776 
 2777 static ng_btsocket_l2cap_pcb_p
 2778 ng_btsocket_l2cap_pcb_by_cid(bdaddr_p src, int cid, int idtype)
 2779 {
 2780         ng_btsocket_l2cap_pcb_p p = NULL;
 2781 
 2782         mtx_assert(&ng_btsocket_l2cap_sockets_mtx, MA_OWNED);
 2783 
 2784         LIST_FOREACH(p, &ng_btsocket_l2cap_sockets, next){
 2785                 if (p->cid == cid &&
 2786                     bcmp(src, &p->src, sizeof(p->src)) == 0&&
 2787                     p->idtype == idtype)                    
 2788                         break;
 2789         }
 2790         return (p);
 2791 } /* ng_btsocket_l2cap_pcb_by_cid */
 2792 
 2793 /*
 2794  * Set timeout on socket
 2795  */
 2796 
 2797 static void
 2798 ng_btsocket_l2cap_timeout(ng_btsocket_l2cap_pcb_p pcb)
 2799 {
 2800         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 2801 
 2802         if (!(pcb->flags & NG_BTSOCKET_L2CAP_TIMO)) {
 2803                 pcb->flags |= NG_BTSOCKET_L2CAP_TIMO;
 2804                 callout_reset(&pcb->timo, bluetooth_l2cap_ertx_timeout(),
 2805                     ng_btsocket_l2cap_process_timeout, pcb);
 2806         } else
 2807                 KASSERT(0,
 2808 ("%s: Duplicated socket timeout?!\n", __func__));
 2809 } /* ng_btsocket_l2cap_timeout */
 2810 
 2811 /*
 2812  * Unset timeout on socket
 2813  */
 2814 
 2815 static void
 2816 ng_btsocket_l2cap_untimeout(ng_btsocket_l2cap_pcb_p pcb)
 2817 {
 2818         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 2819 
 2820         if (pcb->flags & NG_BTSOCKET_L2CAP_TIMO) {
 2821                 callout_stop(&pcb->timo);
 2822                 pcb->flags &= ~NG_BTSOCKET_L2CAP_TIMO;
 2823         } else
 2824                 KASSERT(0,
 2825 ("%s: No socket timeout?!\n", __func__));
 2826 } /* ng_btsocket_l2cap_untimeout */
 2827 
 2828 /*
 2829  * Process timeout on socket
 2830  */
 2831 
 2832 static void
 2833 ng_btsocket_l2cap_process_timeout(void *xpcb)
 2834 {
 2835         ng_btsocket_l2cap_pcb_p pcb = (ng_btsocket_l2cap_pcb_p) xpcb;
 2836 
 2837         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
 2838 
 2839         pcb->flags &= ~NG_BTSOCKET_L2CAP_TIMO;
 2840         pcb->so->so_error = ETIMEDOUT;
 2841 
 2842         switch (pcb->state) {
 2843         case NG_BTSOCKET_L2CAP_CONNECTING:
 2844         case NG_BTSOCKET_L2CAP_CONFIGURING:
 2845         case NG_BTSOCKET_L2CAP_W4_ENC_CHANGE:           
 2846                 /* Send disconnect request with "zero" token */
 2847                 if (pcb->cid != 0)
 2848                         ng_btsocket_l2cap_send_l2ca_discon_req(0, pcb);
 2849 
 2850                 /* ... and close the socket */
 2851                 pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
 2852                 soisdisconnected(pcb->so);
 2853                 break;
 2854 
 2855         case NG_BTSOCKET_L2CAP_OPEN:
 2856                 /* Send timeout - drop packet and wakeup sender */
 2857                 sbdroprecord(&pcb->so->so_snd);
 2858                 sowwakeup(pcb->so);
 2859                 break;
 2860 
 2861         case NG_BTSOCKET_L2CAP_DISCONNECTING:
 2862                 /* Disconnect timeout - disconnect the socket anyway */
 2863                 pcb->state = NG_BTSOCKET_L2CAP_CLOSED;
 2864                 soisdisconnected(pcb->so);
 2865                 break;
 2866 
 2867         default:
 2868                 NG_BTSOCKET_L2CAP_ERR(
 2869 "%s: Invalid socket state=%d\n", __func__, pcb->state);
 2870                 break;
 2871         }
 2872 } /* ng_btsocket_l2cap_process_timeout */
 2873 
 2874 /*
 2875  * Translate HCI/L2CAP error code into "errno" code
 2876  * XXX Note: Some L2CAP and HCI error codes have the same value, but 
 2877  *     different meaning
 2878  */
 2879 
 2880 static int
 2881 ng_btsocket_l2cap_result2errno(int result)
 2882 {
 2883         switch (result) {
 2884         case 0x00: /* No error */ 
 2885                 return (0);
 2886 
 2887         case 0x01: /* Unknown HCI command */
 2888                 return (ENODEV);
 2889 
 2890         case 0x02: /* No connection */
 2891                 return (ENOTCONN);
 2892 
 2893         case 0x03: /* Hardware failure */
 2894                 return (EIO);
 2895 
 2896         case 0x04: /* Page timeout */
 2897                 return (EHOSTDOWN);
 2898 
 2899         case 0x05: /* Authentication failure */
 2900         case 0x06: /* Key missing */
 2901         case 0x18: /* Pairing not allowed */
 2902         case 0x21: /* Role change not allowed */
 2903         case 0x24: /* LMP PSU not allowed */
 2904         case 0x25: /* Encryption mode not acceptable */
 2905         case 0x26: /* Unit key used */
 2906                 return (EACCES);
 2907 
 2908         case 0x07: /* Memory full */
 2909                 return (ENOMEM);
 2910 
 2911         case 0x08:   /* Connection timeout */
 2912         case 0x10:   /* Host timeout */
 2913         case 0x22:   /* LMP response timeout */
 2914         case 0xee:   /* HCI timeout */
 2915         case 0xeeee: /* L2CAP timeout */
 2916                 return (ETIMEDOUT);
 2917 
 2918         case 0x09: /* Max number of connections */
 2919         case 0x0a: /* Max number of SCO connections to a unit */
 2920                 return (EMLINK);
 2921 
 2922         case 0x0b: /* ACL connection already exists */
 2923                 return (EEXIST);
 2924 
 2925         case 0x0c: /* Command disallowed */
 2926                 return (EBUSY);
 2927 
 2928         case 0x0d: /* Host rejected due to limited resources */
 2929         case 0x0e: /* Host rejected due to securiity reasons */
 2930         case 0x0f: /* Host rejected due to remote unit is a personal unit */
 2931         case 0x1b: /* SCO offset rejected */
 2932         case 0x1c: /* SCO interval rejected */
 2933         case 0x1d: /* SCO air mode rejected */
 2934                 return (ECONNREFUSED);
 2935 
 2936         case 0x11: /* Unsupported feature or parameter value */
 2937         case 0x19: /* Unknown LMP PDU */
 2938         case 0x1a: /* Unsupported remote feature */
 2939         case 0x20: /* Unsupported LMP parameter value */
 2940         case 0x27: /* QoS is not supported */
 2941         case 0x29: /* Paring with unit key not supported */
 2942                 return (EOPNOTSUPP);
 2943 
 2944         case 0x12: /* Invalid HCI command parameter */
 2945         case 0x1e: /* Invalid LMP parameters */
 2946                 return (EINVAL);
 2947 
 2948         case 0x13: /* Other end terminated connection: User ended connection */
 2949         case 0x14: /* Other end terminated connection: Low resources */
 2950         case 0x15: /* Other end terminated connection: About to power off */
 2951                 return (ECONNRESET);
 2952 
 2953         case 0x16: /* Connection terminated by local host */
 2954                 return (ECONNABORTED);
 2955 
 2956 #if 0 /* XXX not yet */
 2957         case 0x17: /* Repeated attempts */
 2958         case 0x1f: /* Unspecified error */
 2959         case 0x23: /* LMP error transaction collision */
 2960         case 0x28: /* Instant passed */
 2961 #endif
 2962         }
 2963 
 2964         return (ENOSYS);
 2965 } /* ng_btsocket_l2cap_result2errno */

Cache object: 960049e237e2c26cec002bc6aa6ae633


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