diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r-- | net/bluetooth/hci_event.c | 97 |
1 files changed, 39 insertions, 58 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d8a2d32..d99075a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -545,7 +545,7 @@ static void hci_setup(struct hci_dev *hdev) { hci_setup_event_mask(hdev); - if (hdev->lmp_ver > 1) + if (hdev->hci_ver > 1) hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); if (hdev->features[6] & LMP_SIMPLE_PAIR) { @@ -898,16 +898,15 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, if (!cp) return; - hci_dev_lock(hdev); - if (cp->enable == 0x01) { del_timer(&hdev->adv_timer); + + hci_dev_lock(hdev); hci_adv_entries_clear(hdev); + hci_dev_unlock(hdev); } else if (cp->enable == 0x00) { mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); } - - hci_dev_unlock(hdev); } static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb) @@ -992,7 +991,7 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) } } else { if (!conn) { - conn = hci_conn_add(hdev, ACL_LINK, 0, &cp->bdaddr); + conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); if (conn) { conn->out = 1; conn->link_mode |= HCI_LM_MASTER; @@ -1103,9 +1102,10 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev, return 0; /* Only request authentication for SSP connections or non-SSP - * devices with sec_level HIGH */ + * devices with sec_level HIGH or if MITM protection is requested */ if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && - conn->pending_sec_level != BT_SECURITY_HIGH) + conn->pending_sec_level != BT_SECURITY_HIGH && + !(conn->auth_type & 0x01)) return 0; return 1; @@ -1315,7 +1315,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) } } else { if (!conn) { - conn = hci_conn_add(hdev, LE_LINK, 0, &cp->peer_addr); + conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); if (conn) { conn->dst_type = cp->peer_addr_type; conn->out = 1; @@ -1411,8 +1411,14 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s if (conn->type == ACL_LINK) { conn->state = BT_CONFIG; hci_conn_hold(conn); - conn->disc_timeout = HCI_DISCONN_TIMEOUT; - mgmt_connected(hdev->id, &ev->bdaddr); + + if (!conn->out && + !(conn->ssp_mode && conn->hdev->ssp_mode) && + !hci_find_link_key(hdev, &ev->bdaddr)) + conn->disc_timeout = HCI_PAIRING_TIMEOUT; + else + conn->disc_timeout = HCI_DISCONN_TIMEOUT; + mgmt_connected(hdev->id, &ev->bdaddr, conn->type); } else conn->state = BT_CONNECTED; @@ -1462,15 +1468,6 @@ unlock: hci_conn_check_pending(hdev); } -static inline bool is_sco_active(struct hci_dev *hdev) -{ - if (hci_conn_hash_lookup_state(hdev, SCO_LINK, BT_CONNECTED) || - (hci_conn_hash_lookup_state(hdev, ESCO_LINK, - BT_CONNECTED))) - return true; - return false; -} - static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_conn_request *ev = (void *) skb->data; @@ -1495,8 +1492,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); if (!conn) { - /* pkt_type not yet used for incoming connections */ - conn = hci_conn_add(hdev, ev->link_type, 0, &ev->bdaddr); + conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); if (!conn) { BT_ERR("No memory for new connection"); hci_dev_unlock(hdev); @@ -1514,8 +1510,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk bacpy(&cp.bdaddr, &ev->bdaddr); - if (lmp_rswitch_capable(hdev) && ((mask & HCI_LM_MASTER) - || is_sco_active(hdev))) + if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) cp.role = 0x00; /* Become master */ else cp.role = 0x01; /* Remain slave */ @@ -1590,21 +1585,6 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s if (!conn) goto unlock; - /* SS_BLUETOOTH(gudam.ryu) 2012. 03. 02 - Fixed for opp sending fail, - if the devices were unpaired on the remote end */ - if (ev->status == 0x06 && hdev->ssp_mode > 0 && - conn->ssp_mode > 0) { - struct hci_cp_auth_requested cp; - hci_remove_link_key(hdev, &conn->dst); - cp.handle = cpu_to_le16(conn->handle); - hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, - sizeof(cp), &cp); - hci_dev_unlock(hdev); - BT_DBG("Pin or key missing !!!"); - return; - } - /* SS_Bluetooth(gudam.ryu) End */ - if (!ev->status) { if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) && test_bit(HCI_CONN_REAUTH_PEND, &conn->pend)) { @@ -1615,7 +1595,6 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s } } else { mgmt_auth_failed(hdev->id, &conn->dst, ev->status); - conn->disc_timeout = HCI_DISCONN_TIMEOUT/200; /* 0.01 sec */ } clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); @@ -2201,7 +2180,10 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); - if (conn && conn->state == BT_CONNECTED) { + if (!conn) + goto unlock; + + if (conn->state == BT_CONNECTED) { hci_conn_hold(conn); conn->disc_timeout = HCI_PAIRING_TIMEOUT; hci_conn_put(conn); @@ -2221,6 +2203,7 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff mgmt_pin_code_request(hdev->id, &ev->bdaddr, secure); } +unlock: hci_dev_unlock(hdev); } @@ -2506,7 +2489,6 @@ static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_bu hci_conn_add_sysfs(conn); break; - case 0x10: /* Connection Accept Timeout */ case 0x11: /* Unsupported Feature or Parameter Value */ case 0x1c: /* SCO interval rejected */ case 0x1a: /* Unsupported Remote Feature */ @@ -2708,8 +2690,11 @@ static inline void hci_user_confirm_request_evt(struct hci_dev *hdev, /* If we're not the initiators request authorization to * proceed from user space (mgmt_user_confirm with - * confirm_hint set to 1). */ - if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { + * confirm_hint set to 1). The exception is if neither + * side had MITM in which case we do auto-accept. + */ + if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && + (loc_mitm || rem_mitm)) { BT_DBG("Confirming auto-accept as acceptor"); confirm_hint = 1; goto confirm; @@ -2755,11 +2740,9 @@ static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_ * initiated the authentication. A traditional auth_complete * event gets always produced as initiator and is also mapped to * the mgmt_auth_failed event */ - if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) { + if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0) mgmt_auth_failed(hdev->id, &conn->dst, ev->status); - conn->out = 1; - conn->disc_timeout = HCI_DISCONN_TIMEOUT/200; /* 0.01 sec */ - } + hci_conn_put(conn); unlock: @@ -2828,7 +2811,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); if (!conn) { - conn = hci_conn_add(hdev, LE_LINK, 0, &ev->bdaddr); + conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); if (!conn) { BT_ERR("No memory for new connection"); hci_dev_unlock(hdev); @@ -2846,7 +2829,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff goto unlock; } - mgmt_connected(hdev->id, &ev->bdaddr); + mgmt_connected(hdev->id, &ev->bdaddr, conn->type); conn->sec_level = BT_SECURITY_LOW; conn->handle = __le16_to_cpu(ev->handle); @@ -2864,19 +2847,17 @@ unlock: static inline void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_advertising_info *ev; - u8 num_reports; - - num_reports = skb->data[0]; - ev = (void *) &skb->data[1]; + u8 num_reports = skb->data[0]; + void *ptr = &skb->data[1]; hci_dev_lock(hdev); - hci_add_adv_entry(hdev, ev); + while (num_reports--) { + struct hci_ev_le_advertising_info *ev = ptr; - while (--num_reports) { - ev = (void *) (ev->data + ev->length + 1); hci_add_adv_entry(hdev, ev); + + ptr += sizeof(*ev) + ev->length + 1; } hci_dev_unlock(hdev); |