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_hci_raw.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_hci_raw.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_hci_raw.c,v 1.14 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/priv.h>
   50 #include <sys/protosw.h>
   51 #include <sys/queue.h>
   52 #include <sys/socket.h>
   53 #include <sys/socketvar.h>
   54 #include <sys/sysctl.h>
   55 #include <sys/taskqueue.h>
   56 
   57 #include <net/vnet.h>
   58 
   59 #include <netgraph/ng_message.h>
   60 #include <netgraph/netgraph.h>
   61 #include <netgraph/bluetooth/include/ng_bluetooth.h>
   62 #include <netgraph/bluetooth/include/ng_hci.h>
   63 #include <netgraph/bluetooth/include/ng_l2cap.h>
   64 #include <netgraph/bluetooth/include/ng_btsocket.h>
   65 #include <netgraph/bluetooth/include/ng_btsocket_hci_raw.h>
   66 
   67 /* MALLOC define */
   68 #ifdef NG_SEPARATE_MALLOC
   69 static MALLOC_DEFINE(M_NETGRAPH_BTSOCKET_HCI_RAW, "netgraph_btsocks_hci_raw",
   70         "Netgraph Bluetooth raw HCI sockets");
   71 #else
   72 #define M_NETGRAPH_BTSOCKET_HCI_RAW M_NETGRAPH
   73 #endif /* NG_SEPARATE_MALLOC */
   74 
   75 /* Netgraph node methods */
   76 static ng_constructor_t ng_btsocket_hci_raw_node_constructor;
   77 static ng_rcvmsg_t      ng_btsocket_hci_raw_node_rcvmsg;
   78 static ng_shutdown_t    ng_btsocket_hci_raw_node_shutdown;
   79 static ng_newhook_t     ng_btsocket_hci_raw_node_newhook;
   80 static ng_connect_t     ng_btsocket_hci_raw_node_connect;
   81 static ng_rcvdata_t     ng_btsocket_hci_raw_node_rcvdata;
   82 static ng_disconnect_t  ng_btsocket_hci_raw_node_disconnect;
   83 
   84 static void             ng_btsocket_hci_raw_input (void *, int);
   85 static void             ng_btsocket_hci_raw_output(node_p, hook_p, void *, int);
   86 static void             ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p, 
   87                                                    struct mbuf **,
   88                                                    struct mbuf *); 
   89 static int              ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p,
   90                                                    struct mbuf *, int);
   91 
   92 #define ng_btsocket_hci_raw_wakeup_input_task() \
   93         taskqueue_enqueue(taskqueue_swi, &ng_btsocket_hci_raw_task)
   94 
   95 /* Security filter */
   96 struct ng_btsocket_hci_raw_sec_filter {
   97         bitstr_t        bit_decl(events, 0xff);
   98         bitstr_t        bit_decl(commands[0x3f], 0x3ff);
   99 };
  100 
  101 /* Netgraph type descriptor */
  102 static struct ng_type typestruct = {
  103         .version =      NG_ABI_VERSION,
  104         .name =         NG_BTSOCKET_HCI_RAW_NODE_TYPE,
  105         .constructor =  ng_btsocket_hci_raw_node_constructor,
  106         .rcvmsg =       ng_btsocket_hci_raw_node_rcvmsg,
  107         .shutdown =     ng_btsocket_hci_raw_node_shutdown,
  108         .newhook =      ng_btsocket_hci_raw_node_newhook,
  109         .connect =      ng_btsocket_hci_raw_node_connect,
  110         .rcvdata =      ng_btsocket_hci_raw_node_rcvdata,
  111         .disconnect =   ng_btsocket_hci_raw_node_disconnect,
  112 };
  113 
  114 /* Globals */
  115 static u_int32_t                                ng_btsocket_hci_raw_debug_level;
  116 static u_int32_t                                ng_btsocket_hci_raw_ioctl_timeout;
  117 static node_p                                   ng_btsocket_hci_raw_node;
  118 static struct ng_bt_itemq                       ng_btsocket_hci_raw_queue;
  119 static struct mtx                               ng_btsocket_hci_raw_queue_mtx;
  120 static struct task                              ng_btsocket_hci_raw_task;
  121 static LIST_HEAD(, ng_btsocket_hci_raw_pcb)     ng_btsocket_hci_raw_sockets;
  122 static struct mtx                               ng_btsocket_hci_raw_sockets_mtx;
  123 static u_int32_t                                ng_btsocket_hci_raw_token;
  124 static struct mtx                               ng_btsocket_hci_raw_token_mtx;
  125 static struct ng_btsocket_hci_raw_sec_filter    *ng_btsocket_hci_raw_sec_filter;
  126 static struct timeval                           ng_btsocket_hci_raw_lasttime;
  127 static int                                      ng_btsocket_hci_raw_curpps;
  128 
  129 /* Sysctl tree */
  130 SYSCTL_DECL(_net_bluetooth_hci_sockets);
  131 static SYSCTL_NODE(_net_bluetooth_hci_sockets, OID_AUTO, raw,
  132     CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
  133     "Bluetooth raw HCI sockets family");
  134 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, debug_level, CTLFLAG_RW,
  135         &ng_btsocket_hci_raw_debug_level, NG_BTSOCKET_WARN_LEVEL,
  136         "Bluetooth raw HCI sockets debug level");
  137 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, ioctl_timeout, CTLFLAG_RW,
  138         &ng_btsocket_hci_raw_ioctl_timeout, 5,
  139         "Bluetooth raw HCI sockets ioctl timeout");
  140 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_len, CTLFLAG_RD,
  141         &ng_btsocket_hci_raw_queue.len, 0,
  142         "Bluetooth raw HCI sockets input queue length");
  143 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_maxlen, CTLFLAG_RD,
  144         &ng_btsocket_hci_raw_queue.maxlen, 0,
  145         "Bluetooth raw HCI sockets input queue max. length");
  146 SYSCTL_UINT(_net_bluetooth_hci_sockets_raw, OID_AUTO, queue_drops, CTLFLAG_RD,
  147         &ng_btsocket_hci_raw_queue.drops, 0,
  148         "Bluetooth raw HCI sockets input queue drops");
  149 
  150 /* Debug */
  151 #define NG_BTSOCKET_HCI_RAW_INFO \
  152         if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_INFO_LEVEL && \
  153             ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \
  154                 printf
  155 
  156 #define NG_BTSOCKET_HCI_RAW_WARN \
  157         if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_WARN_LEVEL && \
  158             ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \
  159                 printf
  160 
  161 #define NG_BTSOCKET_HCI_RAW_ERR \
  162         if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ERR_LEVEL && \
  163             ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \
  164                 printf
  165 
  166 #define NG_BTSOCKET_HCI_RAW_ALERT \
  167         if (ng_btsocket_hci_raw_debug_level >= NG_BTSOCKET_ALERT_LEVEL && \
  168             ppsratecheck(&ng_btsocket_hci_raw_lasttime, &ng_btsocket_hci_raw_curpps, 1)) \
  169                 printf
  170 
  171 /****************************************************************************
  172  ****************************************************************************
  173  **                          Netgraph specific
  174  ****************************************************************************
  175  ****************************************************************************/
  176 
  177 /*
  178  * Netgraph node constructor. Do not allow to create node of this type.
  179  */
  180 
  181 static int
  182 ng_btsocket_hci_raw_node_constructor(node_p node)
  183 {
  184         return (EINVAL);
  185 } /* ng_btsocket_hci_raw_node_constructor */
  186 
  187 /*
  188  * Netgraph node destructor. Just let old node go and create new fresh one.
  189  */
  190 
  191 static int
  192 ng_btsocket_hci_raw_node_shutdown(node_p node)
  193 {
  194         int     error = 0;
  195 
  196         NG_NODE_UNREF(node);
  197 
  198         error = ng_make_node_common(&typestruct, &ng_btsocket_hci_raw_node);
  199         if (error  != 0) {
  200                 NG_BTSOCKET_HCI_RAW_ALERT(
  201 "%s: Could not create Netgraph node, error=%d\n", __func__, error);
  202 
  203                 ng_btsocket_hci_raw_node = NULL;
  204 
  205                 return (ENOMEM);
  206         }
  207 
  208         error = ng_name_node(ng_btsocket_hci_raw_node,
  209                                 NG_BTSOCKET_HCI_RAW_NODE_TYPE);
  210         if (error != 0) {
  211                 NG_BTSOCKET_HCI_RAW_ALERT(
  212 "%s: Could not name Netgraph node, error=%d\n", __func__, error);
  213 
  214                 NG_NODE_UNREF(ng_btsocket_hci_raw_node);
  215                 ng_btsocket_hci_raw_node = NULL;
  216 
  217                 return (EINVAL);
  218         }
  219 
  220         return (0);
  221 } /* ng_btsocket_hci_raw_node_shutdown */
  222 
  223 /*
  224  * Create new hook. Just say "yes"
  225  */
  226 
  227 static int
  228 ng_btsocket_hci_raw_node_newhook(node_p node, hook_p hook, char const *name)
  229 {
  230         return (0);
  231 } /* ng_btsocket_hci_raw_node_newhook */
  232 
  233 /*
  234  * Connect hook. Just say "yes"
  235  */
  236 
  237 static int
  238 ng_btsocket_hci_raw_node_connect(hook_p hook)
  239 {
  240         return (0);
  241 } /* ng_btsocket_hci_raw_node_connect */
  242 
  243 /*
  244  * Disconnect hook
  245  */
  246 
  247 static int
  248 ng_btsocket_hci_raw_node_disconnect(hook_p hook)
  249 {
  250         return (0);
  251 } /* ng_btsocket_hci_raw_node_disconnect */
  252 
  253 /*
  254  * Receive control message.
  255  * Make sure it is a message from HCI node and it is a response.
  256  * Enqueue item and schedule input task.
  257  */
  258 
  259 static int
  260 ng_btsocket_hci_raw_node_rcvmsg(node_p node, item_p item, hook_p lasthook) 
  261 {
  262         struct ng_mesg  *msg = NGI_MSG(item); /* item still has message */
  263         int              error = 0;
  264 
  265         /*
  266          * Check for empty sockets list creates LOR when both sender and
  267          * receiver device are connected to the same host, so remove it
  268          * for now
  269          */
  270 
  271         if (msg != NULL &&
  272             (msg->header.typecookie == NGM_HCI_COOKIE ||
  273              msg->header.typecookie == NGM_GENERIC_COOKIE) &&
  274             msg->header.flags & NGF_RESP) {
  275                 if (msg->header.token == 0) {
  276                         NG_FREE_ITEM(item);
  277                         return (0);
  278                 }
  279 
  280                 mtx_lock(&ng_btsocket_hci_raw_queue_mtx);
  281                 if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue)) {
  282                         NG_BTSOCKET_HCI_RAW_ERR(
  283 "%s: Input queue is full\n", __func__);
  284 
  285                         NG_BT_ITEMQ_DROP(&ng_btsocket_hci_raw_queue);
  286                         NG_FREE_ITEM(item);
  287                         error = ENOBUFS;
  288                 } else {
  289                         NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue, item);
  290                         error = ng_btsocket_hci_raw_wakeup_input_task();
  291                 }
  292                 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx);
  293         } else {
  294                 NG_FREE_ITEM(item);
  295                 error = EINVAL;
  296         }
  297 
  298         return (error);
  299 } /* ng_btsocket_hci_raw_node_rcvmsg */
  300 
  301 /*
  302  * Receive packet from the one of our hook.
  303  * Prepend every packet with sockaddr_hci and record sender's node name.
  304  * Enqueue item and schedule input task.
  305  */
  306 
  307 static int
  308 ng_btsocket_hci_raw_node_rcvdata(hook_p hook, item_p item)
  309 {
  310         struct mbuf     *nam = NULL;
  311         int              error;
  312 
  313         /*
  314          * Check for empty sockets list creates LOR when both sender and
  315          * receiver device are connected to the same host, so remove it
  316          * for now
  317          */
  318 
  319         MGET(nam, M_NOWAIT, MT_SONAME);
  320         if (nam != NULL) {
  321                 struct sockaddr_hci     *sa = mtod(nam, struct sockaddr_hci *);
  322 
  323                 nam->m_len = sizeof(struct sockaddr_hci);
  324 
  325                 sa->hci_len = sizeof(*sa);
  326                 sa->hci_family = AF_BLUETOOTH;
  327                 strlcpy(sa->hci_node, NG_PEER_NODE_NAME(hook),
  328                         sizeof(sa->hci_node));
  329 
  330                 NGI_GET_M(item, nam->m_next);
  331                 NGI_M(item) = nam;
  332 
  333                 mtx_lock(&ng_btsocket_hci_raw_queue_mtx);
  334                 if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue)) {
  335                         NG_BTSOCKET_HCI_RAW_ERR(
  336 "%s: Input queue is full\n", __func__);
  337 
  338                         NG_BT_ITEMQ_DROP(&ng_btsocket_hci_raw_queue);
  339                         NG_FREE_ITEM(item);
  340                         error = ENOBUFS;
  341                 } else {
  342                         NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue, item);
  343                         error = ng_btsocket_hci_raw_wakeup_input_task();
  344                 }
  345                 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx);
  346         } else {
  347                 NG_BTSOCKET_HCI_RAW_ERR(
  348 "%s: Failed to allocate address mbuf\n", __func__);
  349 
  350                 NG_FREE_ITEM(item);
  351                 error = ENOBUFS;
  352         }
  353 
  354         return (error);
  355 } /* ng_btsocket_hci_raw_node_rcvdata */
  356 
  357 /****************************************************************************
  358  ****************************************************************************
  359  **                              Sockets specific
  360  ****************************************************************************
  361  ****************************************************************************/
  362 
  363 /*
  364  * Get next token. We need token to avoid theoretical race where process
  365  * submits ioctl() message then interrupts ioctl() and re-submits another
  366  * ioctl() on the same socket *before* first ioctl() complete.
  367  */
  368 
  369 static void
  370 ng_btsocket_hci_raw_get_token(u_int32_t *token)
  371 {
  372         mtx_lock(&ng_btsocket_hci_raw_token_mtx);
  373   
  374         if (++ ng_btsocket_hci_raw_token == 0)
  375                 ng_btsocket_hci_raw_token = 1;
  376 
  377         *token = ng_btsocket_hci_raw_token;
  378 
  379         mtx_unlock(&ng_btsocket_hci_raw_token_mtx);
  380 } /* ng_btsocket_hci_raw_get_token */
  381 
  382 /*
  383  * Send Netgraph message to the node - do not expect reply
  384  */
  385 
  386 static int
  387 ng_btsocket_hci_raw_send_ngmsg(char *path, int cmd, void *arg, int arglen)
  388 {
  389         struct ng_mesg  *msg = NULL;
  390         int              error = 0;
  391 
  392         NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, arglen, M_NOWAIT);
  393         if (msg == NULL)
  394                 return (ENOMEM);
  395 
  396         if (arg != NULL && arglen > 0)
  397                 bcopy(arg, msg->data, arglen);
  398 
  399         NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0);
  400 
  401         return (error);
  402 } /* ng_btsocket_hci_raw_send_ngmsg */
  403 
  404 /*
  405  * Send Netgraph message to the node (no data) and wait for reply 
  406  */
  407 
  408 static int
  409 ng_btsocket_hci_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb, char *path,
  410                 int cmd, void *rsp, int rsplen)
  411 {
  412         struct ng_mesg  *msg = NULL;
  413         int              error = 0;
  414 
  415         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
  416 
  417         NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, 0, M_NOWAIT);
  418         if (msg == NULL)
  419                 return (ENOMEM);
  420 
  421         ng_btsocket_hci_raw_get_token(&msg->header.token);
  422         pcb->token = msg->header.token;
  423         pcb->msg = NULL;
  424 
  425         NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0);
  426         if (error != 0) {
  427                 pcb->token = 0;
  428                 return (error);
  429         }
  430 
  431         error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "hcictl", 
  432                         ng_btsocket_hci_raw_ioctl_timeout * hz);
  433         pcb->token = 0;
  434 
  435         if (error != 0)
  436                 return (error);
  437 
  438         if (pcb->msg != NULL && pcb->msg->header.cmd == cmd)
  439                 bcopy(pcb->msg->data, rsp, rsplen);
  440         else
  441                 error = EINVAL;
  442 
  443         NG_FREE_MSG(pcb->msg); /* checks for != NULL */
  444 
  445         return (0);
  446 } /* ng_btsocket_hci_raw_send_sync_ngmsg */
  447 
  448 /*
  449  * Create control information for the packet
  450  */
  451 
  452 static void
  453 ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p pcb, struct mbuf **ctl,
  454                 struct mbuf *m) 
  455 {
  456         int             dir;
  457         struct timeval  tv;
  458 
  459         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
  460 
  461         if (pcb->flags & NG_BTSOCKET_HCI_RAW_DIRECTION) {
  462                 dir = (m->m_flags & M_PROTO1)? 1 : 0;
  463                 *ctl = sbcreatecontrol(&dir, sizeof(dir),
  464                     SCM_HCI_RAW_DIRECTION, SOL_HCI_RAW, M_NOWAIT);
  465                 if (*ctl != NULL)
  466                         ctl = &((*ctl)->m_next);
  467         }
  468 
  469         if (pcb->so->so_options & SO_TIMESTAMP) {
  470                 microtime(&tv);
  471                 *ctl = sbcreatecontrol(&tv, sizeof(tv), SCM_TIMESTAMP,
  472                     SOL_SOCKET, M_NOWAIT);
  473                 if (*ctl != NULL)
  474                         ctl = &((*ctl)->m_next);
  475         }
  476 } /* ng_btsocket_hci_raw_savctl */
  477 
  478 /*
  479  * Raw HCI sockets data input routine
  480  */
  481 
  482 static void
  483 ng_btsocket_hci_raw_data_input(struct mbuf *nam)
  484 {
  485         ng_btsocket_hci_raw_pcb_p        pcb = NULL;
  486         struct mbuf                     *m0 = NULL, *m = NULL;
  487         struct sockaddr_hci             *sa = NULL;
  488 
  489         m0 = nam->m_next;
  490         nam->m_next = NULL;
  491 
  492         KASSERT((nam->m_type == MT_SONAME),
  493                 ("%s: m_type=%d\n", __func__, nam->m_type));
  494         KASSERT((m0->m_flags & M_PKTHDR),
  495                 ("%s: m_flags=%#x\n", __func__, m0->m_flags));
  496 
  497         sa = mtod(nam, struct sockaddr_hci *);
  498 
  499         mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
  500 
  501         LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) {
  502                 mtx_lock(&pcb->pcb_mtx);
  503 
  504                 /*
  505                  * If socket was bound then check address and
  506                  *  make sure it matches.
  507                  */
  508 
  509                 if (pcb->addr.hci_node[0] != 0 &&
  510                     strcmp(sa->hci_node, pcb->addr.hci_node) != 0)
  511                         goto next;
  512 
  513                 /*
  514                  * Check packet against filters
  515                  * XXX do we have to call m_pullup() here?
  516                  */
  517 
  518                 if (ng_btsocket_hci_raw_filter(pcb, m0, 1) != 0)
  519                         goto next;
  520 
  521                 /*
  522                  * Make a copy of the packet, append to the socket's
  523                  * receive queue and wakeup socket. sbappendaddr()
  524                  * will check if socket has enough buffer space.
  525                  */
  526 
  527                 m = m_dup(m0, M_NOWAIT);
  528                 if (m != NULL) {
  529                         struct mbuf     *ctl = NULL;
  530 
  531                         ng_btsocket_hci_raw_savctl(pcb, &ctl, m);
  532 
  533                         if (sbappendaddr(&pcb->so->so_rcv, 
  534                                         (struct sockaddr *) sa, m, ctl))
  535                                 sorwakeup(pcb->so);
  536                         else {
  537                                 NG_BTSOCKET_HCI_RAW_INFO(
  538 "%s: sbappendaddr() failed\n", __func__);
  539 
  540                                 NG_FREE_M(m);
  541                                 NG_FREE_M(ctl);
  542                                 soroverflow(pcb->so);
  543                         }
  544                 }
  545 next:
  546                 mtx_unlock(&pcb->pcb_mtx);
  547         }
  548 
  549         mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
  550 
  551         NG_FREE_M(nam);
  552         NG_FREE_M(m0);
  553 } /* ng_btsocket_hci_raw_data_input */ 
  554 
  555 /*
  556  * Raw HCI sockets message input routine
  557  */
  558 
  559 static void
  560 ng_btsocket_hci_raw_msg_input(struct ng_mesg *msg)
  561 {
  562         ng_btsocket_hci_raw_pcb_p       pcb = NULL;
  563 
  564         mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
  565 
  566         LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) {
  567                 mtx_lock(&pcb->pcb_mtx);
  568 
  569                 if (msg->header.token == pcb->token) {
  570                         pcb->msg = msg;
  571                         wakeup(&pcb->msg);
  572 
  573                         mtx_unlock(&pcb->pcb_mtx);
  574                         mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
  575 
  576                         return;
  577                 }
  578 
  579                 mtx_unlock(&pcb->pcb_mtx);
  580         }
  581 
  582         mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
  583 
  584         NG_FREE_MSG(msg); /* checks for != NULL */
  585 } /* ng_btsocket_hci_raw_msg_input */
  586 
  587 /*
  588  * Raw HCI sockets input routines
  589  */
  590 
  591 static void
  592 ng_btsocket_hci_raw_input(void *context, int pending)
  593 {
  594         item_p  item = NULL;
  595 
  596         for (;;) {
  597                 mtx_lock(&ng_btsocket_hci_raw_queue_mtx);
  598                 NG_BT_ITEMQ_DEQUEUE(&ng_btsocket_hci_raw_queue, item);
  599                 mtx_unlock(&ng_btsocket_hci_raw_queue_mtx);
  600 
  601                 if (item == NULL)
  602                         break;
  603 
  604                 switch(item->el_flags & NGQF_TYPE) {
  605                 case NGQF_DATA: {
  606                         struct mbuf     *m = NULL;
  607 
  608                         NGI_GET_M(item, m);
  609                         ng_btsocket_hci_raw_data_input(m);
  610                         } break;
  611 
  612                 case NGQF_MESG: {
  613                         struct ng_mesg  *msg = NULL;
  614 
  615                         NGI_GET_MSG(item, msg);
  616                         ng_btsocket_hci_raw_msg_input(msg);
  617                         } break;
  618 
  619                 default:
  620                         KASSERT(0, 
  621 ("%s: invalid item type=%ld\n", __func__, (item->el_flags & NGQF_TYPE)));
  622                         break;
  623                 }
  624 
  625                 NG_FREE_ITEM(item);
  626         }
  627 } /* ng_btsocket_hci_raw_input */
  628 
  629 /*
  630  * Raw HCI sockets output routine
  631  */
  632 
  633 static void
  634 ng_btsocket_hci_raw_output(node_p node, hook_p hook, void *arg1, int arg2)
  635 {
  636         struct mbuf             *nam = (struct mbuf *) arg1, *m = NULL;
  637         struct sockaddr_hci     *sa = NULL;
  638         int                      error;
  639 
  640         m = nam->m_next;
  641         nam->m_next = NULL;
  642 
  643         KASSERT((nam->m_type == MT_SONAME),
  644                 ("%s: m_type=%d\n", __func__, nam->m_type));
  645         KASSERT((m->m_flags & M_PKTHDR),
  646                 ("%s: m_flags=%#x\n", __func__, m->m_flags));
  647 
  648         sa = mtod(nam, struct sockaddr_hci *);
  649 
  650         /*
  651          * Find downstream hook
  652          * XXX For now access node hook list directly. Should be safe because
  653          * we used ng_send_fn() and we should have exclusive lock on the node.
  654          */
  655 
  656         LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) {
  657                 if (hook == NULL || NG_HOOK_NOT_VALID(hook) || 
  658                     NG_NODE_NOT_VALID(NG_PEER_NODE(hook)))
  659                         continue;
  660 
  661                 if (strcmp(sa->hci_node, NG_PEER_NODE_NAME(hook)) == 0) {
  662                         NG_SEND_DATA_ONLY(error, hook, m); /* sets m to NULL */
  663                         break;
  664                 }
  665         }
  666 
  667         NG_FREE_M(nam); /* check for != NULL */
  668         NG_FREE_M(m);
  669 } /* ng_btsocket_hci_raw_output */
  670 
  671 /*
  672  * Check frame against security and socket filters. 
  673  * d (direction bit) == 1 means incoming frame.
  674  */
  675 
  676 static int
  677 ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p pcb, struct mbuf *m, int d)
  678 {
  679         int     type, event, opcode;
  680 
  681         mtx_assert(&pcb->pcb_mtx, MA_OWNED);
  682 
  683         switch ((type = *mtod(m, u_int8_t *))) {
  684         case NG_HCI_CMD_PKT:
  685                 if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)) {
  686                         opcode = le16toh(mtod(m, ng_hci_cmd_pkt_t *)->opcode);
  687                 
  688                         if (!bit_test(
  689 ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF(opcode) - 1],
  690 NG_HCI_OCF(opcode) - 1))
  691                                 return (EPERM);
  692                 }
  693 
  694                 if (d && !bit_test(pcb->filter.packet_mask, NG_HCI_CMD_PKT - 1))
  695                         return (EPERM);
  696                 break;
  697 
  698         case NG_HCI_ACL_DATA_PKT:
  699         case NG_HCI_SCO_DATA_PKT:
  700                 if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) ||
  701                     !bit_test(pcb->filter.packet_mask, type - 1) ||
  702                     !d)
  703                         return (EPERM);
  704                 break;
  705 
  706         case NG_HCI_EVENT_PKT:
  707                 if (!d)
  708                         return (EINVAL);
  709 
  710                 event = mtod(m, ng_hci_event_pkt_t *)->event - 1;
  711 
  712                 if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED))
  713                         if (!bit_test(ng_btsocket_hci_raw_sec_filter->events, event))
  714                                 return (EPERM);
  715 
  716                 if (!bit_test(pcb->filter.event_mask, event))
  717                         return (EPERM);
  718                 break;
  719 
  720         default:
  721                 return (EINVAL);
  722         }
  723 
  724         return (0);
  725 } /* ng_btsocket_hci_raw_filter */
  726 
  727 /*
  728  * Initialize everything
  729  */
  730 
  731 static void
  732 ng_btsocket_hci_raw_init(void *arg __unused)
  733 {
  734         bitstr_t        *f = NULL;
  735         int              error = 0;
  736 
  737         ng_btsocket_hci_raw_node = NULL;
  738         ng_btsocket_hci_raw_debug_level = NG_BTSOCKET_WARN_LEVEL;
  739         ng_btsocket_hci_raw_ioctl_timeout = 5;
  740 
  741         /* Register Netgraph node type */
  742         error = ng_newtype(&typestruct);
  743         if (error != 0) {
  744                 NG_BTSOCKET_HCI_RAW_ALERT(
  745 "%s: Could not register Netgraph node type, error=%d\n", __func__, error);
  746 
  747                 return;
  748         }
  749 
  750         /* Create Netgrapg node */
  751         error = ng_make_node_common(&typestruct, &ng_btsocket_hci_raw_node);
  752         if (error != 0) {
  753                 NG_BTSOCKET_HCI_RAW_ALERT(
  754 "%s: Could not create Netgraph node, error=%d\n", __func__, error);
  755 
  756                 ng_btsocket_hci_raw_node = NULL;
  757 
  758                 return;
  759         }
  760 
  761         error = ng_name_node(ng_btsocket_hci_raw_node,
  762                                 NG_BTSOCKET_HCI_RAW_NODE_TYPE);
  763         if (error != 0) {
  764                 NG_BTSOCKET_HCI_RAW_ALERT(
  765 "%s: Could not name Netgraph node, error=%d\n", __func__, error);
  766 
  767                 NG_NODE_UNREF(ng_btsocket_hci_raw_node);
  768                 ng_btsocket_hci_raw_node = NULL;
  769 
  770                 return;
  771         }
  772 
  773         /* Create input queue */
  774         NG_BT_ITEMQ_INIT(&ng_btsocket_hci_raw_queue, 300);
  775         mtx_init(&ng_btsocket_hci_raw_queue_mtx,
  776                 "btsocks_hci_raw_queue_mtx", NULL, MTX_DEF);
  777         TASK_INIT(&ng_btsocket_hci_raw_task, 0,
  778                 ng_btsocket_hci_raw_input, NULL);
  779 
  780         /* Create list of sockets */
  781         LIST_INIT(&ng_btsocket_hci_raw_sockets);
  782         mtx_init(&ng_btsocket_hci_raw_sockets_mtx,
  783                 "btsocks_hci_raw_sockets_mtx", NULL, MTX_DEF);
  784 
  785         /* Tokens */
  786         ng_btsocket_hci_raw_token = 0;
  787         mtx_init(&ng_btsocket_hci_raw_token_mtx,
  788                 "btsocks_hci_raw_token_mtx", NULL, MTX_DEF);
  789 
  790         /* 
  791          * Security filter
  792          * XXX never free()ed
  793          */
  794         ng_btsocket_hci_raw_sec_filter =
  795             malloc(sizeof(struct ng_btsocket_hci_raw_sec_filter), 
  796                 M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO);
  797         if (ng_btsocket_hci_raw_sec_filter == NULL) {
  798                 printf("%s: Could not allocate security filter!\n", __func__);
  799                 return;
  800         }
  801 
  802         /*
  803          * XXX How paranoid can we get? 
  804          *
  805          * Initialize security filter. If bit is set in the mask then
  806          * unprivileged socket is allowed to send (receive) this command
  807          * (event).
  808          */
  809 
  810         /* Enable all events */
  811         memset(&ng_btsocket_hci_raw_sec_filter->events, 0xff,
  812                 sizeof(ng_btsocket_hci_raw_sec_filter->events)/
  813                         sizeof(ng_btsocket_hci_raw_sec_filter->events[0]));
  814 
  815         /* Disable some critical events */
  816         f = ng_btsocket_hci_raw_sec_filter->events;
  817         bit_clear(f, NG_HCI_EVENT_RETURN_LINK_KEYS - 1);
  818         bit_clear(f, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
  819         bit_clear(f, NG_HCI_EVENT_VENDOR - 1);
  820 
  821         /* Commands - Link control */
  822         f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LINK_CONTROL-1];
  823         bit_set(f, NG_HCI_OCF_INQUIRY - 1);
  824         bit_set(f, NG_HCI_OCF_INQUIRY_CANCEL - 1);
  825         bit_set(f, NG_HCI_OCF_PERIODIC_INQUIRY - 1);
  826         bit_set(f, NG_HCI_OCF_EXIT_PERIODIC_INQUIRY - 1);
  827         bit_set(f, NG_HCI_OCF_REMOTE_NAME_REQ - 1);
  828         bit_set(f, NG_HCI_OCF_READ_REMOTE_FEATURES - 1);
  829         bit_set(f, NG_HCI_OCF_READ_REMOTE_VER_INFO - 1);
  830         bit_set(f, NG_HCI_OCF_READ_CLOCK_OFFSET - 1);
  831 
  832         /* Commands - Link policy */
  833         f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LINK_POLICY-1];
  834         bit_set(f, NG_HCI_OCF_ROLE_DISCOVERY - 1);
  835         bit_set(f, NG_HCI_OCF_READ_LINK_POLICY_SETTINGS - 1);
  836 
  837         /* Commands - Host controller and baseband */
  838         f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_HC_BASEBAND-1];
  839         bit_set(f, NG_HCI_OCF_READ_PIN_TYPE - 1);
  840         bit_set(f, NG_HCI_OCF_READ_LOCAL_NAME - 1);
  841         bit_set(f, NG_HCI_OCF_READ_CON_ACCEPT_TIMO - 1);
  842         bit_set(f, NG_HCI_OCF_READ_PAGE_TIMO - 1);
  843         bit_set(f, NG_HCI_OCF_READ_SCAN_ENABLE - 1);
  844         bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY - 1);
  845         bit_set(f, NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY - 1);
  846         bit_set(f, NG_HCI_OCF_READ_AUTH_ENABLE - 1);
  847         bit_set(f, NG_HCI_OCF_READ_ENCRYPTION_MODE - 1);
  848         bit_set(f, NG_HCI_OCF_READ_UNIT_CLASS - 1);
  849         bit_set(f, NG_HCI_OCF_READ_VOICE_SETTINGS - 1);
  850         bit_set(f, NG_HCI_OCF_READ_AUTO_FLUSH_TIMO - 1);
  851         bit_set(f, NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS - 1);
  852         bit_set(f, NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY - 1);
  853         bit_set(f, NG_HCI_OCF_READ_XMIT_LEVEL - 1);
  854         bit_set(f, NG_HCI_OCF_READ_SCO_FLOW_CONTROL - 1);
  855         bit_set(f, NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO - 1);
  856         bit_set(f, NG_HCI_OCF_READ_SUPPORTED_IAC_NUM - 1);
  857         bit_set(f, NG_HCI_OCF_READ_IAC_LAP - 1);
  858         bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN_PERIOD - 1);
  859         bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN - 1);
  860         bit_set(f, NG_HCI_OCF_READ_LE_HOST_SUPPORTED -1);
  861 
  862         /* Commands - Informational */
  863         f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_INFO - 1];
  864         bit_set(f, NG_HCI_OCF_READ_LOCAL_VER - 1);
  865         bit_set(f, NG_HCI_OCF_READ_LOCAL_FEATURES - 1);
  866         bit_set(f, NG_HCI_OCF_READ_BUFFER_SIZE - 1);
  867         bit_set(f, NG_HCI_OCF_READ_COUNTRY_CODE - 1);
  868         bit_set(f, NG_HCI_OCF_READ_BDADDR - 1);
  869 
  870         /* Commands - Status */
  871         f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_STATUS - 1];
  872         bit_set(f, NG_HCI_OCF_READ_FAILED_CONTACT_CNTR - 1);
  873         bit_set(f, NG_HCI_OCF_GET_LINK_QUALITY - 1);
  874         bit_set(f, NG_HCI_OCF_READ_RSSI - 1);
  875 
  876         /* Commands - Testing */
  877         f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_TESTING - 1];
  878         bit_set(f, NG_HCI_OCF_READ_LOOPBACK_MODE - 1);
  879         /*Commands - LE*/
  880         f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LE -1];
  881         bit_set(f, NG_HCI_OCF_LE_SET_SCAN_ENABLE - 1);
  882         bit_set(f, NG_HCI_OCF_LE_SET_SCAN_PARAMETERS - 1);
  883         bit_set(f, NG_HCI_OCF_LE_READ_LOCAL_SUPPORTED_FEATURES - 1);
  884         bit_set(f, NG_HCI_OCF_LE_READ_BUFFER_SIZE - 1);
  885         bit_set(f, NG_HCI_OCF_LE_READ_WHITE_LIST_SIZE - 1);
  886 
  887 } /* ng_btsocket_hci_raw_init */
  888 SYSINIT(ng_btsocket_hci_raw_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
  889     ng_btsocket_hci_raw_init, NULL);
  890 
  891 /*
  892  * Abort connection on socket
  893  */
  894 
  895 void
  896 ng_btsocket_hci_raw_abort(struct socket *so)
  897 {
  898 } /* ng_btsocket_hci_raw_abort */
  899 
  900 void
  901 ng_btsocket_hci_raw_close(struct socket *so)
  902 {
  903 } /* ng_btsocket_hci_raw_close */
  904 
  905 /*
  906  * Create new raw HCI socket
  907  */
  908 
  909 int
  910 ng_btsocket_hci_raw_attach(struct socket *so, int proto, struct thread *td)
  911 {
  912         ng_btsocket_hci_raw_pcb_p       pcb = so2hci_raw_pcb(so);
  913         int                             error = 0;
  914 
  915         if (pcb != NULL)
  916                 return (EISCONN);
  917 
  918         if (ng_btsocket_hci_raw_node == NULL)
  919                 return (EPROTONOSUPPORT);
  920         if (proto != BLUETOOTH_PROTO_HCI)
  921                 return (EPROTONOSUPPORT);
  922         if (so->so_type != SOCK_RAW)
  923                 return (ESOCKTNOSUPPORT);
  924 
  925         error = soreserve(so, NG_BTSOCKET_HCI_RAW_SENDSPACE,
  926                                 NG_BTSOCKET_HCI_RAW_RECVSPACE);
  927         if (error != 0)
  928                 return (error);
  929 
  930         pcb = malloc(sizeof(*pcb), 
  931                 M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO);
  932         if (pcb == NULL)
  933                 return (ENOMEM);
  934 
  935         so->so_pcb = (caddr_t) pcb;
  936         pcb->so = so;
  937 
  938         if (priv_check(td, PRIV_NETBLUETOOTH_RAW) == 0)
  939                 pcb->flags |= NG_BTSOCKET_HCI_RAW_PRIVILEGED;
  940 
  941         /*
  942          * Set default socket filter. By default socket only accepts HCI
  943          * Command_Complete and Command_Status event packets.
  944          */
  945 
  946         bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_COMPL - 1);
  947         bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_STATUS - 1);
  948 
  949         mtx_init(&pcb->pcb_mtx, "btsocks_hci_raw_pcb_mtx", NULL, MTX_DEF);
  950 
  951         mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
  952         LIST_INSERT_HEAD(&ng_btsocket_hci_raw_sockets, pcb, next);
  953         mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
  954 
  955         return (0);
  956 } /* ng_btsocket_hci_raw_attach */
  957 
  958 /*
  959  * Bind raw HCI socket
  960  */
  961 
  962 int
  963 ng_btsocket_hci_raw_bind(struct socket *so, struct sockaddr *nam,
  964                 struct thread *td)
  965 {
  966         ng_btsocket_hci_raw_pcb_p        pcb = so2hci_raw_pcb(so);
  967         struct sockaddr_hci             *sa = (struct sockaddr_hci *) nam;
  968 
  969         if (pcb == NULL)
  970                 return (EINVAL);
  971         if (ng_btsocket_hci_raw_node == NULL)
  972                 return (EINVAL);
  973 
  974         if (sa == NULL)
  975                 return (EINVAL);
  976         if (sa->hci_family != AF_BLUETOOTH)
  977                 return (EAFNOSUPPORT);
  978         if (sa->hci_len != sizeof(*sa))
  979                 return (EINVAL);
  980         if (sa->hci_node[0] == 0)
  981                 return (EINVAL);
  982 
  983         mtx_lock(&pcb->pcb_mtx);
  984         bcopy(sa, &pcb->addr, sizeof(pcb->addr));
  985         mtx_unlock(&pcb->pcb_mtx);
  986 
  987         return (0);
  988 } /* ng_btsocket_hci_raw_bind */
  989 
  990 /*
  991  * Connect raw HCI socket
  992  */
  993 
  994 int
  995 ng_btsocket_hci_raw_connect(struct socket *so, struct sockaddr *nam,
  996                 struct thread *td)
  997 {
  998         ng_btsocket_hci_raw_pcb_p        pcb = so2hci_raw_pcb(so);
  999         struct sockaddr_hci             *sa = (struct sockaddr_hci *) nam;
 1000 
 1001         if (pcb == NULL)
 1002                 return (EINVAL);
 1003         if (ng_btsocket_hci_raw_node == NULL)
 1004                 return (EINVAL);
 1005 
 1006         if (sa == NULL)
 1007                 return (EINVAL);
 1008         if (sa->hci_family != AF_BLUETOOTH)
 1009                 return (EAFNOSUPPORT);
 1010         if (sa->hci_len != sizeof(*sa))
 1011                 return (EINVAL);
 1012         if (sa->hci_node[0] == 0)
 1013                 return (EDESTADDRREQ);
 1014 
 1015         mtx_lock(&pcb->pcb_mtx);
 1016 
 1017         if (bcmp(sa, &pcb->addr, sizeof(pcb->addr)) != 0) {
 1018                 mtx_unlock(&pcb->pcb_mtx);
 1019                 return (EADDRNOTAVAIL);
 1020         }
 1021 
 1022         soisconnected(so);
 1023 
 1024         mtx_unlock(&pcb->pcb_mtx);
 1025 
 1026         return (0);
 1027 } /* ng_btsocket_hci_raw_connect */
 1028 
 1029 /*
 1030  * Process ioctl on socket
 1031  */
 1032 
 1033 int
 1034 ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, void *data,
 1035                 struct ifnet *ifp, struct thread *td)
 1036 {
 1037         ng_btsocket_hci_raw_pcb_p        pcb = so2hci_raw_pcb(so);
 1038         char                             path[NG_NODESIZ + 1];
 1039         struct ng_mesg                  *msg = NULL;
 1040         int                              error = 0;
 1041 
 1042         if (pcb == NULL)
 1043                 return (EINVAL);
 1044         if (ng_btsocket_hci_raw_node == NULL)
 1045                 return (EINVAL);
 1046 
 1047         mtx_lock(&pcb->pcb_mtx);
 1048 
 1049         /* Check if we have device name */
 1050         if (pcb->addr.hci_node[0] == 0) {
 1051                 mtx_unlock(&pcb->pcb_mtx);
 1052                 return (EHOSTUNREACH);
 1053         }
 1054 
 1055         /* Check if we have pending ioctl() */
 1056         if (pcb->token != 0) {
 1057                 mtx_unlock(&pcb->pcb_mtx);
 1058                 return (EBUSY);
 1059         }
 1060 
 1061         snprintf(path, sizeof(path), "%s:", pcb->addr.hci_node);
 1062 
 1063         switch (cmd) {
 1064         case SIOC_HCI_RAW_NODE_GET_STATE: {
 1065                 struct ng_btsocket_hci_raw_node_state   *p =
 1066                         (struct ng_btsocket_hci_raw_node_state *) data;
 1067 
 1068                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path, 
 1069                                 NGM_HCI_NODE_GET_STATE,
 1070                                 &p->state, sizeof(p->state));
 1071                 } break;
 1072 
 1073         case SIOC_HCI_RAW_NODE_INIT:
 1074                 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
 1075                         error = ng_btsocket_hci_raw_send_ngmsg(path,
 1076                                         NGM_HCI_NODE_INIT, NULL, 0);
 1077                 else
 1078                         error = EPERM;
 1079                 break;
 1080 
 1081         case SIOC_HCI_RAW_NODE_GET_DEBUG: {
 1082                 struct ng_btsocket_hci_raw_node_debug   *p = 
 1083                         (struct ng_btsocket_hci_raw_node_debug *) data;
 1084 
 1085                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
 1086                                 NGM_HCI_NODE_GET_DEBUG,
 1087                                 &p->debug, sizeof(p->debug));
 1088                 } break;
 1089 
 1090         case SIOC_HCI_RAW_NODE_SET_DEBUG: {
 1091                 struct ng_btsocket_hci_raw_node_debug   *p = 
 1092                         (struct ng_btsocket_hci_raw_node_debug *) data;
 1093 
 1094                 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
 1095                         error = ng_btsocket_hci_raw_send_ngmsg(path,
 1096                                         NGM_HCI_NODE_SET_DEBUG, &p->debug,
 1097                                         sizeof(p->debug));
 1098                 else
 1099                         error = EPERM;
 1100                 } break;
 1101 
 1102         case SIOC_HCI_RAW_NODE_GET_BUFFER: {
 1103                 struct ng_btsocket_hci_raw_node_buffer  *p = 
 1104                         (struct ng_btsocket_hci_raw_node_buffer *) data;
 1105 
 1106                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
 1107                                 NGM_HCI_NODE_GET_BUFFER,
 1108                                 &p->buffer, sizeof(p->buffer));
 1109                 } break;
 1110 
 1111         case SIOC_HCI_RAW_NODE_GET_BDADDR: {
 1112                 struct ng_btsocket_hci_raw_node_bdaddr  *p = 
 1113                         (struct ng_btsocket_hci_raw_node_bdaddr *) data;
 1114 
 1115                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
 1116                                 NGM_HCI_NODE_GET_BDADDR,
 1117                                 &p->bdaddr, sizeof(p->bdaddr));
 1118                 } break;
 1119 
 1120         case SIOC_HCI_RAW_NODE_GET_FEATURES: {
 1121                 struct ng_btsocket_hci_raw_node_features        *p = 
 1122                         (struct ng_btsocket_hci_raw_node_features *) data;
 1123 
 1124                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
 1125                                 NGM_HCI_NODE_GET_FEATURES,
 1126                                 &p->features, sizeof(p->features));
 1127                 } break;
 1128 
 1129         case SIOC_HCI_RAW_NODE_GET_STAT: {
 1130                 struct ng_btsocket_hci_raw_node_stat    *p = 
 1131                         (struct ng_btsocket_hci_raw_node_stat *) data;
 1132 
 1133                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
 1134                                 NGM_HCI_NODE_GET_STAT,
 1135                                 &p->stat, sizeof(p->stat));
 1136                 } break;
 1137 
 1138         case SIOC_HCI_RAW_NODE_RESET_STAT:
 1139                 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
 1140                         error = ng_btsocket_hci_raw_send_ngmsg(path,
 1141                                         NGM_HCI_NODE_RESET_STAT, NULL, 0);
 1142                 else
 1143                         error = EPERM;
 1144                 break;
 1145 
 1146         case SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE:
 1147                 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
 1148                         error = ng_btsocket_hci_raw_send_ngmsg(path,
 1149                                         NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE,
 1150                                         NULL, 0);
 1151                 else
 1152                         error = EPERM;
 1153                 break;
 1154 
 1155         case SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE:  {
 1156                 struct ng_btsocket_hci_raw_node_neighbor_cache  *p = 
 1157                         (struct ng_btsocket_hci_raw_node_neighbor_cache *) data;
 1158                 ng_hci_node_get_neighbor_cache_ep               *p1 = NULL;
 1159                 ng_hci_node_neighbor_cache_entry_ep             *p2 = NULL;
 1160 
 1161                 if (p->num_entries <= 0 || 
 1162                     p->num_entries > NG_HCI_MAX_NEIGHBOR_NUM ||
 1163                     p->entries == NULL) {
 1164                         mtx_unlock(&pcb->pcb_mtx);
 1165                         return (EINVAL);
 1166                 }
 1167 
 1168                 NG_MKMESSAGE(msg, NGM_HCI_COOKIE,
 1169                         NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, M_NOWAIT);
 1170                 if (msg == NULL) {
 1171                         mtx_unlock(&pcb->pcb_mtx);
 1172                         return (ENOMEM);
 1173                 }
 1174                 ng_btsocket_hci_raw_get_token(&msg->header.token);
 1175                 pcb->token = msg->header.token;
 1176                 pcb->msg = NULL;
 1177 
 1178                 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0);
 1179                 if (error != 0) {
 1180                         pcb->token = 0;
 1181                         mtx_unlock(&pcb->pcb_mtx);
 1182                         return (error);
 1183                 }
 1184 
 1185                 error = msleep(&pcb->msg, &pcb->pcb_mtx,
 1186                                 PZERO|PCATCH, "hcictl", 
 1187                                 ng_btsocket_hci_raw_ioctl_timeout * hz);
 1188                 pcb->token = 0;
 1189 
 1190                 if (error != 0) {
 1191                         mtx_unlock(&pcb->pcb_mtx);
 1192                         return (error);
 1193                 }
 1194 
 1195                 msg = pcb->msg;
 1196                 pcb->msg = NULL;
 1197 
 1198                 mtx_unlock(&pcb->pcb_mtx);
 1199                 
 1200                 if (msg != NULL &&
 1201                     msg->header.cmd == NGM_HCI_NODE_GET_NEIGHBOR_CACHE) {
 1202                         /* Return data back to user space */
 1203                         p1 = (ng_hci_node_get_neighbor_cache_ep *)(msg->data);
 1204                         p2 = (ng_hci_node_neighbor_cache_entry_ep *)(p1 + 1);
 1205 
 1206                         p->num_entries = min(p->num_entries, p1->num_entries);
 1207                         if (p->num_entries > 0)
 1208                                 error = copyout((caddr_t) p2, 
 1209                                                 (caddr_t) p->entries,
 1210                                                 p->num_entries * sizeof(*p2));
 1211                 } else
 1212                         error = EINVAL;
 1213 
 1214                 NG_FREE_MSG(msg); /* checks for != NULL */
 1215                 return (error);
 1216                 } /* NOTREACHED */
 1217 
 1218         case SIOC_HCI_RAW_NODE_GET_CON_LIST: {
 1219                 struct ng_btsocket_hci_raw_con_list     *p = 
 1220                         (struct ng_btsocket_hci_raw_con_list *) data;
 1221                 ng_hci_node_con_list_ep                 *p1 = NULL;
 1222                 ng_hci_node_con_ep                      *p2 = NULL;
 1223 
 1224                 if (p->num_connections == 0 ||
 1225                     p->num_connections > NG_HCI_MAX_CON_NUM ||
 1226                     p->connections == NULL) {
 1227                         mtx_unlock(&pcb->pcb_mtx);
 1228                         return (EINVAL);
 1229                 }
 1230 
 1231                 NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_NODE_GET_CON_LIST,
 1232                         0, M_NOWAIT);
 1233                 if (msg == NULL) {
 1234                         mtx_unlock(&pcb->pcb_mtx);
 1235                         return (ENOMEM);
 1236                 }
 1237                 ng_btsocket_hci_raw_get_token(&msg->header.token);
 1238                 pcb->token = msg->header.token;
 1239                 pcb->msg = NULL;
 1240 
 1241                 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, 0);
 1242                 if (error != 0) {
 1243                         pcb->token = 0;
 1244                         mtx_unlock(&pcb->pcb_mtx);
 1245                         return (error);
 1246                 }
 1247 
 1248                 error = msleep(&pcb->msg, &pcb->pcb_mtx,
 1249                                 PZERO|PCATCH, "hcictl", 
 1250                                 ng_btsocket_hci_raw_ioctl_timeout * hz);
 1251                 pcb->token = 0;
 1252 
 1253                 if (error != 0) {
 1254                         mtx_unlock(&pcb->pcb_mtx);
 1255                         return (error);
 1256                 }
 1257 
 1258                 msg = pcb->msg;
 1259                 pcb->msg = NULL;
 1260 
 1261                 mtx_unlock(&pcb->pcb_mtx);
 1262 
 1263                 if (msg != NULL &&
 1264                     msg->header.cmd == NGM_HCI_NODE_GET_CON_LIST) {
 1265                         /* Return data back to user space */
 1266                         p1 = (ng_hci_node_con_list_ep *)(msg->data);
 1267                         p2 = (ng_hci_node_con_ep *)(p1 + 1);
 1268 
 1269                         p->num_connections = min(p->num_connections,
 1270                                                 p1->num_connections);
 1271                         if (p->num_connections > 0)
 1272                                 error = copyout((caddr_t) p2, 
 1273                                         (caddr_t) p->connections,
 1274                                         p->num_connections * sizeof(*p2));
 1275                 } else
 1276                         error = EINVAL;
 1277 
 1278                 NG_FREE_MSG(msg); /* checks for != NULL */
 1279                 return (error);
 1280                 } /* NOTREACHED */
 1281 
 1282         case SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK: {
 1283                 struct ng_btsocket_hci_raw_node_link_policy_mask        *p = 
 1284                         (struct ng_btsocket_hci_raw_node_link_policy_mask *) 
 1285                                 data;
 1286 
 1287                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
 1288                                 NGM_HCI_NODE_GET_LINK_POLICY_SETTINGS_MASK,
 1289                                 &p->policy_mask, sizeof(p->policy_mask));
 1290                 } break;
 1291 
 1292         case SIOC_HCI_RAW_NODE_SET_LINK_POLICY_MASK: {
 1293                 struct ng_btsocket_hci_raw_node_link_policy_mask        *p = 
 1294                         (struct ng_btsocket_hci_raw_node_link_policy_mask *) 
 1295                                 data;
 1296 
 1297                 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
 1298                         error = ng_btsocket_hci_raw_send_ngmsg(path,
 1299                                         NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK,
 1300                                         &p->policy_mask,
 1301                                         sizeof(p->policy_mask));
 1302                 else
 1303                         error = EPERM;
 1304                 } break;
 1305 
 1306         case SIOC_HCI_RAW_NODE_GET_PACKET_MASK: {
 1307                 struct ng_btsocket_hci_raw_node_packet_mask     *p = 
 1308                         (struct ng_btsocket_hci_raw_node_packet_mask *) data;
 1309 
 1310                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
 1311                                 NGM_HCI_NODE_GET_PACKET_MASK,
 1312                                 &p->packet_mask, sizeof(p->packet_mask));
 1313                 } break;
 1314 
 1315         case SIOC_HCI_RAW_NODE_SET_PACKET_MASK: {
 1316                 struct ng_btsocket_hci_raw_node_packet_mask     *p = 
 1317                         (struct ng_btsocket_hci_raw_node_packet_mask *) data;
 1318 
 1319                 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
 1320                         error = ng_btsocket_hci_raw_send_ngmsg(path,
 1321                                         NGM_HCI_NODE_SET_PACKET_MASK,
 1322                                         &p->packet_mask,
 1323                                         sizeof(p->packet_mask));
 1324                 else
 1325                         error = EPERM;
 1326                 } break;
 1327 
 1328         case SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH: {
 1329                 struct ng_btsocket_hci_raw_node_role_switch     *p = 
 1330                         (struct ng_btsocket_hci_raw_node_role_switch *) data;
 1331 
 1332                 error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
 1333                                 NGM_HCI_NODE_GET_ROLE_SWITCH,
 1334                                 &p->role_switch, sizeof(p->role_switch));
 1335                 } break;
 1336 
 1337         case SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH: {
 1338                 struct ng_btsocket_hci_raw_node_role_switch     *p = 
 1339                         (struct ng_btsocket_hci_raw_node_role_switch *) data;
 1340 
 1341                 if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
 1342                         error = ng_btsocket_hci_raw_send_ngmsg(path,
 1343                                         NGM_HCI_NODE_SET_ROLE_SWITCH,
 1344                                         &p->role_switch,
 1345                                         sizeof(p->role_switch));
 1346                 else
 1347                         error = EPERM;
 1348                 } break;
 1349 
 1350         case SIOC_HCI_RAW_NODE_LIST_NAMES: {
 1351                 struct ng_btsocket_hci_raw_node_list_names      *nl =
 1352                         (struct ng_btsocket_hci_raw_node_list_names *) data;
 1353                 struct nodeinfo                                 *ni = nl->names;
 1354 
 1355                 if (nl->num_names == 0) {
 1356                         mtx_unlock(&pcb->pcb_mtx);
 1357                         return (EINVAL);
 1358                 }
 1359 
 1360                 NG_MKMESSAGE(msg, NGM_GENERIC_COOKIE, NGM_LISTNAMES,
 1361                         0, M_NOWAIT);
 1362                 if (msg == NULL) {
 1363                         mtx_unlock(&pcb->pcb_mtx);
 1364                         return (ENOMEM);
 1365                 }
 1366                 ng_btsocket_hci_raw_get_token(&msg->header.token);
 1367                 pcb->token = msg->header.token;
 1368                 pcb->msg = NULL;
 1369 
 1370                 NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, ".:", 0);
 1371                 if (error != 0) {
 1372                         pcb->token = 0;
 1373                         mtx_unlock(&pcb->pcb_mtx);
 1374                         return (error);
 1375                 }
 1376 
 1377                 error = msleep(&pcb->msg, &pcb->pcb_mtx,
 1378                                 PZERO|PCATCH, "hcictl",
 1379                                 ng_btsocket_hci_raw_ioctl_timeout * hz);
 1380                 pcb->token = 0;
 1381 
 1382                 if (error != 0) {
 1383                         mtx_unlock(&pcb->pcb_mtx);
 1384                         return (error);
 1385                 }
 1386 
 1387                 msg = pcb->msg;
 1388                 pcb->msg = NULL;
 1389 
 1390                 mtx_unlock(&pcb->pcb_mtx);
 1391 
 1392                 if (msg != NULL && msg->header.cmd == NGM_LISTNAMES) {
 1393                         /* Return data back to user space */
 1394                         struct namelist *nl1 = (struct namelist *) msg->data;
 1395                         struct nodeinfo *ni1 = &nl1->nodeinfo[0];
 1396 
 1397                         while (nl->num_names > 0 && nl1->numnames > 0) {
 1398                                 if (strcmp(ni1->type, NG_HCI_NODE_TYPE) == 0) {
 1399                                         error = copyout((caddr_t) ni1,
 1400                                                         (caddr_t) ni,
 1401                                                         sizeof(*ni));
 1402                                         if (error != 0)
 1403                                                 break;
 1404 
 1405                                         nl->num_names --;
 1406                                         ni ++;
 1407                                 }
 1408 
 1409                                 nl1->numnames --;
 1410                                 ni1 ++;
 1411                         }
 1412 
 1413                         nl->num_names = ni - nl->names;
 1414                 } else
 1415                         error = EINVAL;
 1416 
 1417                 NG_FREE_MSG(msg); /* checks for != NULL */
 1418                 return (error);
 1419                 } /* NOTREACHED */
 1420 
 1421         default:
 1422                 error = EINVAL;
 1423                 break;
 1424         }
 1425 
 1426         mtx_unlock(&pcb->pcb_mtx);
 1427 
 1428         return (error);
 1429 } /* ng_btsocket_hci_raw_control */
 1430 
 1431 /*
 1432  * Process getsockopt/setsockopt system calls
 1433  */
 1434 
 1435 int
 1436 ng_btsocket_hci_raw_ctloutput(struct socket *so, struct sockopt *sopt)
 1437 {
 1438         ng_btsocket_hci_raw_pcb_p               pcb = so2hci_raw_pcb(so);
 1439         struct ng_btsocket_hci_raw_filter       filter;
 1440         int                                     error = 0, dir;
 1441 
 1442         if (pcb == NULL)
 1443                 return (EINVAL);
 1444         if (ng_btsocket_hci_raw_node == NULL)
 1445                 return (EINVAL);
 1446 
 1447         if (sopt->sopt_level != SOL_HCI_RAW)
 1448                 return (0);
 1449 
 1450         mtx_lock(&pcb->pcb_mtx);
 1451 
 1452         switch (sopt->sopt_dir) {
 1453         case SOPT_GET:
 1454                 switch (sopt->sopt_name) {
 1455                 case SO_HCI_RAW_FILTER:
 1456                         error = sooptcopyout(sopt, &pcb->filter,
 1457                                                 sizeof(pcb->filter));
 1458                         break;
 1459 
 1460                 case SO_HCI_RAW_DIRECTION:
 1461                         dir = (pcb->flags & NG_BTSOCKET_HCI_RAW_DIRECTION)?1:0;
 1462                         error = sooptcopyout(sopt, &dir, sizeof(dir));
 1463                         break;
 1464 
 1465                 default:
 1466                         error = EINVAL;
 1467                         break;
 1468                 }
 1469                 break;
 1470 
 1471         case SOPT_SET:
 1472                 switch (sopt->sopt_name) {
 1473                 case SO_HCI_RAW_FILTER:
 1474                         error = sooptcopyin(sopt, &filter, sizeof(filter),
 1475                                                 sizeof(filter));
 1476                         if (error == 0)
 1477                                 bcopy(&filter, &pcb->filter,
 1478                                                 sizeof(pcb->filter));
 1479                         break;
 1480 
 1481                 case SO_HCI_RAW_DIRECTION:
 1482                         error = sooptcopyin(sopt, &dir, sizeof(dir),
 1483                                                 sizeof(dir));
 1484                         if (error != 0)
 1485                                 break;
 1486 
 1487                         if (dir)
 1488                                 pcb->flags |= NG_BTSOCKET_HCI_RAW_DIRECTION;
 1489                         else
 1490                                 pcb->flags &= ~NG_BTSOCKET_HCI_RAW_DIRECTION;
 1491                         break;
 1492 
 1493                 default:
 1494                         error = EINVAL;
 1495                         break;
 1496                 }
 1497                 break;
 1498 
 1499         default:
 1500                 error = EINVAL;
 1501                 break;
 1502         }
 1503 
 1504         mtx_unlock(&pcb->pcb_mtx);
 1505 
 1506         return (error);
 1507 } /* ng_btsocket_hci_raw_ctloutput */
 1508 
 1509 /*
 1510  * Detach raw HCI socket
 1511  */
 1512 
 1513 void
 1514 ng_btsocket_hci_raw_detach(struct socket *so)
 1515 {
 1516         ng_btsocket_hci_raw_pcb_p       pcb = so2hci_raw_pcb(so);
 1517 
 1518         KASSERT(pcb != NULL, ("ng_btsocket_hci_raw_detach: pcb == NULL"));
 1519 
 1520         if (ng_btsocket_hci_raw_node == NULL)
 1521                 return;
 1522 
 1523         mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
 1524         mtx_lock(&pcb->pcb_mtx);
 1525 
 1526         LIST_REMOVE(pcb, next);
 1527 
 1528         mtx_unlock(&pcb->pcb_mtx);
 1529         mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
 1530 
 1531         mtx_destroy(&pcb->pcb_mtx);
 1532 
 1533         bzero(pcb, sizeof(*pcb));
 1534         free(pcb, M_NETGRAPH_BTSOCKET_HCI_RAW);
 1535 
 1536         so->so_pcb = NULL;
 1537 } /* ng_btsocket_hci_raw_detach */
 1538 
 1539 /*
 1540  * Disconnect raw HCI socket
 1541  */
 1542 
 1543 int
 1544 ng_btsocket_hci_raw_disconnect(struct socket *so)
 1545 {
 1546         ng_btsocket_hci_raw_pcb_p        pcb = so2hci_raw_pcb(so);
 1547 
 1548         if (pcb == NULL)
 1549                 return (EINVAL);
 1550         if (ng_btsocket_hci_raw_node == NULL)
 1551                 return (EINVAL);
 1552 
 1553         mtx_lock(&pcb->pcb_mtx);
 1554         soisdisconnected(so);
 1555         mtx_unlock(&pcb->pcb_mtx);
 1556 
 1557         return (0);
 1558 } /* ng_btsocket_hci_raw_disconnect */
 1559 
 1560 /*
 1561  * Get socket peer's address
 1562  */
 1563 
 1564 int
 1565 ng_btsocket_hci_raw_peeraddr(struct socket *so, struct sockaddr **nam)
 1566 {
 1567         return (ng_btsocket_hci_raw_sockaddr(so, nam));
 1568 } /* ng_btsocket_hci_raw_peeraddr */
 1569 
 1570 /*
 1571  * Send data
 1572  */
 1573 
 1574 int
 1575 ng_btsocket_hci_raw_send(struct socket *so, int flags, struct mbuf *m,
 1576                 struct sockaddr *sa, struct mbuf *control, struct thread *td)
 1577 {
 1578         ng_btsocket_hci_raw_pcb_p        pcb = so2hci_raw_pcb(so);
 1579         struct mbuf                     *nam = NULL;
 1580         int                              error = 0;
 1581 
 1582         if (ng_btsocket_hci_raw_node == NULL) {
 1583                 error = ENETDOWN;
 1584                 goto drop;
 1585         }
 1586         if (pcb == NULL) {
 1587                 error = EINVAL;
 1588                 goto drop;
 1589         }
 1590         if (control != NULL) {
 1591                 error = EINVAL;
 1592                 goto drop;
 1593         }
 1594 
 1595         if (m->m_pkthdr.len < sizeof(ng_hci_cmd_pkt_t) ||
 1596             m->m_pkthdr.len > sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE) {
 1597                 error = EMSGSIZE;
 1598                 goto drop;
 1599         }
 1600 
 1601         if (m->m_len < sizeof(ng_hci_cmd_pkt_t)) {
 1602                 if ((m = m_pullup(m, sizeof(ng_hci_cmd_pkt_t))) == NULL) {
 1603                         error = ENOBUFS;
 1604                         goto drop;
 1605                 }
 1606         }
 1607         if (*mtod(m, u_int8_t *) != NG_HCI_CMD_PKT) {
 1608                 error = ENOTSUP;
 1609                 goto drop;
 1610         }
 1611 
 1612         mtx_lock(&pcb->pcb_mtx);
 1613 
 1614         error = ng_btsocket_hci_raw_filter(pcb, m, 0);
 1615         if (error != 0) {
 1616                 mtx_unlock(&pcb->pcb_mtx);
 1617                 goto drop;
 1618         }
 1619 
 1620         if (sa == NULL) {
 1621                 if (pcb->addr.hci_node[0] == 0) {
 1622                         mtx_unlock(&pcb->pcb_mtx);
 1623                         error = EDESTADDRREQ;
 1624                         goto drop;
 1625                 }
 1626 
 1627                 sa = (struct sockaddr *) &pcb->addr;
 1628         }
 1629 
 1630         MGET(nam, M_NOWAIT, MT_SONAME);
 1631         if (nam == NULL) {
 1632                 mtx_unlock(&pcb->pcb_mtx);
 1633                 error = ENOBUFS;
 1634                 goto drop;
 1635         }
 1636 
 1637         nam->m_len = sizeof(struct sockaddr_hci);
 1638         bcopy(sa,mtod(nam, struct sockaddr_hci *),sizeof(struct sockaddr_hci));
 1639 
 1640         nam->m_next = m;
 1641         m = NULL;
 1642 
 1643         mtx_unlock(&pcb->pcb_mtx);
 1644 
 1645         return (ng_send_fn(ng_btsocket_hci_raw_node, NULL, 
 1646                                 ng_btsocket_hci_raw_output, nam, 0));
 1647 drop:
 1648         NG_FREE_M(control); /* NG_FREE_M checks for != NULL */
 1649         NG_FREE_M(nam);
 1650         NG_FREE_M(m);
 1651 
 1652         return (error);
 1653 } /* ng_btsocket_hci_raw_send */
 1654 
 1655 /*
 1656  * Get socket address
 1657  */
 1658 
 1659 int
 1660 ng_btsocket_hci_raw_sockaddr(struct socket *so, struct sockaddr **nam)
 1661 {
 1662         ng_btsocket_hci_raw_pcb_p       pcb = so2hci_raw_pcb(so);
 1663         struct sockaddr_hci             sa;
 1664 
 1665         if (pcb == NULL)
 1666                 return (EINVAL);
 1667         if (ng_btsocket_hci_raw_node == NULL)
 1668                 return (EINVAL);
 1669 
 1670         bzero(&sa, sizeof(sa));
 1671         sa.hci_len = sizeof(sa);
 1672         sa.hci_family = AF_BLUETOOTH;
 1673 
 1674         mtx_lock(&pcb->pcb_mtx);
 1675         strlcpy(sa.hci_node, pcb->addr.hci_node, sizeof(sa.hci_node));
 1676         mtx_unlock(&pcb->pcb_mtx);
 1677 
 1678         *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT);
 1679 
 1680         return ((*nam == NULL)? ENOMEM : 0);
 1681 } /* ng_btsocket_hci_raw_sockaddr */

Cache object: 1abec3a96d755976b72ef5d0cddd08f1


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