diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r-- | net/bluetooth/hci_event.c | 177 |
1 files changed, 125 insertions, 52 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 84093b0000b9..8923b36a67a2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <net/sock.h> | 39 | #include <net/sock.h> |
40 | 40 | ||
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | #include <asm/uaccess.h> | 42 | #include <linux/uaccess.h> |
43 | #include <asm/unaligned.h> | 43 | #include <asm/unaligned.h> |
44 | 44 | ||
45 | #include <net/bluetooth/bluetooth.h> | 45 | #include <net/bluetooth/bluetooth.h> |
@@ -677,9 +677,50 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) | |||
677 | hci_dev_unlock(hdev); | 677 | hci_dev_unlock(hdev); |
678 | } | 678 | } |
679 | 679 | ||
680 | static int hci_outgoing_auth_needed(struct hci_dev *hdev, | ||
681 | struct hci_conn *conn) | ||
682 | { | ||
683 | if (conn->state != BT_CONFIG || !conn->out) | ||
684 | return 0; | ||
685 | |||
686 | if (conn->sec_level == BT_SECURITY_SDP) | ||
687 | return 0; | ||
688 | |||
689 | /* Only request authentication for SSP connections or non-SSP | ||
690 | * devices with sec_level HIGH */ | ||
691 | if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && | ||
692 | conn->sec_level != BT_SECURITY_HIGH) | ||
693 | return 0; | ||
694 | |||
695 | return 1; | ||
696 | } | ||
697 | |||
680 | static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) | 698 | static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) |
681 | { | 699 | { |
700 | struct hci_cp_remote_name_req *cp; | ||
701 | struct hci_conn *conn; | ||
702 | |||
682 | BT_DBG("%s status 0x%x", hdev->name, status); | 703 | BT_DBG("%s status 0x%x", hdev->name, status); |
704 | |||
705 | /* If successful wait for the name req complete event before | ||
706 | * checking for the need to do authentication */ | ||
707 | if (!status) | ||
708 | return; | ||
709 | |||
710 | cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); | ||
711 | if (!cp) | ||
712 | return; | ||
713 | |||
714 | hci_dev_lock(hdev); | ||
715 | |||
716 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | ||
717 | if (conn && hci_outgoing_auth_needed(hdev, conn)) { | ||
718 | struct hci_cp_auth_requested cp; | ||
719 | cp.handle = __cpu_to_le16(conn->handle); | ||
720 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | ||
721 | } | ||
722 | |||
723 | hci_dev_unlock(hdev); | ||
683 | } | 724 | } |
684 | 725 | ||
685 | static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) | 726 | static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) |
@@ -955,12 +996,14 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
955 | 996 | ||
956 | hci_dev_lock(hdev); | 997 | hci_dev_lock(hdev); |
957 | 998 | ||
958 | if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) | 999 | ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); |
1000 | if (ie) | ||
959 | memcpy(ie->data.dev_class, ev->dev_class, 3); | 1001 | memcpy(ie->data.dev_class, ev->dev_class, 3); |
960 | 1002 | ||
961 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | 1003 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); |
962 | if (!conn) { | 1004 | if (!conn) { |
963 | if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { | 1005 | conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); |
1006 | if (!conn) { | ||
964 | BT_ERR("No memory for new connection"); | 1007 | BT_ERR("No memory for new connection"); |
965 | hci_dev_unlock(hdev); | 1008 | hci_dev_unlock(hdev); |
966 | return; | 1009 | return; |
@@ -1090,9 +1133,23 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1090 | 1133 | ||
1091 | static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1134 | static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1092 | { | 1135 | { |
1136 | struct hci_ev_remote_name *ev = (void *) skb->data; | ||
1137 | struct hci_conn *conn; | ||
1138 | |||
1093 | BT_DBG("%s", hdev->name); | 1139 | BT_DBG("%s", hdev->name); |
1094 | 1140 | ||
1095 | hci_conn_check_pending(hdev); | 1141 | hci_conn_check_pending(hdev); |
1142 | |||
1143 | hci_dev_lock(hdev); | ||
1144 | |||
1145 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
1146 | if (conn && hci_outgoing_auth_needed(hdev, conn)) { | ||
1147 | struct hci_cp_auth_requested cp; | ||
1148 | cp.handle = __cpu_to_le16(conn->handle); | ||
1149 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | ||
1150 | } | ||
1151 | |||
1152 | hci_dev_unlock(hdev); | ||
1096 | } | 1153 | } |
1097 | 1154 | ||
1098 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1155 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1162,33 +1219,39 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff | |||
1162 | hci_dev_lock(hdev); | 1219 | hci_dev_lock(hdev); |
1163 | 1220 | ||
1164 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 1221 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
1165 | if (conn) { | 1222 | if (!conn) |
1166 | if (!ev->status) | 1223 | goto unlock; |
1167 | memcpy(conn->features, ev->features, 8); | ||
1168 | 1224 | ||
1169 | if (conn->state == BT_CONFIG) { | 1225 | if (!ev->status) |
1170 | if (!ev->status && lmp_ssp_capable(hdev) && | 1226 | memcpy(conn->features, ev->features, 8); |
1171 | lmp_ssp_capable(conn)) { | 1227 | |
1172 | struct hci_cp_read_remote_ext_features cp; | 1228 | if (conn->state != BT_CONFIG) |
1173 | cp.handle = ev->handle; | 1229 | goto unlock; |
1174 | cp.page = 0x01; | 1230 | |
1175 | hci_send_cmd(hdev, | 1231 | if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { |
1176 | HCI_OP_READ_REMOTE_EXT_FEATURES, | 1232 | struct hci_cp_read_remote_ext_features cp; |
1177 | sizeof(cp), &cp); | 1233 | cp.handle = ev->handle; |
1178 | } else if (!ev->status && conn->out && | 1234 | cp.page = 0x01; |
1179 | conn->sec_level == BT_SECURITY_HIGH) { | 1235 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, |
1180 | struct hci_cp_auth_requested cp; | ||
1181 | cp.handle = ev->handle; | ||
1182 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, | ||
1183 | sizeof(cp), &cp); | 1236 | sizeof(cp), &cp); |
1184 | } else { | 1237 | goto unlock; |
1185 | conn->state = BT_CONNECTED; | 1238 | } |
1186 | hci_proto_connect_cfm(conn, ev->status); | 1239 | |
1187 | hci_conn_put(conn); | 1240 | if (!ev->status) { |
1188 | } | 1241 | struct hci_cp_remote_name_req cp; |
1189 | } | 1242 | memset(&cp, 0, sizeof(cp)); |
1243 | bacpy(&cp.bdaddr, &conn->dst); | ||
1244 | cp.pscan_rep_mode = 0x02; | ||
1245 | hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); | ||
1190 | } | 1246 | } |
1191 | 1247 | ||
1248 | if (!hci_outgoing_auth_needed(hdev, conn)) { | ||
1249 | conn->state = BT_CONNECTED; | ||
1250 | hci_proto_connect_cfm(conn, ev->status); | ||
1251 | hci_conn_put(conn); | ||
1252 | } | ||
1253 | |||
1254 | unlock: | ||
1192 | hci_dev_unlock(hdev); | 1255 | hci_dev_unlock(hdev); |
1193 | } | 1256 | } |
1194 | 1257 | ||
@@ -1449,10 +1512,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1449 | conn->sent -= count; | 1512 | conn->sent -= count; |
1450 | 1513 | ||
1451 | if (conn->type == ACL_LINK) { | 1514 | if (conn->type == ACL_LINK) { |
1452 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) | 1515 | hdev->acl_cnt += count; |
1516 | if (hdev->acl_cnt > hdev->acl_pkts) | ||
1453 | hdev->acl_cnt = hdev->acl_pkts; | 1517 | hdev->acl_cnt = hdev->acl_pkts; |
1454 | } else { | 1518 | } else { |
1455 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | 1519 | hdev->sco_cnt += count; |
1520 | if (hdev->sco_cnt > hdev->sco_pkts) | ||
1456 | hdev->sco_cnt = hdev->sco_pkts; | 1521 | hdev->sco_cnt = hdev->sco_pkts; |
1457 | } | 1522 | } |
1458 | } | 1523 | } |
@@ -1547,7 +1612,8 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1547 | if (conn && !ev->status) { | 1612 | if (conn && !ev->status) { |
1548 | struct inquiry_entry *ie; | 1613 | struct inquiry_entry *ie; |
1549 | 1614 | ||
1550 | if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { | 1615 | ie = hci_inquiry_cache_lookup(hdev, &conn->dst); |
1616 | if (ie) { | ||
1551 | ie->data.clock_offset = ev->clock_offset; | 1617 | ie->data.clock_offset = ev->clock_offset; |
1552 | ie->timestamp = jiffies; | 1618 | ie->timestamp = jiffies; |
1553 | } | 1619 | } |
@@ -1581,7 +1647,8 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff * | |||
1581 | 1647 | ||
1582 | hci_dev_lock(hdev); | 1648 | hci_dev_lock(hdev); |
1583 | 1649 | ||
1584 | if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) { | 1650 | ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); |
1651 | if (ie) { | ||
1585 | ie->data.pscan_rep_mode = ev->pscan_rep_mode; | 1652 | ie->data.pscan_rep_mode = ev->pscan_rep_mode; |
1586 | ie->timestamp = jiffies; | 1653 | ie->timestamp = jiffies; |
1587 | } | 1654 | } |
@@ -1646,32 +1713,37 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b | |||
1646 | hci_dev_lock(hdev); | 1713 | hci_dev_lock(hdev); |
1647 | 1714 | ||
1648 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 1715 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
1649 | if (conn) { | 1716 | if (!conn) |
1650 | if (!ev->status && ev->page == 0x01) { | 1717 | goto unlock; |
1651 | struct inquiry_entry *ie; | ||
1652 | 1718 | ||
1653 | if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) | 1719 | if (!ev->status && ev->page == 0x01) { |
1654 | ie->data.ssp_mode = (ev->features[0] & 0x01); | 1720 | struct inquiry_entry *ie; |
1655 | 1721 | ||
1656 | conn->ssp_mode = (ev->features[0] & 0x01); | 1722 | ie = hci_inquiry_cache_lookup(hdev, &conn->dst); |
1657 | } | 1723 | if (ie) |
1724 | ie->data.ssp_mode = (ev->features[0] & 0x01); | ||
1658 | 1725 | ||
1659 | if (conn->state == BT_CONFIG) { | 1726 | conn->ssp_mode = (ev->features[0] & 0x01); |
1660 | if (!ev->status && hdev->ssp_mode > 0 && | ||
1661 | conn->ssp_mode > 0 && conn->out && | ||
1662 | conn->sec_level != BT_SECURITY_SDP) { | ||
1663 | struct hci_cp_auth_requested cp; | ||
1664 | cp.handle = ev->handle; | ||
1665 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, | ||
1666 | sizeof(cp), &cp); | ||
1667 | } else { | ||
1668 | conn->state = BT_CONNECTED; | ||
1669 | hci_proto_connect_cfm(conn, ev->status); | ||
1670 | hci_conn_put(conn); | ||
1671 | } | ||
1672 | } | ||
1673 | } | 1727 | } |
1674 | 1728 | ||
1729 | if (conn->state != BT_CONFIG) | ||
1730 | goto unlock; | ||
1731 | |||
1732 | if (!ev->status) { | ||
1733 | struct hci_cp_remote_name_req cp; | ||
1734 | memset(&cp, 0, sizeof(cp)); | ||
1735 | bacpy(&cp.bdaddr, &conn->dst); | ||
1736 | cp.pscan_rep_mode = 0x02; | ||
1737 | hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); | ||
1738 | } | ||
1739 | |||
1740 | if (!hci_outgoing_auth_needed(hdev, conn)) { | ||
1741 | conn->state = BT_CONNECTED; | ||
1742 | hci_proto_connect_cfm(conn, ev->status); | ||
1743 | hci_conn_put(conn); | ||
1744 | } | ||
1745 | |||
1746 | unlock: | ||
1675 | hci_dev_unlock(hdev); | 1747 | hci_dev_unlock(hdev); |
1676 | } | 1748 | } |
1677 | 1749 | ||
@@ -1821,7 +1893,8 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ | |||
1821 | 1893 | ||
1822 | hci_dev_lock(hdev); | 1894 | hci_dev_lock(hdev); |
1823 | 1895 | ||
1824 | if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) | 1896 | ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); |
1897 | if (ie) | ||
1825 | ie->data.ssp_mode = (ev->features[0] & 0x01); | 1898 | ie->data.ssp_mode = (ev->features[0] & 0x01); |
1826 | 1899 | ||
1827 | hci_dev_unlock(hdev); | 1900 | hci_dev_unlock(hdev); |