[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netbt/hci_socket.c

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

    1 /*      $NetBSD: hci_socket.c,v 1.20 2011/01/30 17:23:23 plunky Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2005 Iain Hibbert.
    5  * Copyright (c) 2006 Itronix Inc.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. The name of Itronix Inc. may not be used to endorse
   17  *    or promote products derived from this software without specific
   18  *    prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
   24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   27  * ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30  * POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: hci_socket.c,v 1.20 2011/01/30 17:23:23 plunky Exp $");
   35 
   36 /* load symbolic names */
   37 #ifdef BLUETOOTH_DEBUG
   38 #define PRUREQUESTS
   39 #define PRCOREQUESTS
   40 #endif
   41 
   42 #include <sys/param.h>
   43 #include <sys/domain.h>
   44 #include <sys/kauth.h>
   45 #include <sys/kernel.h>
   46 #include <sys/mbuf.h>
   47 #include <sys/proc.h>
   48 #include <sys/protosw.h>
   49 #include <sys/socket.h>
   50 #include <sys/socketvar.h>
   51 #include <sys/systm.h>
   52 
   53 #include <netbt/bluetooth.h>
   54 #include <netbt/hci.h>
   55 
   56 /*******************************************************************************
   57  *
   58  * HCI SOCK_RAW Sockets - for control of Bluetooth Devices
   59  *
   60  */
   61 
   62 /*
   63  * the raw HCI protocol control block
   64  */
   65 struct hci_pcb {
   66         struct socket           *hp_socket;     /* socket */
   67         kauth_cred_t            hp_cred;        /* owner credential */
   68         unsigned int            hp_flags;       /* flags */
   69         bdaddr_t                hp_laddr;       /* local address */
   70         bdaddr_t                hp_raddr;       /* remote address */
   71         struct hci_filter       hp_efilter;     /* user event filter */
   72         struct hci_filter       hp_pfilter;     /* user packet filter */
   73         LIST_ENTRY(hci_pcb)     hp_next;        /* next HCI pcb */
   74 };
   75 
   76 /* hp_flags */
   77 #define HCI_DIRECTION           (1<<1)  /* direction control messages */
   78 #define HCI_PROMISCUOUS         (1<<2)  /* listen to all units */
   79 
   80 LIST_HEAD(hci_pcb_list, hci_pcb) hci_pcb = LIST_HEAD_INITIALIZER(hci_pcb);
   81 
   82 /* sysctl defaults */
   83 int hci_sendspace = HCI_CMD_PKT_SIZE;
   84 int hci_recvspace = 4096;
   85 
   86 /* unprivileged commands opcode table */
   87 static const struct {
   88         uint16_t        opcode;
   89         uint8_t         offs;   /* 0 - 63 */
   90         uint8_t         mask;   /* bit 0 - 7 */
   91         uint8_t         length; /* approved length */
   92 } hci_cmds[] = {
   93         { HCI_CMD_INQUIRY,
   94           0,  0x01, sizeof(hci_inquiry_cp) },
   95         { HCI_CMD_REMOTE_NAME_REQ,
   96           2,  0x08, sizeof(hci_remote_name_req_cp) },
   97         { HCI_CMD_READ_REMOTE_FEATURES,
   98           2,  0x20, sizeof(hci_read_remote_features_cp) },
   99         { HCI_CMD_READ_REMOTE_EXTENDED_FEATURES,
  100           2,  0x40, sizeof(hci_read_remote_extended_features_cp) },
  101         { HCI_CMD_READ_REMOTE_VER_INFO,
  102           2,  0x80, sizeof(hci_read_remote_ver_info_cp) },
  103         { HCI_CMD_READ_CLOCK_OFFSET,
  104           3,  0x01, sizeof(hci_read_clock_offset_cp) },
  105         { HCI_CMD_READ_LMP_HANDLE,
  106           3,  0x02, sizeof(hci_read_lmp_handle_cp) },
  107         { HCI_CMD_ROLE_DISCOVERY,
  108           4,  0x80, sizeof(hci_role_discovery_cp) },
  109         { HCI_CMD_READ_LINK_POLICY_SETTINGS,
  110           5,  0x02, sizeof(hci_read_link_policy_settings_cp) },
  111         { HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS,
  112           5,  0x08, 0 },
  113         { HCI_CMD_READ_PIN_TYPE,
  114           6,  0x04, 0 },
  115         { HCI_CMD_READ_LOCAL_NAME,
  116           7,  0x02, 0 },
  117         { HCI_CMD_READ_CON_ACCEPT_TIMEOUT,
  118           7,  0x04, 0 },
  119         { HCI_CMD_READ_PAGE_TIMEOUT,
  120           7,  0x10, 0 },
  121         { HCI_CMD_READ_SCAN_ENABLE,
  122           7,  0x40, 0 },
  123         { HCI_CMD_READ_PAGE_SCAN_ACTIVITY,
  124           8,  0x01, 0 },
  125         { HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY,
  126           8,  0x04, 0 },
  127         { HCI_CMD_READ_AUTH_ENABLE,
  128           8,  0x10, 0 },
  129         { HCI_CMD_READ_ENCRYPTION_MODE,
  130           8,  0x40, 0 },
  131         { HCI_CMD_READ_UNIT_CLASS,
  132           9,  0x01, 0 },
  133         { HCI_CMD_READ_VOICE_SETTING,
  134           9,  0x04, 0 },
  135         { HCI_CMD_READ_AUTO_FLUSH_TIMEOUT,
  136           9,  0x10, sizeof(hci_read_auto_flush_timeout_cp) },
  137         { HCI_CMD_READ_NUM_BROADCAST_RETRANS,
  138           9,  0x40, 0 },
  139         { HCI_CMD_READ_HOLD_MODE_ACTIVITY,
  140           10, 0x01, 0 },
  141         { HCI_CMD_READ_XMIT_LEVEL,
  142           10, 0x04, sizeof(hci_read_xmit_level_cp) },
  143         { HCI_CMD_READ_SCO_FLOW_CONTROL,
  144           10, 0x08, 0 },
  145         { HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT,
  146           11, 0x01, sizeof(hci_read_link_supervision_timeout_cp) },
  147         { HCI_CMD_READ_NUM_SUPPORTED_IAC,
  148           11, 0x04, 0 },
  149         { HCI_CMD_READ_IAC_LAP,
  150           11, 0x08, 0 },
  151         { HCI_CMD_READ_PAGE_SCAN_PERIOD,
  152           11, 0x20, 0 },
  153         { HCI_CMD_READ_PAGE_SCAN,
  154           11, 0x80, 0 },
  155         { HCI_CMD_READ_INQUIRY_SCAN_TYPE,
  156           12, 0x10, 0 },
  157         { HCI_CMD_READ_INQUIRY_MODE,
  158           12, 0x40, 0 },
  159         { HCI_CMD_READ_PAGE_SCAN_TYPE,
  160           13, 0x01, 0 },
  161         { HCI_CMD_READ_AFH_ASSESSMENT,
  162           13, 0x04, 0 },
  163         { HCI_CMD_READ_LOCAL_VER,
  164           14, 0x08, 0 },
  165         { HCI_CMD_READ_LOCAL_COMMANDS,
  166           14, 0x10, 0 },
  167         { HCI_CMD_READ_LOCAL_FEATURES,
  168           14, 0x20, 0 },
  169         { HCI_CMD_READ_LOCAL_EXTENDED_FEATURES,
  170           14, 0x40, sizeof(hci_read_local_extended_features_cp) },
  171         { HCI_CMD_READ_BUFFER_SIZE,
  172           14, 0x80, 0 },
  173         { HCI_CMD_READ_COUNTRY_CODE,
  174           15, 0x01, 0 },
  175         { HCI_CMD_READ_BDADDR,
  176           15, 0x02, 0 },
  177         { HCI_CMD_READ_FAILED_CONTACT_CNTR,
  178           15, 0x04, sizeof(hci_read_failed_contact_cntr_cp) },
  179         { HCI_CMD_READ_LINK_QUALITY,
  180           15, 0x10, sizeof(hci_read_link_quality_cp) },
  181         { HCI_CMD_READ_RSSI,
  182           15, 0x20, sizeof(hci_read_rssi_cp) },
  183         { HCI_CMD_READ_AFH_CHANNEL_MAP,
  184           15, 0x40, sizeof(hci_read_afh_channel_map_cp) },
  185         { HCI_CMD_READ_CLOCK,
  186           15, 0x80, sizeof(hci_read_clock_cp) },
  187         { HCI_CMD_READ_LOOPBACK_MODE,
  188           16, 0x01, 0 },
  189         { HCI_CMD_READ_EXTENDED_INQUIRY_RSP,
  190           17, 0x01, 0 },
  191         { HCI_CMD_READ_SIMPLE_PAIRING_MODE,
  192           17, 0x20, 0 },
  193         { HCI_CMD_READ_INQUIRY_RSP_XMIT_POWER,
  194           18, 0x01, 0 },
  195         { HCI_CMD_READ_DEFAULT_ERRDATA_REPORTING,
  196           18, 0x04, 0 },
  197 };
  198 
  199 /*
  200  * supply a basic device send/recv policy
  201  */
  202 static int
  203 hci_device_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
  204     void *arg0, void *arg1, void *arg2, void *arg3)
  205 {
  206         int i, result;
  207 
  208         result = KAUTH_RESULT_DEFER;
  209 
  210         switch (action) {
  211         case KAUTH_DEVICE_BLUETOOTH_SEND: {
  212                 struct hci_unit *unit = (struct hci_unit *)arg0;
  213                 hci_cmd_hdr_t *hdr = (hci_cmd_hdr_t *)arg1;
  214 
  215                 /*
  216                  * Allow sending unprivileged commands if the packet size
  217                  * is correct and the unit claims to support it
  218                  */
  219 
  220                 if (hdr->type != HCI_CMD_PKT)
  221                         break;
  222 
  223                 for (i = 0; i < __arraycount(hci_cmds); i++) {
  224                         if (hdr->opcode == hci_cmds[i].opcode
  225                             && hdr->length == hci_cmds[i].length
  226                             && (unit->hci_cmds[hci_cmds[i].offs] & hci_cmds[i].mask)) {
  227                                 result = KAUTH_RESULT_ALLOW;
  228                                 break;
  229                         }
  230                 }
  231 
  232                 break;
  233                 }
  234 
  235         case KAUTH_DEVICE_BLUETOOTH_RECV:
  236                 switch((uint8_t)(uintptr_t)arg0) {
  237                 case HCI_CMD_PKT: {
  238                         uint16_t opcode = (uint16_t)(uintptr_t)arg1;
  239 
  240                         /*
  241                          * Allow to see any unprivileged command packet
  242                          */
  243 
  244                         for (i = 0; i < __arraycount(hci_cmds); i++) {
  245                                 if (opcode == hci_cmds[i].opcode) {
  246                                         result = KAUTH_RESULT_ALLOW;
  247                                         break;
  248                                 }
  249                         }
  250 
  251                         break;
  252                         }
  253 
  254                 case HCI_EVENT_PKT: {
  255                         uint8_t event = (uint8_t)(uintptr_t)arg1;
  256 
  257                         /*
  258                          * Allow to receive most events
  259                          */
  260 
  261                         switch (event) {
  262                         case HCI_EVENT_RETURN_LINK_KEYS:
  263                         case HCI_EVENT_LINK_KEY_NOTIFICATION:
  264                         case HCI_EVENT_USER_CONFIRM_REQ:
  265                         case HCI_EVENT_USER_PASSKEY_NOTIFICATION:
  266                         case HCI_EVENT_VENDOR:
  267                                 break;
  268 
  269                         default:
  270                                 result = KAUTH_RESULT_ALLOW;
  271                                 break;
  272                         }
  273 
  274                         break;
  275                         }
  276 
  277                 case HCI_ACL_DATA_PKT:
  278                 case HCI_SCO_DATA_PKT: {
  279                         /* uint16_t handle = (uint16_t)(uintptr_t)arg1; */
  280                         /*
  281                          * don't normally allow receiving data packets
  282                          */
  283                         break;
  284                         }
  285 
  286                 default:
  287                         break;
  288                 }
  289 
  290                 break;
  291 
  292         default:
  293                 break;
  294         }
  295 
  296         return result;
  297 }
  298 
  299 /*
  300  * HCI protocol init routine,
  301  * - set up a kauth listener to provide basic packet access policy
  302  */
  303 void
  304 hci_init(void)
  305 {
  306 
  307         if (kauth_listen_scope(KAUTH_SCOPE_DEVICE, hci_device_cb, NULL) == NULL)
  308                 panic("Bluetooth HCI: cannot listen on device scope");
  309 }
  310 
  311 /*
  312  * When command packet reaches the device, we can drop
  313  * it from the socket buffer (called from hci_output_acl)
  314  */
  315 void
  316 hci_drop(void *arg)
  317 {
  318         struct socket *so = arg;
  319 
  320         sbdroprecord(&so->so_snd);
  321         sowwakeup(so);
  322 }
  323 
  324 /*
  325  * HCI socket is going away and has some pending packets. We let them
  326  * go by design, but remove the context pointer as it will be invalid
  327  * and we no longer need to be notified.
  328  */
  329 static void
  330 hci_cmdwait_flush(struct socket *so)
  331 {
  332         struct hci_unit *unit;
  333         struct socket *ctx;
  334         struct mbuf *m;
  335 
  336         DPRINTF("flushing %p\n", so);
  337 
  338         SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
  339                 m = MBUFQ_FIRST(&unit->hci_cmdwait);
  340                 while (m != NULL) {
  341                         ctx = M_GETCTX(m, struct socket *);
  342                         if (ctx == so)
  343                                 M_SETCTX(m, NULL);
  344 
  345                         m = MBUFQ_NEXT(m);
  346                 }
  347         }
  348 }
  349 
  350 /*
  351  * HCI send packet
  352  *     This came from userland, so check it out.
  353  */
  354 static int
  355 hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
  356 {
  357         struct hci_unit *unit;
  358         struct mbuf *m0;
  359         hci_cmd_hdr_t hdr;
  360         int err;
  361 
  362         KASSERT(m != NULL);
  363         KASSERT(addr != NULL);
  364 
  365         /* wants at least a header to start with */
  366         if (m->m_pkthdr.len < sizeof(hdr)) {
  367                 err = EMSGSIZE;
  368                 goto bad;
  369         }
  370         m_copydata(m, 0, sizeof(hdr), &hdr);
  371         hdr.opcode = le16toh(hdr.opcode);
  372 
  373         /* only allows CMD packets to be sent */
  374         if (hdr.type != HCI_CMD_PKT) {
  375                 err = EINVAL;
  376                 goto bad;
  377         }
  378 
  379         /* validates packet length */
  380         if (m->m_pkthdr.len != sizeof(hdr) + hdr.length) {
  381                 err = EMSGSIZE;
  382                 goto bad;
  383         }
  384 
  385         /* finds destination */
  386         unit = hci_unit_lookup(addr);
  387         if (unit == NULL) {
  388                 err = ENETDOWN;
  389                 goto bad;
  390         }
  391 
  392         /* security checks for unprivileged users */
  393         if (pcb->hp_cred != NULL
  394             && kauth_authorize_device(pcb->hp_cred,
  395             KAUTH_DEVICE_BLUETOOTH_SEND,
  396             unit, &hdr, NULL, NULL) != 0) {
  397                 err = EPERM;
  398                 goto bad;
  399         }
  400 
  401         /* makess a copy for precious to keep */
  402         m0 = m_copypacket(m, M_DONTWAIT);
  403         if (m0 == NULL) {
  404                 err = ENOMEM;
  405                 goto bad;
  406         }
  407         sbappendrecord(&pcb->hp_socket->so_snd, m0);
  408         M_SETCTX(m, pcb->hp_socket);    /* enable drop callback */
  409 
  410         DPRINTFN(2, "(%s) opcode (%03x|%04x)\n", device_xname(unit->hci_dev),
  411                 HCI_OGF(hdr.opcode), HCI_OCF(hdr.opcode));
  412 
  413         /* Sendss it */
  414         if (unit->hci_num_cmd_pkts == 0)
  415                 MBUFQ_ENQUEUE(&unit->hci_cmdwait, m);
  416         else
  417                 hci_output_cmd(unit, m);
  418 
  419         return 0;
  420 
  421 bad:
  422         DPRINTF("packet (%d bytes) not sent (error %d)\n",
  423                         m->m_pkthdr.len, err);
  424         if (m) m_freem(m);
  425         return err;
  426 }
  427 
  428 /*
  429  * User Request.
  430  * up is socket
  431  * m is either
  432  *      optional mbuf chain containing message
  433  *      ioctl command (PRU_CONTROL)
  434  * nam is either
  435  *      optional mbuf chain containing an address
  436  *      ioctl data (PRU_CONTROL)
  437  *      optionally, protocol number (PRU_ATTACH)
  438  * ctl is optional mbuf chain containing socket options
  439  * l is pointer to process requesting action (if any)
  440  *
  441  * we are responsible for disposing of m and ctl if
  442  * they are mbuf chains
  443  */
  444 int
  445 hci_usrreq(struct socket *up, int req, struct mbuf *m,
  446                 struct mbuf *nam, struct mbuf *ctl, struct lwp *l)
  447 {
  448         struct hci_pcb *pcb = (struct hci_pcb *)up->so_pcb;
  449         struct sockaddr_bt *sa;
  450         int err = 0;
  451 
  452         DPRINTFN(2, "%s\n", prurequests[req]);
  453 
  454         switch(req) {
  455         case PRU_CONTROL:
  456                 mutex_enter(bt_lock);
  457                 err = hci_ioctl((unsigned long)m, (void *)nam, l);
  458                 mutex_exit(bt_lock);
  459                 return err;
  460 
  461         case PRU_PURGEIF:
  462                 return EOPNOTSUPP;
  463 
  464         case PRU_ATTACH:
  465                 if (up->so_lock == NULL) {
  466                         mutex_obj_hold(bt_lock);
  467                         up->so_lock = bt_lock;
  468                         solock(up);
  469                 }
  470                 KASSERT(solocked(up));
  471                 if (pcb)
  472                         return EINVAL;
  473                 err = soreserve(up, hci_sendspace, hci_recvspace);
  474                 if (err)
  475                         return err;
  476 
  477                 pcb = malloc(sizeof(struct hci_pcb), M_PCB, M_NOWAIT | M_ZERO);
  478                 if (pcb == NULL)
  479                         return ENOMEM;
  480 
  481                 up->so_pcb = pcb;
  482                 pcb->hp_socket = up;
  483 
  484                 if (l != NULL)
  485                         pcb->hp_cred = kauth_cred_dup(l->l_cred);
  486 
  487                 /*
  488                  * Set default user filter. By default, socket only passes
  489                  * Command_Complete and Command_Status Events.
  490                  */
  491                 hci_filter_set(HCI_EVENT_COMMAND_COMPL, &pcb->hp_efilter);
  492                 hci_filter_set(HCI_EVENT_COMMAND_STATUS, &pcb->hp_efilter);
  493                 hci_filter_set(HCI_EVENT_PKT, &pcb->hp_pfilter);
  494 
  495                 LIST_INSERT_HEAD(&hci_pcb, pcb, hp_next);
  496 
  497                 return 0;
  498         }
  499 
  500         /* anything after here *requires* a pcb */
  501         if (pcb == NULL) {
  502                 err = EINVAL;
  503                 goto release;
  504         }
  505 
  506         switch(req) {
  507         case PRU_DISCONNECT:
  508                 bdaddr_copy(&pcb->hp_raddr, BDADDR_ANY);
  509 
  510                 /* XXX we cannot call soisdisconnected() here, as it sets
  511                  * SS_CANTRCVMORE and SS_CANTSENDMORE. The problem being,
  512                  * that soisconnected() does not clear these and if you
  513                  * try to reconnect this socket (which is permitted) you
  514                  * get a broken pipe when you try to write any data.
  515                  */
  516                 up->so_state &= ~SS_ISCONNECTED;
  517                 break;
  518 
  519         case PRU_ABORT:
  520                 soisdisconnected(up);
  521                 /* fall through to */
  522         case PRU_DETACH:
  523                 if (up->so_snd.sb_mb != NULL)
  524                         hci_cmdwait_flush(up);
  525 
  526                 if (pcb->hp_cred != NULL)
  527                         kauth_cred_free(pcb->hp_cred);
  528 
  529                 up->so_pcb = NULL;
  530                 LIST_REMOVE(pcb, hp_next);
  531                 free(pcb, M_PCB);
  532                 return 0;
  533 
  534         case PRU_BIND:
  535                 KASSERT(nam != NULL);
  536                 sa = mtod(nam, struct sockaddr_bt *);
  537 
  538                 if (sa->bt_len != sizeof(struct sockaddr_bt))
  539                         return EINVAL;
  540 
  541                 if (sa->bt_family != AF_BLUETOOTH)
  542                         return EAFNOSUPPORT;
  543 
  544                 bdaddr_copy(&pcb->hp_laddr, &sa->bt_bdaddr);
  545 
  546                 if (bdaddr_any(&sa->bt_bdaddr))
  547                         pcb->hp_flags |= HCI_PROMISCUOUS;
  548                 else
  549                         pcb->hp_flags &= ~HCI_PROMISCUOUS;
  550 
  551                 return 0;
  552 
  553         case PRU_CONNECT:
  554                 KASSERT(nam != NULL);
  555                 sa = mtod(nam, struct sockaddr_bt *);
  556 
  557                 if (sa->bt_len != sizeof(struct sockaddr_bt))
  558                         return EINVAL;
  559 
  560                 if (sa->bt_family != AF_BLUETOOTH)
  561                         return EAFNOSUPPORT;
  562 
  563                 if (hci_unit_lookup(&sa->bt_bdaddr) == NULL)
  564                         return EADDRNOTAVAIL;
  565 
  566                 bdaddr_copy(&pcb->hp_raddr, &sa->bt_bdaddr);
  567                 soisconnected(up);
  568                 return 0;
  569 
  570         case PRU_PEERADDR:
  571                 KASSERT(nam != NULL);
  572                 sa = mtod(nam, struct sockaddr_bt *);
  573 
  574                 memset(sa, 0, sizeof(struct sockaddr_bt));
  575                 nam->m_len =
  576                 sa->bt_len = sizeof(struct sockaddr_bt);
  577                 sa->bt_family = AF_BLUETOOTH;
  578                 bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_raddr);
  579                 return 0;
  580 
  581         case PRU_SOCKADDR:
  582                 KASSERT(nam != NULL);
  583                 sa = mtod(nam, struct sockaddr_bt *);
  584 
  585                 memset(sa, 0, sizeof(struct sockaddr_bt));
  586                 nam->m_len =
  587                 sa->bt_len = sizeof(struct sockaddr_bt);
  588                 sa->bt_family = AF_BLUETOOTH;
  589                 bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_laddr);
  590                 return 0;
  591 
  592         case PRU_SHUTDOWN:
  593                 socantsendmore(up);
  594                 break;
  595 
  596         case PRU_SEND:
  597                 sa = NULL;
  598                 if (nam) {
  599                         sa = mtod(nam, struct sockaddr_bt *);
  600 
  601                         if (sa->bt_len != sizeof(struct sockaddr_bt)) {
  602                                 err = EINVAL;
  603                                 goto release;
  604                         }
  605 
  606                         if (sa->bt_family != AF_BLUETOOTH) {
  607                                 err = EAFNOSUPPORT;
  608                                 goto release;
  609                         }
  610                 }
  611 
  612                 if (ctl) /* have no use for this */
  613                         m_freem(ctl);
  614 
  615                 return hci_send(pcb, m, (sa ? &sa->bt_bdaddr : &pcb->hp_raddr));
  616 
  617         case PRU_SENSE:
  618                 return 0;               /* (no sense - Doh!) */
  619 
  620         case PRU_RCVD:
  621         case PRU_RCVOOB:
  622                 return EOPNOTSUPP;      /* (no release) */
  623 
  624         case PRU_ACCEPT:
  625         case PRU_CONNECT2:
  626         case PRU_LISTEN:
  627         case PRU_SENDOOB:
  628         case PRU_FASTTIMO:
  629         case PRU_SLOWTIMO:
  630         case PRU_PROTORCV:
  631         case PRU_PROTOSEND:
  632                 err = EOPNOTSUPP;
  633                 break;
  634 
  635         default:
  636                 UNKNOWN(req);
  637                 err = EOPNOTSUPP;
  638                 break;
  639         }
  640 
  641 release:
  642         if (m)
  643                 m_freem(m);
  644         if (ctl)
  645                 m_freem(ctl);
  646         return err;
  647 }
  648 
  649 /*
  650  * get/set socket options
  651  */
  652 int
  653 hci_ctloutput(int req, struct socket *so, struct sockopt *sopt)
  654 {
  655         struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
  656         int optval, err = 0;
  657 
  658         DPRINTFN(2, "req %s\n", prcorequests[req]);
  659 
  660         if (pcb == NULL)
  661                 return EINVAL;
  662 
  663         if (sopt->sopt_level != BTPROTO_HCI)
  664                 return ENOPROTOOPT;
  665 
  666         switch(req) {
  667         case PRCO_GETOPT:
  668                 switch (sopt->sopt_name) {
  669                 case SO_HCI_EVT_FILTER:
  670                         err = sockopt_set(sopt, &pcb->hp_efilter,
  671                             sizeof(struct hci_filter));
  672 
  673                         break;
  674 
  675                 case SO_HCI_PKT_FILTER:
  676                         err = sockopt_set(sopt, &pcb->hp_pfilter,
  677                             sizeof(struct hci_filter));
  678 
  679                         break;
  680 
  681                 case SO_HCI_DIRECTION:
  682                         err = sockopt_setint(sopt,
  683                             (pcb->hp_flags & HCI_DIRECTION ? 1 : 0));
  684 
  685                         break;
  686 
  687                 default:
  688                         err = ENOPROTOOPT;
  689                         break;
  690                 }
  691                 break;
  692 
  693         case PRCO_SETOPT:
  694                 switch (sopt->sopt_name) {
  695                 case SO_HCI_EVT_FILTER: /* set event filter */
  696                         err = sockopt_get(sopt, &pcb->hp_efilter,
  697                             sizeof(pcb->hp_efilter));
  698 
  699                         break;
  700 
  701                 case SO_HCI_PKT_FILTER: /* set packet filter */
  702                         err = sockopt_get(sopt, &pcb->hp_pfilter,
  703                             sizeof(pcb->hp_pfilter));
  704 
  705                         break;
  706 
  707                 case SO_HCI_DIRECTION:  /* request direction ctl messages */
  708                         err = sockopt_getint(sopt, &optval);
  709                         if (err)
  710                                 break;
  711 
  712                         if (optval)
  713                                 pcb->hp_flags |= HCI_DIRECTION;
  714                         else
  715                                 pcb->hp_flags &= ~HCI_DIRECTION;
  716                         break;
  717 
  718                 default:
  719                         err = ENOPROTOOPT;
  720                         break;
  721                 }
  722                 break;
  723 
  724         default:
  725                 err = ENOPROTOOPT;
  726                 break;
  727         }
  728 
  729         return err;
  730 }
  731 
  732 /*
  733  * HCI mbuf tap routine
  734  *
  735  * copy packets to any raw HCI sockets that wish (and are
  736  * permitted) to see them
  737  */
  738 void
  739 hci_mtap(struct mbuf *m, struct hci_unit *unit)
  740 {
  741         struct hci_pcb *pcb;
  742         struct mbuf *m0, *ctlmsg, **ctl;
  743         struct sockaddr_bt sa;
  744         uint8_t type;
  745         uint8_t event;
  746         uint16_t arg1;
  747 
  748         KASSERT(m->m_len >= sizeof(type));
  749 
  750         type = *mtod(m, uint8_t *);
  751 
  752         memset(&sa, 0, sizeof(sa));
  753         sa.bt_len = sizeof(struct sockaddr_bt);
  754         sa.bt_family = AF_BLUETOOTH;
  755         bdaddr_copy(&sa.bt_bdaddr, &unit->hci_bdaddr);
  756 
  757         LIST_FOREACH(pcb, &hci_pcb, hp_next) {
  758                 /*
  759                  * filter according to source address
  760                  */
  761                 if ((pcb->hp_flags & HCI_PROMISCUOUS) == 0
  762                     && bdaddr_same(&pcb->hp_laddr, &sa.bt_bdaddr) == 0)
  763                         continue;
  764 
  765                 /*
  766                  * filter according to packet type filter
  767                  */
  768                 if (hci_filter_test(type, &pcb->hp_pfilter) == 0)
  769                         continue;
  770 
  771                 /*
  772                  * filter according to event/security filters
  773                  */
  774                 switch(type) {
  775                 case HCI_EVENT_PKT:
  776                         KASSERT(m->m_len >= sizeof(hci_event_hdr_t));
  777 
  778                         event = mtod(m, hci_event_hdr_t *)->event;
  779 
  780                         if (hci_filter_test(event, &pcb->hp_efilter) == 0)
  781                                 continue;
  782 
  783                         arg1 = event;
  784                         break;
  785 
  786                 case HCI_CMD_PKT:
  787                         KASSERT(m->m_len >= sizeof(hci_cmd_hdr_t));
  788                         arg1 = le16toh(mtod(m, hci_cmd_hdr_t *)->opcode);
  789                         break;
  790 
  791                 case HCI_ACL_DATA_PKT:
  792                         KASSERT(m->m_len >= sizeof(hci_acldata_hdr_t));
  793                         arg1 = le16toh(mtod(m, hci_acldata_hdr_t *)->con_handle);
  794                         arg1 = HCI_CON_HANDLE(arg1);
  795                         break;
  796 
  797                 case HCI_SCO_DATA_PKT:
  798                         KASSERT(m->m_len >= sizeof(hci_scodata_hdr_t));
  799                         arg1 = le16toh(mtod(m, hci_scodata_hdr_t *)->con_handle);
  800                         arg1 = HCI_CON_HANDLE(arg1);
  801                         break;
  802 
  803                 default:
  804                         arg1 = 0;
  805                         break;
  806                 }
  807 
  808                 if (pcb->hp_cred != NULL
  809                     && kauth_authorize_device(pcb->hp_cred,
  810                     KAUTH_DEVICE_BLUETOOTH_RECV,
  811                     KAUTH_ARG(type), KAUTH_ARG(arg1), NULL, NULL) != 0)
  812                         continue;
  813 
  814                 /*
  815                  * create control messages
  816                  */
  817                 ctlmsg = NULL;
  818                 ctl = &ctlmsg;
  819                 if (pcb->hp_flags & HCI_DIRECTION) {
  820                         int dir = m->m_flags & M_LINK0 ? 1 : 0;
  821 
  822                         *ctl = sbcreatecontrol(&dir, sizeof(dir),
  823                             SCM_HCI_DIRECTION, BTPROTO_HCI);
  824 
  825                         if (*ctl != NULL)
  826                                 ctl = &((*ctl)->m_next);
  827                 }
  828                 if (pcb->hp_socket->so_options & SO_TIMESTAMP) {
  829                         struct timeval tv;
  830 
  831                         microtime(&tv);
  832                         *ctl = sbcreatecontrol(&tv, sizeof(tv),
  833                             SCM_TIMESTAMP, SOL_SOCKET);
  834 
  835                         if (*ctl != NULL)
  836                                 ctl = &((*ctl)->m_next);
  837                 }
  838 
  839                 /*
  840                  * copy to socket
  841                  */
  842                 m0 = m_copypacket(m, M_DONTWAIT);
  843                 if (m0 && sbappendaddr(&pcb->hp_socket->so_rcv,
  844                                 (struct sockaddr *)&sa, m0, ctlmsg)) {
  845                         sorwakeup(pcb->hp_socket);
  846                 } else {
  847                         m_freem(ctlmsg);
  848                         m_freem(m0);
  849                 }
  850         }
  851 }

Cache object: 90de4cfc7a117fc29eecaf3fdc166083


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