Page MenuHomeFreeBSD

D41332.id.diff
No OneTemporary

D41332.id.diff

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

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)

Event Timeline