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:
parent
47708a0e13
commit
aeab3db895
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) */
|
||||
|
|
Loading…
Reference in New Issue