struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
-int hci_conn_security(struct hci_conn *conn, __u8 sec_level);
+int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
EXPORT_SYMBOL(hci_conn_check_link_mode);
/* Authenticate remote device */
-static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level)
+static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
{
BT_DBG("conn %p", conn);
- if (sec_level > conn->sec_level)
- conn->link_mode &= ~HCI_LM_AUTH;
-
- conn->sec_level = sec_level;
-
- if (sec_level == BT_SECURITY_HIGH)
- conn->auth_type |= 0x01;
-
- if (conn->link_mode & HCI_LM_AUTH)
+ if (sec_level > conn->sec_level) {
+ conn->sec_level = sec_level;
+ conn->auth_type = auth_type;
+ } else if (conn->link_mode & HCI_LM_AUTH)
return 1;
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
}
/* Enable security */
-int hci_conn_security(struct hci_conn *conn, __u8 sec_level)
+int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
{
BT_DBG("conn %p", conn);
if (sec_level == BT_SECURITY_LOW) {
if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0)
- return hci_conn_auth(conn, sec_level);
+ return hci_conn_auth(conn, sec_level, auth_type);
else
return 1;
}
if (conn->link_mode & HCI_LM_ENCRYPT)
- return hci_conn_auth(conn, sec_level);
+ return hci_conn_auth(conn, sec_level, auth_type);
if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return 0;
- if (hci_conn_auth(conn, sec_level)) {
+ if (hci_conn_auth(conn, sec_level, auth_type)) {
struct hci_cp_set_conn_encrypt cp;
cp.handle = cpu_to_le16(conn->handle);
cp.encrypt = 1;
static inline int l2cap_check_security(struct sock *sk)
{
struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+ __u8 auth_type;
+
+ switch (l2cap_pi(sk)->sec_level) {
+ case BT_SECURITY_HIGH:
+ auth_type = HCI_AT_GENERAL_BONDING_MITM;
+ break;
+ case BT_SECURITY_MEDIUM:
+ auth_type = HCI_AT_GENERAL_BONDING;
+ break;
+ default:
+ auth_type = HCI_AT_NO_BONDING;
+ break;
+ }
- return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level);
+ return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
+ auth_type);
}
static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
static inline int rfcomm_check_security(struct rfcomm_dlc *d)
{
struct sock *sk = d->session->sock->sk;
+ __u8 auth_type;
- return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level);
+ switch (d->sec_level) {
+ case BT_SECURITY_HIGH:
+ auth_type = HCI_AT_GENERAL_BONDING_MITM;
+ break;
+ case BT_SECURITY_MEDIUM:
+ auth_type = HCI_AT_GENERAL_BONDING;
+ break;
+ default:
+ auth_type = HCI_AT_NO_BONDING;
+ break;
+ }
+
+ return hci_conn_security(l2cap_pi(sk)->conn->hcon, d->sec_level,
+ auth_type);
}
/* ---- RFCOMM DLCs ---- */