diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
-rw-r--r-- | net/bluetooth/hci_event.c | 72 |
1 files changed, 54 insertions, 18 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 9c6d9bc1d8af..4165895049b3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -677,11 +677,9 @@ 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_request_outgoing_auth(struct hci_dev *hdev, | 680 | static int hci_outgoing_auth_needed(struct hci_dev *hdev, |
681 | struct hci_conn *conn) | 681 | struct hci_conn *conn) |
682 | { | 682 | { |
683 | struct hci_cp_auth_requested cp; | ||
684 | |||
685 | if (conn->state != BT_CONFIG || !conn->out) | 683 | if (conn->state != BT_CONFIG || !conn->out) |
686 | return 0; | 684 | return 0; |
687 | 685 | ||
@@ -694,15 +692,35 @@ static int hci_request_outgoing_auth(struct hci_dev *hdev, | |||
694 | conn->sec_level != BT_SECURITY_HIGH) | 692 | conn->sec_level != BT_SECURITY_HIGH) |
695 | return 0; | 693 | return 0; |
696 | 694 | ||
697 | cp.handle = __cpu_to_le16(conn->handle); | ||
698 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | ||
699 | |||
700 | return 1; | 695 | return 1; |
701 | } | 696 | } |
702 | 697 | ||
703 | 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) |
704 | { | 699 | { |
700 | struct hci_cp_remote_name_req *cp; | ||
701 | struct hci_conn *conn; | ||
702 | |||
705 | 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); | ||
706 | } | 724 | } |
707 | 725 | ||
708 | 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) |
@@ -1113,9 +1131,23 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1113 | 1131 | ||
1114 | static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1132 | static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1115 | { | 1133 | { |
1134 | struct hci_ev_remote_name *ev = (void *) skb->data; | ||
1135 | struct hci_conn *conn; | ||
1136 | |||
1116 | BT_DBG("%s", hdev->name); | 1137 | BT_DBG("%s", hdev->name); |
1117 | 1138 | ||
1118 | hci_conn_check_pending(hdev); | 1139 | hci_conn_check_pending(hdev); |
1140 | |||
1141 | hci_dev_lock(hdev); | ||
1142 | |||
1143 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
1144 | if (conn && hci_outgoing_auth_needed(hdev, conn)) { | ||
1145 | struct hci_cp_auth_requested cp; | ||
1146 | cp.handle = __cpu_to_le16(conn->handle); | ||
1147 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | ||
1148 | } | ||
1149 | |||
1150 | hci_dev_unlock(hdev); | ||
1119 | } | 1151 | } |
1120 | 1152 | ||
1121 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1153 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1179,7 +1211,6 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff | |||
1179 | { | 1211 | { |
1180 | struct hci_ev_remote_features *ev = (void *) skb->data; | 1212 | struct hci_ev_remote_features *ev = (void *) skb->data; |
1181 | struct hci_conn *conn; | 1213 | struct hci_conn *conn; |
1182 | int auth_requested; | ||
1183 | 1214 | ||
1184 | BT_DBG("%s status %d", hdev->name, ev->status); | 1215 | BT_DBG("%s status %d", hdev->name, ev->status); |
1185 | 1216 | ||
@@ -1204,12 +1235,15 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff | |||
1204 | goto unlock; | 1235 | goto unlock; |
1205 | } | 1236 | } |
1206 | 1237 | ||
1207 | if (!ev->status) | 1238 | if (!ev->status) { |
1208 | auth_requested = hci_request_outgoing_auth(hdev, conn); | 1239 | struct hci_cp_remote_name_req cp; |
1209 | else | 1240 | memset(&cp, 0, sizeof(cp)); |
1210 | auth_requested = 0; | 1241 | bacpy(&cp.bdaddr, &conn->dst); |
1242 | cp.pscan_rep_mode = 0x02; | ||
1243 | hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); | ||
1244 | } | ||
1211 | 1245 | ||
1212 | if (!auth_requested) { | 1246 | if (!hci_outgoing_auth_needed(hdev, conn)) { |
1213 | conn->state = BT_CONNECTED; | 1247 | conn->state = BT_CONNECTED; |
1214 | hci_proto_connect_cfm(conn, ev->status); | 1248 | hci_proto_connect_cfm(conn, ev->status); |
1215 | hci_conn_put(conn); | 1249 | hci_conn_put(conn); |
@@ -1667,7 +1701,6 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b | |||
1667 | { | 1701 | { |
1668 | struct hci_ev_remote_ext_features *ev = (void *) skb->data; | 1702 | struct hci_ev_remote_ext_features *ev = (void *) skb->data; |
1669 | struct hci_conn *conn; | 1703 | struct hci_conn *conn; |
1670 | int auth_requested; | ||
1671 | 1704 | ||
1672 | BT_DBG("%s", hdev->name); | 1705 | BT_DBG("%s", hdev->name); |
1673 | 1706 | ||
@@ -1689,12 +1722,15 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b | |||
1689 | if (conn->state != BT_CONFIG) | 1722 | if (conn->state != BT_CONFIG) |
1690 | goto unlock; | 1723 | goto unlock; |
1691 | 1724 | ||
1692 | if (!ev->status) | 1725 | if (!ev->status) { |
1693 | auth_requested = hci_request_outgoing_auth(hdev, conn); | 1726 | struct hci_cp_remote_name_req cp; |
1694 | else | 1727 | memset(&cp, 0, sizeof(cp)); |
1695 | auth_requested = 0; | 1728 | bacpy(&cp.bdaddr, &conn->dst); |
1729 | cp.pscan_rep_mode = 0x02; | ||
1730 | hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); | ||
1731 | } | ||
1696 | 1732 | ||
1697 | if (!auth_requested) { | 1733 | if (!hci_outgoing_auth_needed(hdev, conn)) { |
1698 | conn->state = BT_CONNECTED; | 1734 | conn->state = BT_CONNECTED; |
1699 | hci_proto_connect_cfm(conn, ev->status); | 1735 | hci_proto_connect_cfm(conn, ev->status); |
1700 | hci_conn_put(conn); | 1736 | hci_conn_put(conn); |