request and keep a mask of supported commands per unit in order

to block unsupported HCI commands sent by unprivileged users
reaching the device.
This commit is contained in:
plunky 2007-12-30 18:26:42 +00:00
parent 47708a0e13
commit aeab3db895
6 changed files with 374 additions and 109 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: bluetooth.4,v 1.9 2007/11/28 20:16:12 plunky Exp $
.\" $NetBSD: bluetooth.4,v 1.10 2007/12/30 18:26:42 plunky Exp $
.\"
.\" Copyright (c) 2006 Itronix Inc.
.\" All rights reserved.
@ -30,7 +30,7 @@
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.\"
.Dd November 20, 2007
.Dd December 28, 2007
.Dt BLUETOOTH 4
.Os
.Sh NAME
@ -329,6 +329,7 @@ struct btreq {
#define BTF_INIT_BUFFER_SIZE (1\*[Lt]\*[Lt]6) /* waiting for buffer size */
#define BTF_INIT_FEATURES (1\*[Lt]\*[Lt]7) /* waiting for features */
#define BTF_NOOP_ON_RESET (1\*[Lt]\*[Lt]8) /* wait for No-op on reset */
#define BTF_INIT_COMMANDS (1\*[Lt]\*[Lt]9) /* waiting for supported commands */
struct bt_stats {
uint32_t err_tx;

View File

@ -1,4 +1,4 @@
/* $NetBSD: hci.h,v 1.20 2007/12/29 11:30:27 plunky Exp $ */
/* $NetBSD: hci.h,v 1.21 2007/12/30 18:26:42 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@ -54,7 +54,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: hci.h,v 1.20 2007/12/29 11:30:27 plunky Exp $
* $Id: hci.h,v 1.21 2007/12/30 18:26:42 plunky Exp $
* $FreeBSD: src/sys/netgraph/bluetooth/include/ng_hci.h,v 1.6 2005/01/07 01:45:43 imp Exp $
*/
@ -90,6 +90,7 @@
#define HCI_FEATURES_SIZE 8 /* LMP features */
#define HCI_UNIT_NAME_SIZE 248 /* unit name size */
#define HCI_DEVNAME_SIZE 16 /* same as dv_xname */
#define HCI_COMMANDS_SIZE 64 /* supported commands mask */
/* HCI specification */
#define HCI_SPEC_V10 0x00 /* v1.0 */
@ -1413,7 +1414,7 @@ typedef struct {
/* No command parameter(s) */
typedef struct {
uint8_t status; /* 0x00 - success */
uint8_t commands[64]; /* opcode bitmask */
uint8_t commands[HCI_COMMANDS_SIZE]; /* opcode bitmask */
} __attribute__ ((__packed__)) hci_read_local_commands_rp;
#define HCI_OCF_READ_LOCAL_FEATURES 0x0003
@ -2011,8 +2012,13 @@ struct btreq {
#define BTF_INIT_BDADDR (1<<5) /* waiting for bdaddr */
#define BTF_INIT_BUFFER_SIZE (1<<6) /* waiting for buffer size */
#define BTF_INIT_FEATURES (1<<7) /* waiting for features */
#define BTF_INIT (BTF_INIT_BDADDR | BTF_INIT_BUFFER_SIZE | BTF_INIT_FEATURES)
#define BTF_POWER_UP_NOOP (1<<8) /* should wait for No-op on power up */
#define BTF_INIT_COMMANDS (1<<9) /* waiting for supported commands */
#define BTF_INIT (BTF_INIT_BDADDR \
| BTF_INIT_BUFFER_SIZE \
| BTF_INIT_FEATURES \
| BTF_INIT_COMMANDS)
/**************************************************************************
**************************************************************************
@ -2132,6 +2138,8 @@ struct hci_unit {
uint16_t hci_link_policy; /* link policy */
uint16_t hci_lmp_mask; /* link policy capabilities */
uint8_t hci_cmds[HCI_COMMANDS_SIZE]; /* opcode bitmask */
/* flow control */
uint16_t hci_max_acl_size; /* ACL payload mtu */
uint16_t hci_num_acl_pkts; /* free ACL packet buffers */

View File

@ -1,4 +1,4 @@
/* $NetBSD: hci_event.c,v 1.12 2007/11/28 21:46:52 plunky Exp $ */
/* $NetBSD: hci_event.c,v 1.13 2007/12/30 18:26:42 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: hci_event.c,v 1.12 2007/11/28 21:46:52 plunky Exp $");
__KERNEL_RCSID(0, "$NetBSD: hci_event.c,v 1.13 2007/12/30 18:26:42 plunky Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@ -59,6 +59,8 @@ static void hci_event_read_clock_offset_compl(struct hci_unit *, struct mbuf *);
static void hci_cmd_read_bdaddr(struct hci_unit *, struct mbuf *);
static void hci_cmd_read_buffer_size(struct hci_unit *, struct mbuf *);
static void hci_cmd_read_local_features(struct hci_unit *, struct mbuf *);
static void hci_cmd_read_local_ver(struct hci_unit *, struct mbuf *);
static void hci_cmd_read_local_commands(struct hci_unit *, struct mbuf *);
static void hci_cmd_reset(struct hci_unit *, struct mbuf *);
#ifdef BLUETOOTH_DEBUG
@ -331,6 +333,14 @@ hci_event_command_compl(struct hci_unit *unit, struct mbuf *m)
hci_cmd_read_local_features(unit, m);
break;
case HCI_CMD_READ_LOCAL_VER:
hci_cmd_read_local_ver(unit, m);
break;
case HCI_CMD_READ_LOCAL_COMMANDS:
hci_cmd_read_local_commands(unit, m);
break;
case HCI_CMD_RESET:
hci_cmd_reset(unit, m);
break;
@ -965,6 +975,59 @@ hci_cmd_read_local_features(struct hci_unit *unit, struct mbuf *m)
unit->hci_acl_mask, unit->hci_sco_mask);
}
/*
* process results of read_local_ver command_complete event
*
* reading local supported commands is only supported from 1.2 spec
*/
static void
hci_cmd_read_local_ver(struct hci_unit *unit, struct mbuf *m)
{
hci_read_local_ver_rp rp;
KASSERT(m->m_pkthdr.len >= sizeof(rp));
m_copydata(m, 0, sizeof(rp), &rp);
m_adj(m, sizeof(rp));
if (rp.status != 0)
return;
if ((unit->hci_flags & BTF_INIT_COMMANDS) == 0)
return;
if (rp.hci_version < HCI_SPEC_V12) {
unit->hci_flags &= ~BTF_INIT_COMMANDS;
wakeup(unit);
return;
}
hci_send_cmd(unit, HCI_CMD_READ_LOCAL_COMMANDS, NULL, 0);
}
/*
* process results of read_local_commands command_complete event
*/
static void
hci_cmd_read_local_commands(struct hci_unit *unit, struct mbuf *m)
{
hci_read_local_commands_rp rp;
KASSERT(m->m_pkthdr.len >= sizeof(rp));
m_copydata(m, 0, sizeof(rp), &rp);
m_adj(m, sizeof(rp));
if (rp.status != 0)
return;
if ((unit->hci_flags & BTF_INIT_COMMANDS) == 0)
return;
unit->hci_flags &= ~BTF_INIT_COMMANDS;
memcpy(unit->hci_cmds, rp.commands, HCI_COMMANDS_SIZE);
wakeup(unit);
}
/*
* process results of reset command_complete event
*
@ -1009,4 +1072,7 @@ hci_cmd_reset(struct hci_unit *unit, struct mbuf *m)
if (hci_send_cmd(unit, HCI_CMD_READ_LOCAL_FEATURES, NULL, 0))
return;
if (hci_send_cmd(unit, HCI_CMD_READ_LOCAL_VER, NULL, 0))
return;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: hci_socket.c,v 1.12 2007/11/10 23:12:23 plunky Exp $ */
/* $NetBSD: hci_socket.c,v 1.13 2007/12/30 18:26:42 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: hci_socket.c,v 1.12 2007/11/10 23:12:23 plunky Exp $");
__KERNEL_RCSID(0, "$NetBSD: hci_socket.c,v 1.13 2007/12/30 18:26:42 plunky Exp $");
/* load symbolic names */
#ifdef BLUETOOTH_DEBUG
@ -83,104 +83,274 @@ LIST_HEAD(hci_pcb_list, hci_pcb) hci_pcb = LIST_HEAD_INITIALIZER(hci_pcb);
int hci_sendspace = HCI_CMD_PKT_SIZE;
int hci_recvspace = 4096;
/* supported commands opcode table */
static const struct {
uint16_t opcode;
uint8_t offs; /* 0 - 63 */
uint8_t mask; /* bit 0 - 7 */
int16_t length; /* -1 if privileged */
} hci_cmds[] = {
{ HCI_CMD_INQUIRY,
0, 0x01, sizeof(hci_inquiry_cp) },
{ HCI_CMD_INQUIRY_CANCEL,
0, 0x02, -1 },
{ HCI_CMD_PERIODIC_INQUIRY,
0, 0x04, -1 },
{ HCI_CMD_EXIT_PERIODIC_INQUIRY,
0, 0x08, -1 },
{ HCI_CMD_CREATE_CON,
0, 0x10, -1 },
{ HCI_CMD_DISCONNECT,
0, 0x20, -1 },
{ HCI_CMD_ADD_SCO_CON,
0, 0x40, -1 },
{ HCI_CMD_CREATE_CON_CANCEL,
0, 0x80, -1 },
{ HCI_CMD_ACCEPT_CON,
1, 0x01, -1 },
{ HCI_CMD_REJECT_CON,
1, 0x02, -1 },
{ HCI_CMD_LINK_KEY_REP,
1, 0x04, -1 },
{ HCI_CMD_LINK_KEY_NEG_REP,
1, 0x08, -1 },
{ HCI_CMD_PIN_CODE_REP,
1, 0x10, -1 },
{ HCI_CMD_PIN_CODE_NEG_REP,
1, 0x20, -1 },
{ HCI_CMD_CHANGE_CON_PACKET_TYPE,
1, 0x40, -1 },
{ HCI_CMD_AUTH_REQ,
1, 0x80, -1 },
{ HCI_CMD_SET_CON_ENCRYPTION,
2, 0x01, -1 },
{ HCI_CMD_CHANGE_CON_LINK_KEY,
2, 0x02, -1 },
{ HCI_CMD_MASTER_LINK_KEY,
2, 0x04, -1 },
{ HCI_CMD_REMOTE_NAME_REQ,
2, 0x08, sizeof(hci_remote_name_req_cp) },
{ HCI_CMD_REMOTE_NAME_REQ_CANCEL,
2, 0x10, -1 },
{ HCI_CMD_READ_REMOTE_FEATURES,
2, 0x20, sizeof(hci_read_remote_features_cp) },
{ HCI_CMD_READ_REMOTE_EXTENDED_FEATURES,
2, 0x40, sizeof(hci_read_remote_extended_features_cp) },
{ HCI_CMD_READ_REMOTE_VER_INFO,
2, 0x80, sizeof(hci_read_remote_ver_info_cp) },
{ HCI_CMD_READ_CLOCK_OFFSET,
3, 0x01, sizeof(hci_read_clock_offset_cp) },
{ HCI_CMD_READ_LMP_HANDLE,
3, 0x02, sizeof(hci_read_lmp_handle_cp) },
{ HCI_CMD_HOLD_MODE,
4, 0x02, -1 },
{ HCI_CMD_SNIFF_MODE,
4, 0x04, -1 },
{ HCI_CMD_EXIT_SNIFF_MODE,
4, 0x08, -1 },
{ HCI_CMD_PARK_MODE,
4, 0x10, -1 },
{ HCI_CMD_EXIT_PARK_MODE,
4, 0x20, -1 },
{ HCI_CMD_QOS_SETUP,
4, 0x40, -1 },
{ HCI_CMD_ROLE_DISCOVERY,
4, 0x80, sizeof(hci_role_discovery_cp) },
{ HCI_CMD_SWITCH_ROLE,
5, 0x01, -1 },
{ HCI_CMD_READ_LINK_POLICY_SETTINGS,
5, 0x02, sizeof(hci_read_link_policy_settings_cp) },
{ HCI_CMD_WRITE_LINK_POLICY_SETTINGS,
5, 0x04, -1 },
{ HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS,
5, 0x08, 0 },
{ HCI_CMD_WRITE_DEFAULT_LINK_POLICY_SETTINGS,
5, 0x10, -1 },
{ HCI_CMD_FLOW_SPECIFICATION,
5, 0x20, -1 },
{ HCI_CMD_SET_EVENT_MASK,
5, 0x40, -1 },
{ HCI_CMD_RESET,
5, 0x80, -1 },
{ HCI_CMD_SET_EVENT_FILTER,
6, 0x01, -1 },
{ HCI_CMD_FLUSH,
6, 0x02, -1 },
{ HCI_CMD_READ_PIN_TYPE,
6, 0x04, 0 },
{ HCI_CMD_WRITE_PIN_TYPE,
6, 0x08, -1 },
{ HCI_CMD_CREATE_NEW_UNIT_KEY,
6, 0x10, -1 },
{ HCI_CMD_READ_STORED_LINK_KEY,
6, 0x20, -1 },
{ HCI_CMD_WRITE_STORED_LINK_KEY,
6, 0x40, -1 },
{ HCI_CMD_DELETE_STORED_LINK_KEY,
6, 0x80, -1 },
{ HCI_CMD_WRITE_LOCAL_NAME,
7, 0x01, -1 },
{ HCI_CMD_READ_LOCAL_NAME,
7, 0x02, 0 },
{ HCI_CMD_READ_CON_ACCEPT_TIMEOUT,
7, 0x04, 0 },
{ HCI_CMD_WRITE_CON_ACCEPT_TIMEOUT,
7, 0x08, -1 },
{ HCI_CMD_READ_PAGE_TIMEOUT,
7, 0x10, 0 },
{ HCI_CMD_WRITE_PAGE_TIMEOUT,
7, 0x20, -1 },
{ HCI_CMD_READ_SCAN_ENABLE,
7, 0x40, 0 },
{ HCI_CMD_WRITE_SCAN_ENABLE,
7, 0x80, -1 },
{ HCI_CMD_READ_PAGE_SCAN_ACTIVITY,
8, 0x01, 0 },
{ HCI_CMD_WRITE_PAGE_SCAN_ACTIVITY,
8, 0x02, -1 },
{ HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY,
8, 0x04, 0 },
{ HCI_CMD_WRITE_INQUIRY_SCAN_ACTIVITY,
8, 0x08, -1 },
{ HCI_CMD_READ_AUTH_ENABLE,
8, 0x10, 0 },
{ HCI_CMD_WRITE_AUTH_ENABLE,
8, 0x20, -1 },
{ HCI_CMD_READ_ENCRYPTION_MODE,
8, 0x40, 0 },
{ HCI_CMD_WRITE_ENCRYPTION_MODE,
8, 0x80, -1 },
{ HCI_CMD_READ_UNIT_CLASS,
9, 0x01, 0 },
{ HCI_CMD_WRITE_UNIT_CLASS,
9, 0x02, -1 },
{ HCI_CMD_READ_VOICE_SETTING,
9, 0x04, 0 },
{ HCI_CMD_WRITE_VOICE_SETTING,
9, 0x08, -1 },
{ HCI_CMD_READ_AUTO_FLUSH_TIMEOUT,
9, 0x10, sizeof(hci_read_auto_flush_timeout_cp) },
{ HCI_CMD_WRITE_AUTO_FLUSH_TIMEOUT,
9, 0x20, -1 },
{ HCI_CMD_READ_NUM_BROADCAST_RETRANS,
9, 0x40, 0 },
{ HCI_CMD_WRITE_NUM_BROADCAST_RETRANS,
9, 0x80, -1 },
{ HCI_CMD_READ_HOLD_MODE_ACTIVITY,
10, 0x01, 0 },
{ HCI_CMD_WRITE_HOLD_MODE_ACTIVITY,
10, 0x02, -1 },
{ HCI_CMD_READ_XMIT_LEVEL,
10, 0x04, sizeof(hci_read_xmit_level_cp) },
{ HCI_CMD_READ_SCO_FLOW_CONTROL,
10, 0x08, 0 },
{ HCI_CMD_WRITE_SCO_FLOW_CONTROL,
10, 0x10, -1 },
{ HCI_CMD_HC2H_FLOW_CONTROL,
10, 0x20, -1 },
{ HCI_CMD_HOST_BUFFER_SIZE,
10, 0x40, -1 },
{ HCI_CMD_HOST_NUM_COMPL_PKTS,
10, 0x80, -1 },
{ HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT,
11, 0x01, sizeof(hci_read_link_supervision_timeout_cp) },
{ HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT,
11, 0x02, -1 },
{ HCI_CMD_READ_NUM_SUPPORTED_IAC,
11, 0x04, 0 },
{ HCI_CMD_READ_IAC_LAP,
11, 0x08, 0 },
{ HCI_CMD_WRITE_IAC_LAP,
11, 0x10, -1 },
{ HCI_CMD_READ_PAGE_SCAN_PERIOD,
11, 0x20, 0 },
{ HCI_CMD_WRITE_PAGE_SCAN_PERIOD,
11, 0x40, -1 },
{ HCI_CMD_READ_PAGE_SCAN,
11, 0x80, 0 },
{ HCI_CMD_WRITE_PAGE_SCAN,
12, 0x01, -1 },
{ HCI_CMD_SET_AFH_CLASSIFICATION,
12, 0x02, -1 },
{ HCI_CMD_READ_INQUIRY_SCAN_TYPE,
12, 0x10, 0 },
{ HCI_CMD_WRITE_INQUIRY_SCAN_TYPE,
12, 0x20, -1 },
{ HCI_CMD_READ_INQUIRY_MODE,
12, 0x40, 0 },
{ HCI_CMD_WRITE_INQUIRY_MODE,
12, 0x80, -1 },
{ HCI_CMD_READ_PAGE_SCAN_TYPE,
13, 0x01, 0 },
{ HCI_CMD_WRITE_PAGE_SCAN_TYPE,
13, 0x02, -1 },
{ HCI_CMD_READ_AFH_ASSESSMENT,
13, 0x04, 0 },
{ HCI_CMD_WRITE_AFH_ASSESSMENT,
13, 0x08, -1 },
{ HCI_CMD_READ_LOCAL_VER,
14, 0x08, 0 },
{ HCI_CMD_READ_LOCAL_COMMANDS,
14, 0x10, 0 },
{ HCI_CMD_READ_LOCAL_FEATURES,
14, 0x20, 0 },
{ HCI_CMD_READ_LOCAL_EXTENDED_FEATURES,
14, 0x40, sizeof(hci_read_local_extended_features_cp) },
{ HCI_CMD_READ_BUFFER_SIZE,
14, 0x80, 0 },
{ HCI_CMD_READ_COUNTRY_CODE,
15, 0x01, 0 },
{ HCI_CMD_READ_BDADDR,
15, 0x02, 0 },
{ HCI_CMD_READ_FAILED_CONTACT_CNTR,
15, 0x04, sizeof(hci_read_failed_contact_cntr_cp) },
{ HCI_CMD_RESET_FAILED_CONTACT_CNTR,
15, 0x08, -1 },
{ HCI_CMD_READ_LINK_QUALITY,
15, 0x10, sizeof(hci_read_link_quality_cp) },
{ HCI_CMD_READ_RSSI,
15, 0x20, sizeof(hci_read_rssi_cp) },
{ HCI_CMD_READ_AFH_CHANNEL_MAP,
15, 0x40, sizeof(hci_read_afh_channel_map_cp) },
{ HCI_CMD_READ_CLOCK,
15, 0x80, sizeof(hci_read_clock_cp) },
{ HCI_CMD_READ_LOOPBACK_MODE,
16, 0x01, 0 },
{ HCI_CMD_WRITE_LOOPBACK_MODE,
16, 0x02, -1 },
{ HCI_CMD_ENABLE_UNIT_UNDER_TEST,
16, 0x04, -1 },
{ HCI_CMD_SETUP_SCO_CON,
16, 0x08, -1 },
{ HCI_CMD_ACCEPT_SCO_CON_REQ,
16, 0x10, -1 },
{ HCI_CMD_REJECT_SCO_CON_REQ,
16, 0x20, -1 },
};
/*
* Security filter routines for unprivileged users.
* Allow all but a few critical events, and only permit read commands.
* If a unit is given, verify the command is supported.
*/
static int
hci_security_check_opcode(uint16_t opcode)
hci_security_check_opcode(struct hci_unit *unit, uint16_t opcode)
{
int i;
switch (opcode) {
/* Link control */
case HCI_CMD_INQUIRY:
return sizeof(hci_inquiry_cp);
case HCI_CMD_REMOTE_NAME_REQ:
return sizeof(hci_remote_name_req_cp);
case HCI_CMD_READ_REMOTE_FEATURES:
return sizeof(hci_read_remote_features_cp);
case HCI_CMD_READ_REMOTE_EXTENDED_FEATURES:
return sizeof(hci_read_remote_extended_features_cp);
case HCI_CMD_READ_REMOTE_VER_INFO:
return sizeof(hci_read_remote_ver_info_cp);
case HCI_CMD_READ_CLOCK_OFFSET:
return sizeof(hci_read_clock_offset_cp);
case HCI_CMD_READ_LMP_HANDLE:
return sizeof(hci_read_lmp_handle_cp);
for (i = 0 ; i < __arraycount(hci_cmds) ; i++) {
if (opcode != hci_cmds[i].opcode)
continue;
/* Link policy */
case HCI_CMD_ROLE_DISCOVERY:
return sizeof(hci_role_discovery_cp);
case HCI_CMD_READ_LINK_POLICY_SETTINGS:
return sizeof(hci_read_link_policy_settings_cp);
case HCI_CMD_READ_DEFAULT_LINK_POLICY_SETTINGS:
return 0; /* No command parameters */
if (unit == NULL
|| (unit->hci_cmds[hci_cmds[i].offs] & hci_cmds[i].mask))
return hci_cmds[i].length;
/* Host controller and baseband */
case HCI_CMD_READ_PIN_TYPE:
case HCI_CMD_READ_LOCAL_NAME:
case HCI_CMD_READ_CON_ACCEPT_TIMEOUT:
case HCI_CMD_READ_PAGE_TIMEOUT:
case HCI_CMD_READ_SCAN_ENABLE:
case HCI_CMD_READ_PAGE_SCAN_ACTIVITY:
case HCI_CMD_READ_INQUIRY_SCAN_ACTIVITY:
case HCI_CMD_READ_AUTH_ENABLE:
case HCI_CMD_READ_ENCRYPTION_MODE:
case HCI_CMD_READ_UNIT_CLASS:
case HCI_CMD_READ_VOICE_SETTING:
return 0; /* No command parameters */
case HCI_CMD_READ_AUTO_FLUSH_TIMEOUT:
return sizeof(hci_read_auto_flush_timeout_cp);
case HCI_CMD_READ_NUM_BROADCAST_RETRANS:
case HCI_CMD_READ_HOLD_MODE_ACTIVITY:
return 0; /* No command parameters */
case HCI_CMD_READ_XMIT_LEVEL:
return sizeof(hci_read_xmit_level_cp);
case HCI_CMD_READ_SCO_FLOW_CONTROL:
return 0; /* No command parameters */
case HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT:
return sizeof(hci_read_link_supervision_timeout_cp);
case HCI_CMD_READ_NUM_SUPPORTED_IAC:
case HCI_CMD_READ_IAC_LAP:
case HCI_CMD_READ_PAGE_SCAN_PERIOD:
case HCI_CMD_READ_PAGE_SCAN:
case HCI_CMD_READ_INQUIRY_SCAN_TYPE:
case HCI_CMD_READ_INQUIRY_MODE:
case HCI_CMD_READ_PAGE_SCAN_TYPE:
case HCI_CMD_READ_AFH_ASSESSMENT:
return 0; /* No command parameters */
/* Informational */
case HCI_CMD_READ_LOCAL_VER:
case HCI_CMD_READ_LOCAL_COMMANDS:
case HCI_CMD_READ_LOCAL_FEATURES:
return 0; /* No command parameters */
case HCI_CMD_READ_LOCAL_EXTENDED_FEATURES:
return sizeof(hci_read_local_extended_features_cp);
case HCI_CMD_READ_BUFFER_SIZE:
case HCI_CMD_READ_COUNTRY_CODE:
case HCI_CMD_READ_BDADDR:
return 0; /* No command parameters */
/* Status */
case HCI_CMD_READ_FAILED_CONTACT_CNTR:
return sizeof(hci_read_failed_contact_cntr_cp);
case HCI_CMD_READ_LINK_QUALITY:
return sizeof(hci_read_link_quality_cp);
case HCI_CMD_READ_RSSI:
return sizeof(hci_read_rssi_cp);
case HCI_CMD_READ_AFH_CHANNEL_MAP:
return sizeof(hci_read_afh_channel_map_cp);
case HCI_CMD_READ_CLOCK:
return sizeof(hci_read_clock_cp);
/* Testing */
case HCI_CMD_READ_LOOPBACK_MODE:
return 0; /* No command parameters */
break;
}
return -1; /* disallowed */
return -1;
}
static int
@ -257,6 +427,7 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
goto bad;
}
m_copydata(m, 0, sizeof(hdr), &hdr);
hdr.opcode = le16toh(hdr.opcode);
/* only allows CMD packets to be sent */
if (hdr.type != HCI_CMD_PKT) {
@ -270,13 +441,6 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
goto bad;
}
/* security checks for unprivileged users */
if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
&& hci_security_check_opcode(le16toh(hdr.opcode)) != hdr.length) {
err = EPERM;
goto bad;
}
/* finds destination */
unit = hci_unit_lookup(addr);
if (unit == NULL) {
@ -284,6 +448,13 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
goto bad;
}
/* security checks for unprivileged users */
if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
&& hci_security_check_opcode(unit, hdr.opcode) != hdr.length) {
err = EPERM;
goto bad;
}
/* makess a copy for precious to keep */
m0 = m_copypacket(m, M_DONTWAIT);
if (m0 == NULL) {
@ -294,7 +465,7 @@ hci_send(struct hci_pcb *pcb, struct mbuf *m, bdaddr_t *addr)
M_SETCTX(m, pcb->hp_socket); /* enable drop callback */
DPRINTFN(2, "(%s) opcode (%03x|%04x)\n", device_xname(unit->hci_dev),
HCI_OGF(le16toh(hdr.opcode)), HCI_OCF(le16toh(hdr.opcode)));
HCI_OGF(hdr.opcode), HCI_OCF(hdr.opcode));
/* Sendss it */
if (unit->hci_num_cmd_pkts == 0)
@ -669,7 +840,7 @@ hci_mtap(struct mbuf *m, struct hci_unit *unit)
opcode = le16toh(mtod(m, hci_cmd_hdr_t *)->opcode);
if ((pcb->hp_flags & HCI_PRIVILEGED) == 0
&& hci_security_check_opcode(opcode) == -1)
&& hci_security_check_opcode(NULL, opcode) == -1)
continue;
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: hci_unit.c,v 1.8 2007/11/28 20:16:12 plunky Exp $ */
/* $NetBSD: hci_unit.c,v 1.9 2007/12/30 18:26:42 plunky Exp $ */
/*-
* Copyright (c) 2005 Iain Hibbert.
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: hci_unit.c,v 1.8 2007/11/28 20:16:12 plunky Exp $");
__KERNEL_RCSID(0, "$NetBSD: hci_unit.c,v 1.9 2007/12/30 18:26:42 plunky Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -58,6 +58,22 @@ int hci_eventq_max = 20;
int hci_aclrxq_max = 50;
int hci_scorxq_max = 50;
/*
* This is the default minimum command set supported by older
* devices. Anything conforming to 1.2 spec or later will get
* updated during init.
*/
static const uint8_t hci_cmds_v10[HCI_COMMANDS_SIZE] = {
0xff, 0xff, 0xff, 0x01, 0xfe, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x7f, 0x32, 0x03, 0xb8, 0xfe,
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/*
* bluetooth unit functions
*/
@ -140,6 +156,8 @@ hci_enable(struct hci_unit *unit)
unit->hci_acl_mask = HCI_PKT_DM1 | HCI_PKT_DH1;
unit->hci_packet_type = unit->hci_acl_mask;
memcpy(unit->hci_cmds, hci_cmds_v10, HCI_COMMANDS_SIZE);
unit->hci_rxint = softint_establish(SOFTINT_NET, &hci_intr, unit);
if (unit->hci_rxint == NULL)
return EIO;

View File

@ -1,4 +1,4 @@
/* $NetBSD: btconfig.c,v 1.9 2007/12/29 14:35:39 plunky Exp $ */
/* $NetBSD: btconfig.c,v 1.10 2007/12/30 18:26:43 plunky Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -34,7 +34,7 @@
#include <sys/cdefs.h>
__COPYRIGHT("@(#) Copyright (c) 2006 Itronix, Inc.\n"
"All rights reserved.\n");
__RCSID("$NetBSD: btconfig.c,v 1.9 2007/12/29 14:35:39 plunky Exp $");
__RCSID("$NetBSD: btconfig.c,v 1.10 2007/12/30 18:26:43 plunky Exp $");
#include <sys/ioctl.h>
#include <sys/param.h>
@ -106,6 +106,7 @@ int opt_reset = 0;
"\007INIT_BUFFER_SIZE" \
"\010INIT_FEATURES" \
"\011POWER_UP_NOOP" \
"\012INIT_COMMANDS" \
""
/* authorisation (flag) */