[BACK]Return to hci_socket.c CVS log [TXT][DIR] Up to [local] / sys / netbt

Annotation of sys/netbt/hci_socket.c, Revision 1.1.1.1

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

CVSweb