Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168251318
D41332.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
D41332.id.diff
View Options
diff --git a/libexec/rc/rc.d/bluetooth b/libexec/rc/rc.d/bluetooth
--- a/libexec/rc/rc.d/bluetooth
+++ b/libexec/rc/rc.d/bluetooth
@@ -131,6 +131,15 @@
${hccontrol} -n ${dev}hci reset \
> /dev/null 2>&1 || return 1
+ # Enable SSP if supported ignoring the result if it is
+ # unsupported.
+ ${hccontrol} -n ${dev}hci write_simple_pairing_mode 1 \
+ > /dev/null 2>&1
+
+ # Set event mask for SSP features
+ ${hccontrol} -n ${dev}hci set_event_mask \
+ > /dev/null 2>&1
+
${hccontrol} -n ${dev}hci read_bd_addr \
> /dev/null 2>&1 || return 1
diff --git a/sys/netgraph/bluetooth/include/ng_hci.h b/sys/netgraph/bluetooth/include/ng_hci.h
--- a/sys/netgraph/bluetooth/include/ng_hci.h
+++ b/sys/netgraph/bluetooth/include/ng_hci.h
@@ -228,61 +228,61 @@
#define NG_HCI_EVMSK_DEFAULT 0x00001fffffffffff
#define NG_HCI_EVMSK_ALL 0x1fffffffffffffff
#define NG_HCI_EVMSK_NONE 0x0000000000000000
-#define NG_HCI_EVMSK_INQUIRY_COMPL 0x0000000000000001
-#define NG_HCI_EVMSK_INQUIRY_RESULT 0x0000000000000002
-#define NG_HCI_EVMSK_CON_COMPL 0x0000000000000004
-#define NG_HCI_EVMSK_CON_REQ 0x0000000000000008
-#define NG_HCI_EVMSK_DISCON_COMPL 0x0000000000000010
-#define NG_HCI_EVMSK_AUTH_COMPL 0x0000000000000020
-#define NG_HCI_EVMSK_REMOTE_NAME_REQ_COMPL 0x0000000000000040
-#define NG_HCI_EVMSK_ENCRYPTION_CHANGE 0x0000000000000080
-#define NG_HCI_EVMSK_CHANGE_CON_LINK_KEY_COMPL 0x0000000000000100
-#define NG_HCI_EVMSK_MASTER_LINK_KEY_COMPL 0x0000000000000200
-#define NG_HCI_EVMSK_READ_REMOTE_FEATURES_COMPL 0x0000000000000400
-#define NG_HCI_EVMSK_READ_REMOTE_VER_INFO_COMPL 0x0000000000000800
-#define NG_HCI_EVMSK_QOS_SETUP_COMPL 0x0000000000001000
-#define NG_HCI_EVMSK_COMMAND_COMPL 0x0000000000002000
-#define NG_HCI_EVMSK_COMMAND_STATUS 0x0000000000004000
-#define NG_HCI_EVMSK_HARDWARE_ERROR 0x0000000000008000
-#define NG_HCI_EVMSK_FLUSH_OCCUR 0x0000000000010000
-#define NG_HCI_EVMSK_ROLE_CHANGE 0x0000000000020000
-#define NG_HCI_EVMSK_NUM_COMPL_PKTS 0x0000000000040000
-#define NG_HCI_EVMSK_MODE_CHANGE 0x0000000000080000
-#define NG_HCI_EVMSK_RETURN_LINK_KEYS 0x0000000000100000
-#define NG_HCI_EVMSK_PIN_CODE_REQ 0x0000000000200000
-#define NG_HCI_EVMSK_LINK_KEY_REQ 0x0000000000400000
-#define NG_HCI_EVMSK_LINK_KEY_NOTIFICATION 0x0000000000800000
-#define NG_HCI_EVMSK_LOOPBACK_COMMAND 0x0000000001000000
-#define NG_HCI_EVMSK_DATA_BUFFER_OVERFLOW 0x0000000002000000
-#define NG_HCI_EVMSK_MAX_SLOT_CHANGE 0x0000000004000000
-#define NG_HCI_EVMSK_READ_CLOCK_OFFSET_COMLETE 0x0000000008000000
-#define NG_HCI_EVMSK_CON_PKT_TYPE_CHANGED 0x0000000010000000
-#define NG_HCI_EVMSK_QOS_VIOLATION 0x0000000020000000
-#define NG_HCI_EVMSK_PAGE_SCAN_MODE_CHANGE 0x0000000040000000
-#define NG_HCI_EVMSK_PAGE_SCAN_REP_MODE_CHANGE 0x0000000080000000
-#define NG_HCI_EVMSK_FLOW_SPEC_COMPL 0x0000000100000000
-#define NG_HCI_EVMSK_INQUIRY_RESULT_W_RSSI 0x0000000200000000
-#define NG_HCI_EVMSK_READ_REM_EXT_FEAT_COMPL 0x0000000400000000
-
-/* 0x0000000800000000 - 0x0000080000000000 - not in use */
-
-#define NG_HCI_EVMSK_SYNC_CONN_COMPL 0x0000100000000000
-#define NG_HCI_EVMSK_SYNC_CONN_CHANGED 0x0000200000000000
-#define NG_HCI_EVMSK_SNIFF_SUBRATING 0x0000400000000000
-#define NG_HCI_EVMSK_EXT_INQUIRY_RESULT 0x0000800000000000
-#define NG_HCI_EVMSK_ENC_KEY_REFRESH_COMPL 0x0001000000000000
-#define NG_HCI_EVMSK_IO_CAPABILITY_REQ 0x0002000000000000
-#define NG_HCI_EVMSK_IO_CAPABILITY_RESP 0x0004000000000000
-#define NG_HCI_EVMSK_USER_CONFIRMATION_REQ 0x0008000000000000
-#define NG_HCI_EVMSK_USER_PASSKEY_REQ 0x0010000000000000
-#define NG_HCI_EVMSK_REM_OOB_DATA_REQ 0x0020000000000000
-#define NG_HCI_EVMSK_SIMPLE_PAIRING_COMPL 0x0040000000000000
-#define NG_HCI_EVMSK_LINK_SUPERV_TO_CHANGED 0x0080000000000000
-#define NG_HCI_EVMSK_ENH_FLUSH_COMPL 0x0100000000000000
-#define NG_HCI_EVMSK_USER_PASSKEY_NOTIFICATION 0x0200000000000000
-#define NG_HCI_EVMSK_KEYPRESS_NOTIFICATION 0x0400000000000000
-#define NG_HCI_EVMSK_REM_HOST_SUPP_FEAT_NOTIFI 0x0800000000000000
-#define NG_HCI_EVMSK_LE_META 0x1000000000000000
+#define NG_HCI_EVMSK_INQUIRY_COMPL (1lu << 0)
+#define NG_HCI_EVMSK_INQUIRY_RESULT (1lu << 1)
+#define NG_HCI_EVMSK_CON_COMPL (1lu << 2)
+#define NG_HCI_EVMSK_CON_REQ (1lu << 3)
+#define NG_HCI_EVMSK_DISCON_COMPL (1lu << 4)
+#define NG_HCI_EVMSK_AUTH_COMPL (1lu << 5)
+#define NG_HCI_EVMSK_REMOTE_NAME_REQ_COMPL (1lu << 6)
+#define NG_HCI_EVMSK_ENCRYPTION_CHANGE (1lu << 7)
+#define NG_HCI_EVMSK_CHANGE_CON_LINK_KEY_COMPL (1lu << 8)
+#define NG_HCI_EVMSK_MASTER_LINK_KEY_COMPL (1lu << 9)
+#define NG_HCI_EVMSK_READ_REMOTE_FEATURES_COMPL (1lu << 10)
+#define NG_HCI_EVMSK_READ_REMOTE_VER_INFO_COMPL (1lu << 11)
+#define NG_HCI_EVMSK_QOS_SETUP_COMPL (1lu << 12)
+#define NG_HCI_EVMSK_COMMAND_COMPL (1lu << 13)
+#define NG_HCI_EVMSK_COMMAND_STATUS (1lu << 14)
+#define NG_HCI_EVMSK_HARDWARE_ERROR (1lu << 15)
+#define NG_HCI_EVMSK_FLUSH_OCCUR (1lu << 16)
+#define NG_HCI_EVMSK_ROLE_CHANGE (1lu << 17)
+#define NG_HCI_EVMSK_NUM_COMPL_PKTS (1lu << 18)
+#define NG_HCI_EVMSK_MODE_CHANGE (1lu << 19)
+#define NG_HCI_EVMSK_RETURN_LINK_KEYS (1lu << 20)
+#define NG_HCI_EVMSK_PIN_CODE_REQ (1lu << 21)
+#define NG_HCI_EVMSK_LINK_KEY_REQ (1lu << 22)
+#define NG_HCI_EVMSK_LINK_KEY_NOTIFICATION (1lu << 23)
+#define NG_HCI_EVMSK_LOOPBACK_COMMAND (1lu << 24)
+#define NG_HCI_EVMSK_DATA_BUFFER_OVERFLOW (1lu << 25)
+#define NG_HCI_EVMSK_MAX_SLOT_CHANGE (1lu << 26)
+#define NG_HCI_EVMSK_READ_CLOCK_OFFSET_COMLETE (1lu << 27)
+#define NG_HCI_EVMSK_CON_PKT_TYPE_CHANGED (1lu << 28)
+#define NG_HCI_EVMSK_QOS_VIOLATION (1lu << 29)
+#define NG_HCI_EVMSK_PAGE_SCAN_MODE_CHANGE (1lu << 30)
+#define NG_HCI_EVMSK_PAGE_SCAN_REP_MODE_CHANGE (1lu << 31)
+#define NG_HCI_EVMSK_FLOW_SPEC_COMPL (1lu << 32)
+#define NG_HCI_EVMSK_INQUIRY_RESULT_W_RSSI (1lu << 33)
+#define NG_HCI_EVMSK_READ_REM_EXT_FEAT_COMPL (1lu << 34)
+
+/* 0x0000000800000000 - 0x0000080000000000 - not in use */
+
+#define NG_HCI_EVMSK_SYNC_CONN_COMPL (1lu << 43)
+#define NG_HCI_EVMSK_SYNC_CONN_CHANGED (1lu << 44)
+#define NG_HCI_EVMSK_SNIFF_SUBRATING (1lu << 45)
+#define NG_HCI_EVMSK_EXT_INQUIRY_RESULT (1lu << 46)
+#define NG_HCI_EVMSK_ENC_KEY_REFRESH_COMPL (1lu << 47)
+#define NG_HCI_EVMSK_IO_CAPABILITY_REQ (1lu << 48)
+#define NG_HCI_EVMSK_IO_CAPABILITY_RESP (1lu << 49)
+#define NG_HCI_EVMSK_USER_CONFIRMATION_REQ (1lu << 50)
+#define NG_HCI_EVMSK_USER_PASSKEY_REQ (1lu << 51)
+#define NG_HCI_EVMSK_REM_OOB_DATA_REQ (1lu << 52)
+#define NG_HCI_EVMSK_SIMPLE_PAIRING_COMPL (1lu << 53)
+#define NG_HCI_EVMSK_LINK_SUPERV_TO_CHANGED (1lu << 55)
+#define NG_HCI_EVMSK_ENH_FLUSH_COMPL (1lu << 56)
+#define NG_HCI_EVMSK_USER_PASSKEY_NOTIFICATION (1lu << 58)
+#define NG_HCI_EVMSK_KEYPRESS_NOTIFICATION (1lu << 59)
+#define NG_HCI_EVMSK_REM_HOST_SUPP_FEAT_NOTIFI (1lu << 60)
+#define NG_HCI_EVMSK_LE_META (1lu << 61)
/* 0x1000000100000000 - 0x8000000000000000 - reserved for future use */
/* LE events masks*/
@@ -861,6 +861,13 @@
} __attribute__ ((packed)) ng_hci_read_clock_offset_cp;
/* No return parameter(s) */
+#define NG_HCI_OCF_USER_CONFIRM_REP 0x002c
+typedef struct {
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) ng_hci_user_confirm_rp;
+
+#define NG_HCI_OCF_USER_CONFIRM_NEGATIVE_REP 0x002d
+
/**************************************************************************
**************************************************************************
** Link policy commands and return parameters
@@ -1781,6 +1788,26 @@
} __attribute__((packed)) ng_le_transmitter_test_cp;
typedef ng_hci_status_rp ng_hci_le_transmitter_test_rp;
+#define NG_HCI_OCF_IO_CAPABILITY_REP 0x02b
+typedef struct {
+ bdaddr_t addr;
+ u_int8_t io_cap;
+#define NG_HCI_IO_CAP_DISPLAY_ONLY 0x00
+#define NG_HCI_IO_CAP_DISPLAY_YESNO 0x01
+#define NG_HCI_IO_CAP_KEYBOAD_ONLY 0x02
+#define NG_HCI_IO_CAP_NO_INPUT_NO_OUTPUT 0x03
+#define NG_HCI_IO_CAP_KEYBOAD_DISPLAY 0x04
+ u_int8_t oob_data_present;
+ u_int8_t auth_requirements;
+#define NG_HCI_AUTH_REQ_MITMPROT_NOTREQ 0x00
+#define NG_HCI_AUTH_REQ_MITMPROT_REQ 0x01
+#define NG_HCI_AUTH_REQ_NO_BONDING 0x00
+#define NG_HCI_AUTH_REQ_DEDICATED_BONDING 0x02
+#define NG_HCI_AUTH_REQ_GENERAL_BONDING 0x04
+#define NG_HCI_AUTH_REQ_NUMERIC_COMP 0x00
+#define NG_HCI_AUTH_REQ_USE_IO_CAPS 0x01
+} __attribute__((packed)) ng_hci_io_capability_request_rp;
+
#define NG_HCI_OCF_LE_TEST_END 0x001f
/* No command parameter. */
typedef struct {
@@ -2026,6 +2053,17 @@
bdaddr_t bdaddr; /* destination address */
u_int8_t page_scan_rep_mode; /* page scan repetition mode */
} __attribute__ ((packed)) ng_hci_page_scan_rep_mode_change_ep;
+
+#define NG_HCI_EVENT_IO_CAPABILITY_REQ 0x31
+typedef struct {
+ bdaddr_t bdaddr; /* remote address */
+} __attribute__ ((packed)) ng_hci_io_capability_req_ep;
+
+#define NG_HCI_EVENT_USER_CONFIRM_REQ 0x33
+typedef struct {
+ u_int32_t numeric_value;
+} __attribute__ ((packed)) ng_hci_user_confirm_ep;
+
#define NG_HCI_EVENT_LE 0x3e
typedef struct {
u_int8_t subevent_code;
diff --git a/usr.sbin/bluetooth/hccontrol/hccontrol.c b/usr.sbin/bluetooth/hccontrol/hccontrol.c
--- a/usr.sbin/bluetooth/hccontrol/hccontrol.c
+++ b/usr.sbin/bluetooth/hccontrol/hccontrol.c
@@ -140,6 +140,8 @@
bit_set(filter.event_mask, NG_HCI_EVENT_INQUIRY_COMPL - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_INQUIRY_RESULT - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_CON_COMPL - 1);
+ bit_set(filter.event_mask, NG_HCI_EVENT_AUTH_COMPL - 1);
+ bit_set(filter.event_mask, NG_HCI_EVENT_ENCRYPTION_CHANGE - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_DISCON_COMPL - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_REMOTE_NAME_REQ_COMPL - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_READ_REMOTE_FEATURES_COMPL - 1);
diff --git a/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c b/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c
--- a/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c
+++ b/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c
@@ -34,6 +34,7 @@
#define L2CAP_SOCKET_CHECKED
#include <bluetooth.h>
#include <errno.h>
+#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include "hccontrol.h"
@@ -393,6 +394,47 @@
return (OK);
} /* hci_delete_stored_link_key */
+/* Send Set_Event_Mask command to the unit */
+static int
+hci_set_event_mask(int s, int argc, char **argv)
+{
+ ng_hci_set_event_mask_cp cp;
+ ng_hci_set_event_mask_rp rp;
+ int32_t n;
+ uint64_t mask = NG_HCI_EVENT_MASK_DEFAULT;
+ uint64_t extra = 0;
+
+ /* enable notifications for IO capability req/rep and simple
+ * pairing complete events */
+ mask |=
+ NG_HCI_EVMSK_USER_CONFIRMATION_REQ |
+ NG_HCI_EVMSK_SIMPLE_PAIRING_COMPL |
+ NG_HCI_EVMSK_IO_CAPABILITY_REQ |
+ NG_HCI_EVMSK_IO_CAPABILITY_RESP;
+ memset(&cp, 0, sizeof(cp));
+
+ if (argc == 1 && sscanf(argv[0], "%"SCNx64, &extra) != 1)
+ return (USAGE);
+
+ le64enc(cp.event_mask, mask | extra);
+
+ /* send command */
+ n = sizeof(cp);
+ if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
+ NG_HCI_OCF_SET_EVENT_MASK),
+ (char const *) &cp, sizeof(cp),
+ (char *) &rp, &n) == ERROR)
+ return (ERROR);
+
+ if (rp.status != 0x00) {
+ fprintf(stdout, "Status: %s [%#02x]\n",
+ hci_status2str(rp.status), rp.status);
+ return (FAILED);
+ }
+
+ return (OK);
+} /* hci_set_event_mask */
+
/* Send Change_Local_Name command to the unit */
static int
hci_change_local_name(int s, int argc, char **argv)
@@ -1211,6 +1253,44 @@
return (OK);
} /* hci_write_hold_mode_activity */
+/* Send Write_Simple_Pairing_Mode command to the unit */
+static int
+hci_write_simple_pairing_mode(int s, int argc, char **argv)
+{
+ uint8_t enable = 0;
+ uint8_t rp_status = 0;
+ int n;
+
+ /* parse command parameters */
+ switch (argc) {
+ case 1:
+ if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 1)
+ return (USAGE);
+
+ enable = (uint8_t) n;
+ break;
+
+ default:
+ return (USAGE);
+ }
+
+ /* send command */
+ n = sizeof(rp_status);
+ if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND,
+ 0x056),
+ (char const *) &enable, sizeof(enable),
+ (char *) &rp_status, &n) == ERROR)
+ return (ERROR);
+
+ if (rp_status != 0x00) {
+ fprintf(stdout, "Status: %s [%#02x]\n",
+ hci_status2str(rp_status), rp_status);
+ return (FAILED);
+ }
+
+ return (OK);
+} /* hci_write_simple_pairing_mode */
+
/* Send Read_SCO_Flow_Control_Enable command to the unit */
static int
hci_read_sco_flow_control_enable(int s, int argc, char **argv)
@@ -1617,6 +1697,11 @@
&hci_delete_stored_link_key
},
{
+"set_event_mask mask",
+"Sets the event mask of the HC including for use in SSP.\n",
+&hci_set_event_mask
+},
+{
"change_local_name <name>",
"\nThe Change_Local_Name command provides the ability to modify the user\n" \
"friendly name for the Bluetooth unit.\n\n" \
@@ -1857,6 +1942,11 @@
&hci_write_hold_mode_activity
},
{
+"write_simple_pairing_mode enable(0|1)",
+"\nEnable or disable simple pairing mode\n",
+&hci_write_simple_pairing_mode
+},
+{
"read_sco_flow_control_enable",
"\nThe Read_SCO_Flow_Control_Enable command provides the ability to read\n" \
"the SCO_Flow_Control_Enable setting. By using this setting, the Host can\n" \
diff --git a/usr.sbin/bluetooth/hccontrol/link_control.c b/usr.sbin/bluetooth/hccontrol/link_control.c
--- a/usr.sbin/bluetooth/hccontrol/link_control.c
+++ b/usr.sbin/bluetooth/hccontrol/link_control.c
@@ -288,6 +288,121 @@
return (OK);
} /* hci_create_connection */
+/* Send Request_Authentication command to the unit */
+static int
+hci_request_authentication(int s, int argc, char **argv)
+{
+ int n0;
+ char b[512];
+ ng_hci_auth_req_cp cp;
+ ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b;
+
+ /* Set defaults */
+ memset(&cp, 0, sizeof(cp));
+
+ if (argc != 1)
+ return (USAGE);
+
+ if (sscanf(argv[0], "%d", &n0) != 1)
+ return (USAGE);
+
+ cp.con_handle = htole16(n0);
+
+ /* send request and expect status response */
+ n0 = sizeof(b);
+ if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
+ NG_HCI_OCF_AUTH_REQ),
+ (char const *) &cp, sizeof(cp), b, &n0) == ERROR)
+ return (ERROR);
+
+ if (*b != 0x00)
+ return (FAILED);
+
+ /* wait for event */
+again:
+ n0 = sizeof(b);
+ if (hci_recv(s, b, &n0) == ERROR)
+ return (ERROR);
+ if (n0 < sizeof(*e)) {
+ errno = EIO;
+ return (ERROR);
+ }
+
+ if (e->event == NG_HCI_EVENT_AUTH_COMPL) {
+ ng_hci_auth_compl_ep *ep = (ng_hci_auth_compl_ep *)(e + 1);
+
+ if (ep->status != 0x00) {
+ fprintf(stdout, "Status: %s [%#02x]\n",
+ hci_status2str(ep->status), ep->status);
+ return (FAILED);
+ }
+
+ } else
+ goto again;
+
+ return (OK);
+} /* hci_request_authentication */
+
+/* Send Set_Connection_Encryption */
+static int
+hci_set_connection_encryption(int s, int argc, char **argv)
+{
+ int n0;
+ char b[512];
+ ng_hci_set_con_encryption_cp cp;
+ ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b;
+
+ /* Set defaults */
+ memset(&cp, 0, sizeof(cp));
+
+ if (argc != 2)
+ return (USAGE);
+
+ if (sscanf(argv[0], "%d", &n0) != 1)
+ return (USAGE);
+
+ cp.con_handle = htole16(n0);
+
+ if (sscanf(argv[1], "%d", &n0) != 1)
+ return (USAGE);
+
+ cp.encryption_enable = (u_int16_t)n0;
+
+ /* send request and expect status response */
+ n0 = sizeof(b);
+ if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
+ NG_HCI_OCF_SET_CON_ENCRYPTION),
+ (char const *) &cp, sizeof(cp), b, &n0) == ERROR)
+ return (ERROR);
+
+ if (*b != 0x00)
+ return (FAILED);
+
+ /* wait for event */
+again:
+ n0 = sizeof(b);
+ if (hci_recv(s, b, &n0) == ERROR)
+ return (ERROR);
+ if (n0 < sizeof(*e)) {
+ errno = EIO;
+ return (ERROR);
+ }
+
+ if (e->event == NG_HCI_EVENT_ENCRYPTION_CHANGE) {
+ ng_hci_encryption_change_ep *ep = (ng_hci_encryption_change_ep *)(e + 1);
+
+ if (ep->status != 0x00) {
+ fprintf(stdout, "Status: %s [%#02x]\n",
+ hci_status2str(ep->status), ep->status);
+ return (FAILED);
+ }
+
+ } else
+ goto again;
+
+ return (OK);
+} /* hci_set_connection_encryption */
+
/* Send Disconnect command to the unit */
static int
hci_disconnect(int s, int argc, char **argv)
@@ -958,6 +1073,19 @@
&hci_read_clock_offset
},
{
+"request_authentication <connection_handle>",
+"\nThis command allows to manually request authentication for a given unit.\n" \
+"Requires that the hcsecd daemon is running.\n" \
+"\t<connection_handle> - dddd; connection handle",
+&hci_request_authentication
+},
+{
+"set_connection_encryption <connection_handle> <enable(0|1)>",
+"\nThis command allows to set the connection encryption for a given connection.\n" \
+"\t<connection_handle> - dddd; connection handle" \
+"\tenable(1|0); enable or disable connection",
+&hci_set_connection_encryption
+},
+{
NULL,
}};
-
diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.h b/usr.sbin/bluetooth/hcsecd/hcsecd.h
--- a/usr.sbin/bluetooth/hcsecd/hcsecd.h
+++ b/usr.sbin/bluetooth/hcsecd/hcsecd.h
@@ -45,6 +45,7 @@
char *name; /* remote device name */
uint8_t *key; /* link key (or NULL if no key) */
char *pin; /* pin (or NULL if no pin) */
+ int autoaccept; /* automatically accept user confirm requests if non-zero */
LIST_ENTRY(link_key) next; /* link to the next */
};
typedef struct link_key link_key_t;
diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.8 b/usr.sbin/bluetooth/hcsecd/hcsecd.8
--- a/usr.sbin/bluetooth/hcsecd/hcsecd.8
+++ b/usr.sbin/bluetooth/hcsecd/hcsecd.8
@@ -41,13 +41,16 @@
daemon controls link keys and PIN codes for Bluetooth devices.
It opens a raw HCI socket and listens for
.Dv Link_Key_Request ,
-.Dv PIN_Code_Request
+.Dv PIN_Code_Request ,
+.Dv Link_Key_Notification ,
+.Dv IO_Capability_Request ,
and
-.Dv Link_Key_Notification
+.Dv User_Confirmation_Request
HCI events.
.Pp
Once a
-.Dv Link_Key_Request
+.Dv Link_Key_Request ,
+.Dv User_Confirmation_Request
or
.Dv PIN_Code_Request
HCI event is received, the daemon scans the configuration file for a
@@ -69,6 +72,12 @@
(or
.Dv PIN_Code_Request_Negative_Reply )
command will be sent back to the device.
+If the request was a
+.Dv User_Confirmation_Request
+and the autoaccept option was set for the matching entry in the
+configuration file,
+.Nm
+will accept the request. This is needed for Secure Simple Pairing.
.Pp
The
.Nm
diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.c b/usr.sbin/bluetooth/hcsecd/hcsecd.c
--- a/usr.sbin/bluetooth/hcsecd/hcsecd.c
+++ b/usr.sbin/bluetooth/hcsecd/hcsecd.c
@@ -51,6 +51,10 @@
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
static int process_link_key_request_event
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
+static int process_user_confirm_request
+ (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
+static int process_io_capability_request
+ (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
static int send_pin_code_reply
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin);
static int send_link_key_reply
@@ -126,6 +130,8 @@
bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1);
bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
+ bit_set(filter.event_mask, NG_HCI_EVENT_USER_CONFIRM_REQ - 1);
+ bit_set(filter.event_mask, NG_HCI_EVENT_IO_CAPABILITY_REQ - 1);
if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
(void * const) &filter, sizeof(filter)) < 0)
@@ -188,6 +194,16 @@
(ng_hci_link_key_notification_ep *)(event + 1));
break;
+ case NG_HCI_EVENT_USER_CONFIRM_REQ:
+ process_user_confirm_request(sock, &addr,
+ (bdaddr_p)(event + 1));
+ break;
+
+ case NG_HCI_EVENT_IO_CAPABILITY_REQ:
+ process_io_capability_request(sock, &addr,
+ (bdaddr_p)(event + 1));
+ break;
+
default:
syslog(LOG_ERR, "Received unexpected HCI event, " \
"event=%#x", event->event);
@@ -415,7 +431,97 @@
return (0);
}
-/* Signal handlers */
+static int
+process_user_confirm_request(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr)
+{
+ uint8_t buffer[HCSECD_BUFFER_SIZE] = {0};
+ ng_hci_cmd_pkt_t *cmd = NULL;
+ ng_hci_user_confirm_rp *rp = NULL;
+ link_key_p key = NULL;
+
+ syslog(LOG_DEBUG, "Got User Confirmation Request from '%s'\n",
+ addr->hci_node);
+
+ /* prepare command */
+ cmd = (ng_hci_cmd_pkt_t *) buffer;
+ cmd->type = NG_HCI_CMD_PKT;
+ cmd->length = sizeof(*rp);
+ rp = (ng_hci_user_confirm_rp *)(cmd + 1);
+ memcpy(&rp->bdaddr, bdaddr, sizeof(rp->bdaddr));
+
+ /* Now look if we should accept the command */
+ if (((key = get_key(bdaddr, 1)) != NULL) && key->autoaccept) {
+ cmd->opcode = htole32(NG_HCI_OPCODE(
+ NG_HCI_OGF_LINK_CONTROL,
+ NG_HCI_OCF_USER_CONFIRM_REP));
+ syslog(LOG_DEBUG, "Accepting User Confirmation Request from '%s'\n",
+ addr->hci_node);
+ } else {
+ cmd->opcode = htole32(NG_HCI_OPCODE(
+ NG_HCI_OGF_LINK_CONTROL,
+ NG_HCI_OCF_USER_CONFIRM_NEGATIVE_REP));
+ syslog(LOG_ERR,
+ "No configuration for '%s' or missing autoaccept option. "
+ "Rejecting the user confirmation request.\n",
+ addr->hci_node);
+ }
+
+again:
+ if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
+ (struct sockaddr *) addr, sizeof(*addr)) < 0) {
+ if (errno == EINTR)
+ goto again;
+
+ syslog(LOG_ERR, "Could not send reply to user confirmation request to '%s' " \
+ "for remote bdaddr %s. %s (%d)",
+ addr->hci_node, bt_ntoa(bdaddr, NULL),
+ strerror(errno), errno);
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+process_io_capability_request(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr)
+{
+ uint8_t buffer[HCSECD_BUFFER_SIZE] = {0};
+ ng_hci_cmd_pkt_t *cmd = NULL;
+ ng_hci_io_capability_request_rp *rp = NULL;
+
+ syslog(LOG_DEBUG, "Got IO Capability Request from '%s'\n",
+ addr->hci_node);
+
+ cmd = (ng_hci_cmd_pkt_t *) buffer;
+ cmd->type = NG_HCI_CMD_PKT;
+ cmd->opcode = htole32(NG_HCI_OPCODE(
+ NG_HCI_OGF_LINK_CONTROL,
+ NG_HCI_OCF_IO_CAPABILITY_REP));
+ cmd->length = sizeof(*rp);
+
+ rp = (ng_hci_io_capability_request_rp *)(cmd + 1);
+ memcpy(&rp->addr, bdaddr, sizeof(rp->addr));
+ rp->io_cap = NG_HCI_IO_CAP_NO_INPUT_NO_OUTPUT;
+ rp->auth_requirements =
+ NG_HCI_AUTH_REQ_MITMPROT_REQ |
+ NG_HCI_AUTH_REQ_DEDICATED_BONDING |
+ NG_HCI_AUTH_REQ_USE_IO_CAPS;
+
+again:
+ if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
+ (struct sockaddr *) addr, sizeof(*addr)) < 0) {
+ if (errno == EINTR)
+ goto again;
+
+ syslog(LOG_ERR, "Could not send IO capability reply to '%s' " \
+ "for remote bdaddr %s. %s (%d)",
+ addr->hci_node, bt_ntoa(bdaddr, NULL),
+ strerror(errno), errno);
+ return (-1);
+ }
+ return (0);
+}
+
+/* SIGNAL handlers */
static void
sighup(int s)
{
diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.conf b/usr.sbin/bluetooth/hcsecd/hcsecd.conf
--- a/usr.sbin/bluetooth/hcsecd/hcsecd.conf
+++ b/usr.sbin/bluetooth/hcsecd/hcsecd.conf
@@ -17,6 +17,7 @@
# name "any char" ; - to set user friendly device name
# key 0x11223344 | nokey ; - to set link key for the device
# pin "secret" | nopin ; - to PIN code for the device
+# autoaccept - to accept user confirmation requests
#
# Notes:
#
diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5 b/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5
--- a/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5
+++ b/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5
@@ -94,6 +94,8 @@
PIN code is a string up to 16 characters in length in straight double quotes.
.It Cm pin nopin
Specify no PIN code for the entry.
+.It Cm autoaccept
+Set this to automatically accept user confirmation requests.
.El
.Sh EXAMPLES
A sample
@@ -124,6 +126,16 @@
key 0x00112233445566778899aabbccddeeff; # 16 bytes key
pin nopin;
}
+
+# A device that allows Secure Simple Pairing that we should
+# automatically accept incoming user confirmation requests from.
+device {
+ bdaddr f0:0f:de:ad:c0:de;
+ name "Some SSP capable Device";
+ key nokey;
+ pin "0000";
+ autoaccept;
+}
.Ed
.Sh SEE ALSO
.Xr hcsecd 8
diff --git a/usr.sbin/bluetooth/hcsecd/lexer.l b/usr.sbin/bluetooth/hcsecd/lexer.l
--- a/usr.sbin/bluetooth/hcsecd/lexer.l
+++ b/usr.sbin/bluetooth/hcsecd/lexer.l
@@ -53,6 +53,7 @@
nokey_word nokey
pin_word pin
nopin_word nopin
+autoaccept_word autoaccept
bdaddrstring {hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}
hexstring 0x{hexbyte}+
@@ -76,6 +77,7 @@
{nokey_word} return (T_NOKEY);
{pin_word} return (T_PIN);
{nopin_word} return (T_NOPIN);
+{autoaccept_word} return (T_AUTOACCEPT);
{bdaddrstring} {
yylval.string = yytext;
diff --git a/usr.sbin/bluetooth/hcsecd/parser.y b/usr.sbin/bluetooth/hcsecd/parser.y
--- a/usr.sbin/bluetooth/hcsecd/parser.y
+++ b/usr.sbin/bluetooth/hcsecd/parser.y
@@ -65,7 +65,8 @@
}
%token <string> T_BDADDRSTRING T_HEXSTRING T_STRING
-%token T_DEVICE T_BDADDR T_NAME T_KEY T_PIN T_NOKEY T_NOPIN T_JUNK
+%token T_DEVICE T_BDADDR T_NAME T_KEY T_PIN T_NOKEY
+%token T_NOPIN T_AUTOACCEPT T_JUNK
%%
@@ -106,6 +107,7 @@
| name
| key
| pin
+ | autoaccept
;
bdaddr: T_BDADDR T_BDADDRSTRING
@@ -185,6 +187,11 @@
}
;
+autoaccept: T_AUTOACCEPT
+ {
+ key->autoaccept = 1;
+ }
+
%%
/* Display parser error message */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 28, 4:42 AM (18 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37435893
Default Alt Text
D41332.id.diff (25 KB)
Attached To
Mode
D41332: ng_hci, hccontrol, hcsecd: Add Bluetooth SSP support
Attached
Detach File
Event Timeline
Log In to Comment