aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorBrian Gix <bgix@codeaurora.org>2011-11-23 11:28:33 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-12-01 08:51:53 -0500
commit604086b73b9b342414a53c0f34dd23aecb005ff8 (patch)
treed378965d8c019f52f957e4dffb00e17cf36ea7ed /net/bluetooth/mgmt.c
parentbadaaa00f2122bab4bc2d46c26d6fad6af50f97c (diff)
Bluetooth: Add User Passkey Response handling
For some MITM protection pairing scenarios, the user is required to enter or accept a 6 digit passkey. Signed-off-by: Brian Gix <bgix@codeaurora.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c74
1 files changed, 73 insertions, 1 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index c06a05c09a9..7a23f211d60 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1618,7 +1618,15 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr,
1618 } 1618 }
1619 1619
1620 /* Continue with pairing via HCI */ 1620 /* Continue with pairing via HCI */
1621 err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); 1621 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
1622 struct hci_cp_user_passkey_reply cp;
1623
1624 bacpy(&cp.bdaddr, bdaddr);
1625 cp.passkey = passkey;
1626 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
1627 } else
1628 err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr);
1629
1622 if (err < 0) 1630 if (err < 0)
1623 mgmt_pending_remove(cmd); 1631 mgmt_pending_remove(cmd);
1624 1632
@@ -1660,6 +1668,37 @@ static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data,
1660 HCI_OP_USER_CONFIRM_NEG_REPLY, 0); 1668 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
1661} 1669}
1662 1670
1671static int user_passkey_reply(struct sock *sk, u16 index, void *data, u16 len)
1672{
1673 struct mgmt_cp_user_passkey_reply *cp = (void *) data;
1674
1675 BT_DBG("");
1676
1677 if (len != sizeof(*cp))
1678 return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_REPLY,
1679 EINVAL);
1680
1681 return user_pairing_resp(sk, index, &cp->bdaddr,
1682 MGMT_OP_USER_PASSKEY_REPLY,
1683 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
1684}
1685
1686static int user_passkey_neg_reply(struct sock *sk, u16 index, void *data,
1687 u16 len)
1688{
1689 struct mgmt_cp_user_passkey_neg_reply *cp = (void *) data;
1690
1691 BT_DBG("");
1692
1693 if (len != sizeof(*cp))
1694 return cmd_status(sk, index, MGMT_OP_USER_PASSKEY_NEG_REPLY,
1695 EINVAL);
1696
1697 return user_pairing_resp(sk, index, &cp->bdaddr,
1698 MGMT_OP_USER_PASSKEY_NEG_REPLY,
1699 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
1700}
1701
1663static int set_local_name(struct sock *sk, u16 index, unsigned char *data, 1702static int set_local_name(struct sock *sk, u16 index, unsigned char *data,
1664 u16 len) 1703 u16 len)
1665{ 1704{
@@ -2117,6 +2156,13 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
2117 err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr), 2156 err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr),
2118 len); 2157 len);
2119 break; 2158 break;
2159 case MGMT_OP_USER_PASSKEY_REPLY:
2160 err = user_passkey_reply(sk, index, buf + sizeof(*hdr), len);
2161 break;
2162 case MGMT_OP_USER_PASSKEY_NEG_REPLY:
2163 err = user_passkey_neg_reply(sk, index, buf + sizeof(*hdr),
2164 len);
2165 break;
2120 case MGMT_OP_SET_LOCAL_NAME: 2166 case MGMT_OP_SET_LOCAL_NAME:
2121 err = set_local_name(sk, index, buf + sizeof(*hdr), len); 2167 err = set_local_name(sk, index, buf + sizeof(*hdr), len);
2122 break; 2168 break;
@@ -2477,6 +2523,18 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
2477 NULL); 2523 NULL);
2478} 2524}
2479 2525
2526int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr)
2527{
2528 struct mgmt_ev_user_passkey_request ev;
2529
2530 BT_DBG("%s", hdev->name);
2531
2532 bacpy(&ev.bdaddr, bdaddr);
2533
2534 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
2535 NULL);
2536}
2537
2480static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, 2538static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2481 u8 status, u8 opcode) 2539 u8 status, u8 opcode)
2482{ 2540{
@@ -2511,6 +2569,20 @@ int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
2511 MGMT_OP_USER_CONFIRM_NEG_REPLY); 2569 MGMT_OP_USER_CONFIRM_NEG_REPLY);
2512} 2570}
2513 2571
2572int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
2573 u8 status)
2574{
2575 return user_pairing_resp_complete(hdev, bdaddr, status,
2576 MGMT_OP_USER_PASSKEY_REPLY);
2577}
2578
2579int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev,
2580 bdaddr_t *bdaddr, u8 status)
2581{
2582 return user_pairing_resp_complete(hdev, bdaddr, status,
2583 MGMT_OP_USER_PASSKEY_NEG_REPLY);
2584}
2585
2514int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status) 2586int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status)
2515{ 2587{
2516 struct mgmt_ev_auth_failed ev; 2588 struct mgmt_ev_auth_failed ev;