The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


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

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

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: hci_socket.c,v 1.47 2019/09/28 07:10:55 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.47 2019/09/28 07:10:55 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/kmem.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/proc.h>
   49 #include <sys/protosw.h>
   50 #include <sys/socket.h>
   51 #include <sys/socketvar.h>
   52 #include <sys/systm.h>
   53 
   54 #include <netbt/bluetooth.h>
   55 #include <netbt/hci.h>
   56 
   57 /*******************************************************************************
   58  *
   59  * HCI SOCK_RAW Sockets - for control of Bluetooth Devices
   60  *
   61  */
   62 
   63 /*
   64  * the raw HCI protocol control block
   65  */
   66 struct hci_pcb {
   67         struct socket           *hp_socket;     /* socket */
   68         kauth_cred_t            hp_cred;        /* owner credential */
   69         unsigned int            hp_flags;       /* flags */
   70         bdaddr_t                hp_laddr;       /* local address */
   71         bdaddr_t                hp_raddr;       /* remote address */
   72         struct hci_filter       hp_efilter;     /* user event filter */
   73         struct hci_filter       hp_pfilter;     /* user packet filter */
   74         LIST_ENTRY(hci_pcb)     hp_next;        /* next HCI pcb */
   75 };
   76 
   77 /* hp_flags */
   78 #define HCI_DIRECTION           (1<<1)  /* direction control messages */
   79 #define HCI_PROMISCUOUS         (1<<2)  /* listen to all units */
   80 
   81 LIST_HEAD(hci_pcb_list, hci_pcb) hci_pcb = LIST_HEAD_INITIALIZER(hci_pcb);
   82 
   83 /* sysctl defaults */
   84 int hci_sendspace = HCI_CMD_PKT_SIZE;
   85 int hci_recvspace = 4096;
   86 
   87 /* unprivileged commands opcode table */
   88 static const struct {
   89         uint16_t        opcode;
   90         uint8_t         offs;   /* 0 - 63 */
   91         uint8_t         mask;   /* bit 0 - 7 */
   92         uint8_t         length; /* approved length */
   93 } hci_cmds[] = {
   94         { HCI_CMD_INQUIRY,
   95           0,  0x01, sizeof(hci_inquiry_cp) },
   96         { HCI_CMD_REMOTE_NAME_REQ,
   97           2,  0x08, sizeof(hci_remote_name_req_cp) },
   98         { HCI_CMD_READ_REMOTE_FEATURES,
   99           2,  0x20, sizeof(hci_read_remote_features_cp) },
  100         { HCI_CMD_READ_REMOTE_EXTENDED_FEATURES,
  101           2,  0x40, sizeof(hci_read_remote_extended_features_cp) },
  102         { HCI_CMD_READ_REMOTE_VER_INFO,
  103           2,  0x80, sizeof(hci_read_remote_ver_info_cp) },
  104         { HCI_CMD_READ_CLOCK_OFFSET,
  105           3,  0x01, sizeof(hci_read_clock_offset_cp) },
  106         { HCI_CMD_READ_LMP_HANDLE,
  107           3,  0x02, sizeof(hci_read_lmp_handle_cp) },
  108         { HCI_CMD_ROLE_DISCOVERY,
  109           4,  0x80, sizeof(hci_role_discovery_cp) },
  110         { HCI_CMD_READ_LINK_POLICY_SETTINGS,
  111           5,  0x02, sizeof(hci_read_link_policy_settings_cp) },
  112         { HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS,
  113           5,  0x08, 0 },
  114         { HCI_CMD_READ_PIN_TYPE,
  115           6,  0x04, 0 },
  116         { HCI_CMD_READ_LOCAL_NAME,
  117           7,  0x02, 0 },
  118         { HCI_CMD_READ_CON_ACCEPT_TIMEOUT,
  119           7,  0x04, 0 },
  120         { HCI_CMD_READ_PAGE_TIMEOUT,
  121           7,  0x10, 0 },
  122         { HCI_CMD_READ_SCAN_ENABLE,
  123           7,  0x40, 0 },
  124         { HCI_CMD_READ_PAGE_SCAN_ACTIVITY,
  125           8,  0x01, 0 },
  126         { HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY,
  127           8,  0x04, 0 },
  128         { HCI_CMD_READ_AUTH_ENABLE,
  129           8,  0x10, 0 },
  130         { HCI_CMD_READ_ENCRYPTION_MODE,
  131           8,  0x40, 0 },
  132         { HCI_CMD_READ_UNIT_CLASS,
  133           9,  0x01, 0 },
  134         { HCI_CMD_READ_VOICE_SETTING,
  135           9,  0x04, 0 },
  136         { HCI_CMD_READ_AUTO_FLUSH_TIMEOUT,
  137           9,  0x10, sizeof(hci_read_auto_flush_timeout_cp) },
  138         { HCI_CMD_READ_NUM_BROADCAST_RETRANS,
  139           9,  0x40, 0 },
  140         { HCI_CMD_READ_HOLD_MODE_ACTIVITY,
  141           10, 0x01, 0 },
  142         { HCI_CMD_READ_XMIT_LEVEL,
  143           10, 0x04, sizeof(hci_read_xmit_level_cp) },
  144         { HCI_CMD_READ_SCO_FLOW_CONTROL,
  145           10, 0x08, 0 },
  146         { HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT,
  147           11, 0x01, sizeof(hci_read_link_supervision_timeout_cp) },
  148         { HCI_CMD_READ_NUM_SUPPORTED_IAC,
  149           11, 0x04, 0 },
  150         { HCI_CMD_READ_IAC_LAP,
  151           11, 0x08, 0 },
  152         { HCI_CMD_READ_PAGE_SCAN_PERIOD,
  153           11, 0x20, 0 },
  154         { HCI_CMD_READ_PAGE_SCAN,
  155           11, 0x80, 0 },
  156         { HCI_CMD_READ_INQUIRY_SCAN_TYPE,
  157           12, 0x10, 0 },
  158         { HCI_CMD_READ_INQUIRY_MODE,
  159           12, 0x40, 0 },
  160         { HCI_CMD_READ_PAGE_SCAN_TYPE,
  161           13, 0x01, 0 },
  162         { HCI_CMD_READ_AFH_ASSESSMENT,
  163           13, 0x04, 0 },
  164         { HCI_CMD_READ_LOCAL_VER,
  165           14, 0x08, 0 },
  166         { HCI_CMD_READ_LOCAL_COMMANDS,
  167           14, 0x10, 0 },
  168         { HCI_CMD_READ_LOCAL_FEATURES,
  169           14, 0x20, 0 },
  170         { HCI_CMD_READ_LOCAL_EXTENDED_FEATURES,
  171           14, 0x40, sizeof(hci_read_local_extended_features_cp) },
  172         { HCI_CMD_READ_BUFFER_SIZE,
  173           14, 0x80, 0 },
  174         { HCI_CMD_READ_COUNTRY_CODE,
  175           15, 0x01, 0 },
  176         { HCI_CMD_READ_BDADDR,
  177           15, 0x02, 0 },
  178         { HCI_CMD_READ_FAILED_CONTACT_CNTR,
  179           15, 0x04, sizeof(hci_read_failed_contact_cntr_cp) },
  180         { HCI_CMD_READ_LINK_QUALITY,
  181           15, 0x10, sizeof(hci_read_link_quality_cp) },
  182         { HCI_CMD_READ_RSSI,
  183           15, 0x20, sizeof(hci_read_rssi_cp) },
  184         { HCI_CMD_READ_AFH_CHANNEL_MAP,
  185           15, 0x40, sizeof(hci_read_afh_channel_map_cp) },
  186         { HCI_CMD_READ_CLOCK,
  187           15, 0x80, sizeof(hci_read_clock_cp) },
  188         { HCI_CMD_READ_LOOPBACK_MODE,
  189           16, 0x01, 0 },
  190         { HCI_CMD_READ_EXTENDED_INQUIRY_RSP,
  191           17, 0x01, 0 },
  192         { HCI_CMD_READ_SIMPLE_PAIRING_MODE,
  193           17, 0x20, 0 },
  194         { HCI_CMD_READ_INQUIRY_RSP_XMIT_POWER,
  195           18, 0x01, 0 },
  196         { HCI_CMD_READ_DEFAULT_ERRDATA_REPORTING,
  197           18, 0x04, 0 },
  198         { HCI_CMD_READ_ENCRYPTION_KEY_SIZE,
  199           20, 0x10, sizeof(hci_read_encryption_key_size_cp) },
  200 };
  201 
  202 /*
  203  * supply a basic device send/recv policy
  204  */
  205 static int
  206 hci_device_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
  207     void *arg0, void *arg1, void *arg2, void *arg3)
  208 {
  209         int i, result;
  210 
  211         result = KAUTH_RESULT_DEFER;
  212 
  213         switch (action) {
  214         case KAUTH_DEVICE_BLUETOOTH_SEND: {
  215                 struct hci_unit *unit = (struct hci_unit *)arg0;
  216                 hci_cmd_hdr_t *hdr = (hci_cmd_hdr_t *)arg1;
  217 
  218                 /*
  219                  * Allow sending unprivileged commands if the packet size
  220                  * is correct and the unit claims to support it
  221                  */
  222 
  223                 if (hdr->type != HCI_CMD_PKT)
  224                         break;
  225 
  226                 for (i = 0; i < __arraycount(hci_cmds); i++) {
  227                         if (hdr->opcode == hci_cmds[i].opcode
  228                             && hdr->length == hci_cmds[i].length
  229                             && (unit->hci_cmds[hci_cmds[i].offs] & hci_cmds[i].mask)) {
  230                                 result = KAUTH_RESULT_ALLOW;
  231                                 break;
  232                         }
  233                 }
  234 
  235                 break;
  236                 }
  237 
  238         case KAUTH_DEVICE_BLUETOOTH_RECV:
  239                 switch((uint8_t)(uintptr_t)arg0) {
  240                 case HCI_CMD_PKT: {
  241                         uint16_t opcode = (uint16_t)(uintptr_t)arg1;
  242 
  243                         /*
  244                          * Allow to see any unprivileged command packet
  245                          */
  246 
  247                         for (i = 0; i < __arraycount(hci_cmds); i++) {
  248                                 if (opcode == hci_cmds[i].opcode) {
  249                                         result = KAUTH_RESULT_ALLOW;
  250                                         break;
  251                                 }
  252                         }
  253 
  254                         break;
  255                         }
  256 
  257                 case HCI_EVENT_PKT: {
  258                         uint8_t event = (uint8_t)(uintptr_t)arg1;
  259 
  260                         /*
  261                          * Allow to receive most events
  262                          */
  263 
  264                         switch (event) {
  265                         case HCI_EVENT_RETURN_LINK_KEYS:
  266                         case HCI_EVENT_LINK_KEY_NOTIFICATION:
  267                         case HCI_EVENT_USER_CONFIRM_REQ:
  268                         case HCI_EVENT_USER_PASSKEY_NOTIFICATION:
  269                         case HCI_EVENT_VENDOR:
  270                                 break;
  271 
  272                         default:
  273                                 result = KAUTH_RESULT_ALLOW;
  274                                 break;
  275                         }
  276 
  277                         break;
  278                         }
  279 
  280                 case HCI_ACL_DATA_PKT:
  281                 case HCI_SCO_DATA_PKT: {
  282                         /* uint16_t handle = (uint16_t)(uintptr_t)arg1; */
  283                         /*
  284                          * don't normally allow receiving data packets
  285                          */
  286                         break;
  287                         }
  288 
  289                 default:
  290                         break;
  291                 }
  292 
  293                 break;
  294 
  295         default:
  296                 break;
  297         }
  298 
  299         return result;
  300 }
  301 
  302 /*
  303  * HCI protocol init routine,
  304  * - set up a kauth listener to provide basic packet access policy
  305  */
  306 void
  307 hci_init(void)
  308 {
  309 
  310         if (kauth_listen_scope(KAUTH_SCOPE_DEVICE, hci_device_cb, NULL) == NULL)
  311                 panic("Bluetooth HCI: cannot listen on device scope");
  312 }
  313 
  314 /*
  315  * When command packet reaches the device, we can drop
  316  * it from the socket buffer (called from hci_output_acl)
  317  */
  318 void
  319 hci_drop(void *arg)
  320 {
  321         struct socket *so = arg;
  322 
  323         sbdroprecord(&so->so_snd);
  324         sowwakeup(so);
  325 }
  326 
  327 /*
  328  * HCI socket is going away and has some pending packets. We let them
  329  * go by design, but remove the context pointer as it will be invalid
  330  * and we no longer need to be notified.
  331  */
  332 static void
  333 hci_cmdwait_flush(struct socket *so)
  334 {
  335         struct hci_unit *unit;
  336         struct socket *ctx;
  337         struct mbuf *m;
  338 
  339         DPRINTF("flushing %p\n", so);
  340 
  341         SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
  342                 m = MBUFQ_FIRST(&unit->hci_cmdwait);
  343                 while (m != NULL) {
  344                         ctx = M_GETCTX(m, struct socket *);
  345                         if (ctx == so)
  346                                 M_SETCTX(m, NULL);
  347 
  348                         m = MBUFQ_NEXT(m);
  349                 }
  350         }
  351 }
  352 
  353 static int
  354 hci_attach(struct socket *so, int proto)
  355 {
  356         struct hci_pcb *pcb;
  357         int error;
  358 
  359         KASSERT(so->so_pcb == NULL);
  360 
  361         if (so->so_lock == NULL) {
  362                 mutex_obj_hold(bt_lock);
  363                 so->so_lock = bt_lock;
  364                 solock(so);
  365         }
  366         KASSERT(solocked(so));
  367 
  368         error = soreserve(so, hci_sendspace, hci_recvspace);
  369         if (error) {
  370                 return error;
  371         }
  372 
  373         pcb = kmem_zalloc(sizeof(struct hci_pcb), KM_SLEEP);
  374         pcb->hp_cred = kauth_cred_dup(curlwp->l_cred);
  375         pcb->hp_socket = so;
  376 
  377         /*
  378          * Set default user filter. By default, socket only passes
  379          * Command_Complete and Command_Status Events.
  380          */
  381         hci_filter_set(HCI_EVENT_COMMAND_COMPL, &pcb->hp_efilter);
  382         hci_filter_set(HCI_EVENT_COMMAND_STATUS, &pcb->hp_efilter);
  383         hci_filter_set(HCI_EVENT_PKT, &pcb->hp_pfilter);
  384 
  385         LIST_INSERT_HEAD(&hci_pcb, pcb, hp_next);
  386         so->so_pcb = pcb;
  387 
  388         return 0;
  389 }
  390 
  391 static void
  392 hci_detach(struct socket *so)
  393 {
  394         struct hci_pcb *pcb;
  395 
  396         pcb = (struct hci_pcb *)so->so_pcb;
  397         KASSERT(pcb != NULL);
  398 
  399         if (so->so_snd.sb_mb != NULL)
  400                 hci_cmdwait_flush(so);
  401 
  402         if (pcb->hp_cred != NULL)
  403                 kauth_cred_free(pcb->hp_cred);
  404 
  405         so->so_pcb = NULL;
  406         LIST_REMOVE(pcb, hp_next);
  407         kmem_free(pcb, sizeof(*pcb));
  408 }
  409 
  410 static int
  411 hci_accept(struct socket *so, struct sockaddr *nam)
  412 {
  413         KASSERT(solocked(so));
  414 
  415         return EOPNOTSUPP;
  416 }
  417 
  418 static int
  419 hci_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
  420 {
  421         struct hci_pcb *pcb = so->so_pcb;
  422         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  423 
  424         KASSERT(solocked(so));
  425         KASSERT(pcb != NULL);
  426         KASSERT(nam != NULL);
  427 
  428         if (sa->bt_len != sizeof(struct sockaddr_bt))
  429                 return EINVAL;
  430 
  431         if (sa->bt_family != AF_BLUETOOTH)
  432                 return EAFNOSUPPORT;
  433 
  434         bdaddr_copy(&pcb->hp_laddr, &sa->bt_bdaddr);
  435 
  436         if (bdaddr_any(&sa->bt_bdaddr))
  437                 pcb->hp_flags |= HCI_PROMISCUOUS;
  438         else
  439                 pcb->hp_flags &= ~HCI_PROMISCUOUS;
  440 
  441         return 0;
  442 }
  443 
  444 static int
  445 hci_listen(struct socket *so, struct lwp *l)
  446 {
  447         KASSERT(solocked(so));
  448 
  449         return EOPNOTSUPP;
  450 }
  451 
  452 static int
  453 hci_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
  454 {
  455         struct hci_pcb *pcb = so->so_pcb;
  456         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  457 
  458         KASSERT(solocked(so));
  459         KASSERT(pcb != NULL);
  460         KASSERT(nam != NULL);
  461 
  462         if (sa->bt_len != sizeof(struct sockaddr_bt))
  463                 return EINVAL;
  464 
  465         if (sa->bt_family != AF_BLUETOOTH)
  466                 return EAFNOSUPPORT;
  467 
  468         if (hci_unit_lookup(&sa->bt_bdaddr) == NULL)
  469                 return EADDRNOTAVAIL;
  470 
  471         bdaddr_copy(&pcb->hp_raddr, &sa->bt_bdaddr);
  472         soisconnected(so);
  473         return 0;
  474 }
  475 
  476 static int
  477 hci_connect2(struct socket *so, struct socket *so2)
  478 {
  479         KASSERT(solocked(so));
  480 
  481         return EOPNOTSUPP;
  482 }
  483 
  484 static int
  485 hci_disconnect(struct socket *so)
  486 {
  487         struct hci_pcb *pcb = so->so_pcb;
  488 
  489         KASSERT(solocked(so));
  490         KASSERT(pcb != NULL);
  491 
  492         bdaddr_copy(&pcb->hp_raddr, BDADDR_ANY);
  493 
  494         /* XXX we cannot call soisdisconnected() here, as it sets
  495          * SS_CANTRCVMORE and SS_CANTSENDMORE. The problem being,
  496          * that soisconnected() does not clear these and if you
  497          * try to reconnect this socket (which is permitted) you
  498          * get a broken pipe when you try to write any data.
  499          */
  500         so->so_state &= ~SS_ISCONNECTED;
  501         return 0;
  502 }
  503 
  504 static int
  505 hci_shutdown(struct socket *so)
  506 {
  507         KASSERT(solocked(so));
  508 
  509         socantsendmore(so);
  510         return 0;
  511 }
  512 
  513 static int
  514 hci_abort(struct socket *so)
  515 {
  516         KASSERT(solocked(so));
  517 
  518         soisdisconnected(so);
  519         hci_detach(so);
  520         return 0;
  521 }
  522 
  523 static int
  524 hci_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
  525 {
  526         int err;
  527         mutex_enter(bt_lock);
  528         err = hci_ioctl_pcb(cmd, nam);
  529         mutex_exit(bt_lock);
  530         return err;
  531 }
  532 
  533 static int
  534 hci_stat(struct socket *so, struct stat *ub)
  535 {
  536         KASSERT(solocked(so));
  537 
  538         return 0;
  539 }
  540 
  541 static int
  542 hci_peeraddr(struct socket *so, struct sockaddr *nam)
  543 {
  544         struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
  545         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  546 
  547         KASSERT(solocked(so));
  548         KASSERT(pcb != NULL);
  549         KASSERT(nam != NULL);
  550 
  551         memset(sa, 0, sizeof(struct sockaddr_bt));
  552         sa->bt_len = sizeof(struct sockaddr_bt);
  553         sa->bt_family = AF_BLUETOOTH;
  554         bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_raddr);
  555         return 0;
  556 }
  557 
  558 static int
  559 hci_sockaddr(struct socket *so, struct sockaddr *nam)
  560 {
  561         struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
  562         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  563 
  564         KASSERT(solocked(so));
  565         KASSERT(pcb != NULL);
  566         KASSERT(nam != NULL);
  567 
  568         memset(sa, 0, sizeof(struct sockaddr_bt));
  569         sa->bt_len = sizeof(struct sockaddr_bt);
  570         sa->bt_family = AF_BLUETOOTH;
  571         bdaddr_copy(&sa->bt_bdaddr, &pcb->hp_laddr);
  572         return 0;
  573 }
  574 
  575 static int
  576 hci_rcvd(struct socket *so, int flags, struct lwp *l)
  577 {
  578         KASSERT(solocked(so));
  579 
  580         return EOPNOTSUPP;
  581 }
  582 
  583 static int
  584 hci_recvoob(struct socket *so, struct mbuf *m, int flags)
  585 {
  586         KASSERT(solocked(so));
  587 
  588         return EOPNOTSUPP;
  589 }
  590 
  591 static int
  592 hci_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
  593     struct mbuf *control, struct lwp *l)
  594 {
  595         struct hci_pcb *pcb = so->so_pcb;
  596         struct sockaddr_bt *sa = (struct sockaddr_bt *)nam;
  597         struct hci_unit *unit;
  598         struct mbuf *m0;
  599         hci_cmd_hdr_t hdr;
  600         int err = 0;
  601 
  602         KASSERT(solocked(so));
  603         KASSERT(pcb != NULL);
  604         KASSERT(m != NULL);
  605 
  606         if (control) /* have no use for this */
  607                 m_freem(control);
  608 
  609         if (sa) {
  610                 if (sa->bt_len != sizeof(struct sockaddr_bt)) {
  611                         err = EINVAL;
  612                         goto bad;
  613                 }
  614 
  615                 if (sa->bt_family != AF_BLUETOOTH) {
  616                         err = EAFNOSUPPORT;
  617                         goto bad;
  618                 }
  619         }
  620 
  621         /*
  622          * this came from userland, so we check it out first
  623          */
  624 
  625         /* wants at least a header to start with */
  626         if (m->m_pkthdr.len < sizeof(hdr)) {
  627                 err = EMSGSIZE;
  628                 goto bad;
  629         }
  630         m_copydata(m, 0, sizeof(hdr), &hdr);
  631         hdr.opcode = le16toh(hdr.opcode);
  632 
  633         /* only allows CMD packets to be sent */
  634         if (hdr.type != HCI_CMD_PKT) {
  635                 err = EINVAL;
  636                 goto bad;
  637         }
  638 
  639         /* validates packet length */
  640         if (m->m_pkthdr.len != sizeof(hdr) + hdr.length) {
  641                 err = EMSGSIZE;
  642                 goto bad;
  643         }
  644 
  645         /* finds destination */
  646         unit = hci_unit_lookup((sa ? &sa->bt_bdaddr : &pcb->hp_raddr));
  647         if (unit == NULL) {
  648                 err = ENETDOWN;
  649                 goto bad;
  650         }
  651 
  652         /* security checks for unprivileged users */
  653         if (pcb->hp_cred != NULL
  654             && kauth_authorize_device(pcb->hp_cred,
  655             KAUTH_DEVICE_BLUETOOTH_SEND,
  656             unit, &hdr, NULL, NULL) != 0) {
  657                 err = EPERM;
  658                 goto bad;
  659         }
  660 
  661         /* makess a copy for precious to keep */
  662         m0 = m_copypacket(m, M_DONTWAIT);
  663         if (m0 == NULL) {
  664                 err = ENOMEM;
  665                 goto bad;
  666         }
  667         sbappendrecord(&pcb->hp_socket->so_snd, m0);
  668         M_SETCTX(m, pcb->hp_socket);    /* enable drop callback */
  669 
  670         DPRINTFN(2, "(%s) opcode (%03x|%04x)\n", device_xname(unit->hci_dev),
  671                 HCI_OGF(hdr.opcode), HCI_OCF(hdr.opcode));
  672 
  673         /* Sendss it */
  674         if (unit->hci_num_cmd_pkts == 0)
  675                 MBUFQ_ENQUEUE(&unit->hci_cmdwait, m);
  676         else
  677                 hci_output_cmd(unit, m);
  678 
  679         return 0;
  680 
  681 bad:
  682         DPRINTF("packet (%d bytes) not sent (error %d)\n",
  683                         m->m_pkthdr.len, err);
  684         if (m)
  685                 m_freem(m);
  686 
  687         return err;
  688 }
  689 
  690 static int
  691 hci_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
  692 {
  693         KASSERT(solocked(so));
  694 
  695         m_freem(m);
  696         m_freem(control);
  697 
  698         return EOPNOTSUPP;
  699 }
  700 
  701 static int
  702 hci_purgeif(struct socket *so, struct ifnet *ifp)
  703 {
  704 
  705         return EOPNOTSUPP;
  706 }
  707 
  708 /*
  709  * get/set socket options
  710  */
  711 int
  712 hci_ctloutput(int req, struct socket *so, struct sockopt *sopt)
  713 {
  714         struct hci_pcb *pcb = (struct hci_pcb *)so->so_pcb;
  715         int optval, err = 0;
  716 
  717         DPRINTFN(2, "req %s\n", prcorequests[req]);
  718 
  719         if (pcb == NULL)
  720                 return EINVAL;
  721 
  722         if (sopt->sopt_level != BTPROTO_HCI)
  723                 return ENOPROTOOPT;
  724 
  725         switch(req) {
  726         case PRCO_GETOPT:
  727                 switch (sopt->sopt_name) {
  728                 case SO_HCI_EVT_FILTER:
  729                         err = sockopt_set(sopt, &pcb->hp_efilter,
  730                             sizeof(struct hci_filter));
  731 
  732                         break;
  733 
  734                 case SO_HCI_PKT_FILTER:
  735                         err = sockopt_set(sopt, &pcb->hp_pfilter,
  736                             sizeof(struct hci_filter));
  737 
  738                         break;
  739 
  740                 case SO_HCI_DIRECTION:
  741                         err = sockopt_setint(sopt,
  742                             (pcb->hp_flags & HCI_DIRECTION ? 1 : 0));
  743 
  744                         break;
  745 
  746                 default:
  747                         err = ENOPROTOOPT;
  748                         break;
  749                 }
  750                 break;
  751 
  752         case PRCO_SETOPT:
  753                 switch (sopt->sopt_name) {
  754                 case SO_HCI_EVT_FILTER: /* set event filter */
  755                         err = sockopt_get(sopt, &pcb->hp_efilter,
  756                             sizeof(pcb->hp_efilter));
  757 
  758                         break;
  759 
  760                 case SO_HCI_PKT_FILTER: /* set packet filter */
  761                         err = sockopt_get(sopt, &pcb->hp_pfilter,
  762                             sizeof(pcb->hp_pfilter));
  763 
  764                         break;
  765 
  766                 case SO_HCI_DIRECTION:  /* request direction ctl messages */
  767                         err = sockopt_getint(sopt, &optval);
  768                         if (err)
  769                                 break;
  770 
  771                         if (optval)
  772                                 pcb->hp_flags |= HCI_DIRECTION;
  773                         else
  774                                 pcb->hp_flags &= ~HCI_DIRECTION;
  775                         break;
  776 
  777                 default:
  778                         err = ENOPROTOOPT;
  779                         break;
  780                 }
  781                 break;
  782 
  783         default:
  784                 err = ENOPROTOOPT;
  785                 break;
  786         }
  787 
  788         return err;
  789 }
  790 
  791 /*
  792  * HCI mbuf tap routine
  793  *
  794  * copy packets to any raw HCI sockets that wish (and are
  795  * permitted) to see them
  796  */
  797 void
  798 hci_mtap(struct mbuf *m, struct hci_unit *unit)
  799 {
  800         struct hci_pcb *pcb;
  801         struct mbuf *m0, *ctlmsg, **ctl;
  802         struct sockaddr_bt sa;
  803         uint8_t type;
  804         uint8_t event;
  805         uint16_t arg1;
  806 
  807         KASSERT(m->m_len >= sizeof(type));
  808 
  809         type = *mtod(m, uint8_t *);
  810 
  811         memset(&sa, 0, sizeof(sa));
  812         sa.bt_len = sizeof(struct sockaddr_bt);
  813         sa.bt_family = AF_BLUETOOTH;
  814         bdaddr_copy(&sa.bt_bdaddr, &unit->hci_bdaddr);
  815 
  816         LIST_FOREACH(pcb, &hci_pcb, hp_next) {
  817                 /*
  818                  * filter according to source address
  819                  */
  820                 if ((pcb->hp_flags & HCI_PROMISCUOUS) == 0
  821                     && bdaddr_same(&pcb->hp_laddr, &sa.bt_bdaddr) == 0)
  822                         continue;
  823 
  824                 /*
  825                  * filter according to packet type filter
  826                  */
  827                 if (hci_filter_test(type, &pcb->hp_pfilter) == 0)
  828                         continue;
  829 
  830                 /*
  831                  * filter according to event/security filters
  832                  */
  833                 switch(type) {
  834                 case HCI_EVENT_PKT:
  835                         KASSERT(m->m_len >= sizeof(hci_event_hdr_t));
  836 
  837                         event = mtod(m, hci_event_hdr_t *)->event;
  838 
  839                         if (hci_filter_test(event, &pcb->hp_efilter) == 0)
  840                                 continue;
  841 
  842                         arg1 = event;
  843                         break;
  844 
  845                 case HCI_CMD_PKT:
  846                         KASSERT(m->m_len >= sizeof(hci_cmd_hdr_t));
  847                         arg1 = le16toh(mtod(m, hci_cmd_hdr_t *)->opcode);
  848                         break;
  849 
  850                 case HCI_ACL_DATA_PKT:
  851                         KASSERT(m->m_len >= sizeof(hci_acldata_hdr_t));
  852                         arg1 = le16toh(mtod(m, hci_acldata_hdr_t *)->con_handle);
  853                         arg1 = HCI_CON_HANDLE(arg1);
  854                         break;
  855 
  856                 case HCI_SCO_DATA_PKT:
  857                         KASSERT(m->m_len >= sizeof(hci_scodata_hdr_t));
  858                         arg1 = le16toh(mtod(m, hci_scodata_hdr_t *)->con_handle);
  859                         arg1 = HCI_CON_HANDLE(arg1);
  860                         break;
  861 
  862                 default:
  863                         arg1 = 0;
  864                         break;
  865                 }
  866 
  867                 if (pcb->hp_cred != NULL
  868                     && kauth_authorize_device(pcb->hp_cred,
  869                     KAUTH_DEVICE_BLUETOOTH_RECV,
  870                     KAUTH_ARG(type), KAUTH_ARG(arg1), NULL, NULL) != 0)
  871                         continue;
  872 
  873                 /*
  874                  * create control messages
  875                  */
  876                 ctlmsg = NULL;
  877                 ctl = &ctlmsg;
  878                 if (pcb->hp_flags & HCI_DIRECTION) {
  879                         int dir = m->m_flags & M_LINK0 ? 1 : 0;
  880 
  881                         *ctl = sbcreatecontrol(&dir, sizeof(dir),
  882                             SCM_HCI_DIRECTION, BTPROTO_HCI);
  883 
  884                         if (*ctl != NULL)
  885                                 ctl = &((*ctl)->m_next);
  886                 }
  887                 if (pcb->hp_socket->so_options & SO_TIMESTAMP) {
  888                         struct timeval tv;
  889 
  890                         microtime(&tv);
  891                         *ctl = sbcreatecontrol(&tv, sizeof(tv),
  892                             SCM_TIMESTAMP, SOL_SOCKET);
  893 
  894                         if (*ctl != NULL)
  895                                 ctl = &((*ctl)->m_next);
  896                 }
  897 
  898                 /*
  899                  * copy to socket
  900                  */
  901                 m0 = m_copypacket(m, M_DONTWAIT);
  902                 if (m0 && sbappendaddr(&pcb->hp_socket->so_rcv,
  903                                 (struct sockaddr *)&sa, m0, ctlmsg)) {
  904                         sorwakeup(pcb->hp_socket);
  905                 } else {
  906                         m_freem(ctlmsg);
  907                         m_freem(m0);
  908                 }
  909         }
  910 }
  911 
  912 PR_WRAP_USRREQS(hci)
  913 
  914 #define hci_attach              hci_attach_wrapper
  915 #define hci_detach              hci_detach_wrapper
  916 #define hci_accept              hci_accept_wrapper
  917 #define hci_bind                hci_bind_wrapper
  918 #define hci_listen              hci_listen_wrapper
  919 #define hci_connect             hci_connect_wrapper
  920 #define hci_connect2            hci_connect2_wrapper
  921 #define hci_disconnect          hci_disconnect_wrapper
  922 #define hci_shutdown            hci_shutdown_wrapper
  923 #define hci_abort               hci_abort_wrapper
  924 #define hci_ioctl               hci_ioctl_wrapper
  925 #define hci_stat                hci_stat_wrapper
  926 #define hci_peeraddr            hci_peeraddr_wrapper
  927 #define hci_sockaddr            hci_sockaddr_wrapper
  928 #define hci_rcvd                hci_rcvd_wrapper
  929 #define hci_recvoob             hci_recvoob_wrapper
  930 #define hci_send                hci_send_wrapper
  931 #define hci_sendoob             hci_sendoob_wrapper
  932 #define hci_purgeif             hci_purgeif_wrapper
  933 
  934 const struct pr_usrreqs hci_usrreqs = {
  935         .pr_attach      = hci_attach,
  936         .pr_detach      = hci_detach,
  937         .pr_accept      = hci_accept,
  938         .pr_bind        = hci_bind,
  939         .pr_listen      = hci_listen,
  940         .pr_connect     = hci_connect,
  941         .pr_connect2    = hci_connect2,
  942         .pr_disconnect  = hci_disconnect,
  943         .pr_shutdown    = hci_shutdown,
  944         .pr_abort       = hci_abort,
  945         .pr_ioctl       = hci_ioctl,
  946         .pr_stat        = hci_stat,
  947         .pr_peeraddr    = hci_peeraddr,
  948         .pr_sockaddr    = hci_sockaddr,
  949         .pr_rcvd        = hci_rcvd,
  950         .pr_recvoob     = hci_recvoob,
  951         .pr_send        = hci_send,
  952         .pr_sendoob     = hci_sendoob,
  953         .pr_purgeif     = hci_purgeif,
  954 };

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.