diff options
-rw-r--r-- | net/bluetooth/mgmt.c | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 1ae14c91bb0..394222ef67a 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1567,29 +1567,14 @@ unlock: | |||
1567 | return err; | 1567 | return err; |
1568 | } | 1568 | } |
1569 | 1569 | ||
1570 | static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, | 1570 | static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr, |
1571 | u16 len, int success) | 1571 | u16 mgmt_op, u16 hci_op, __le32 passkey) |
1572 | { | 1572 | { |
1573 | struct mgmt_cp_user_confirm_reply *cp = (void *) data; | ||
1574 | u16 mgmt_op, hci_op; | ||
1575 | struct pending_cmd *cmd; | 1573 | struct pending_cmd *cmd; |
1576 | struct hci_dev *hdev; | 1574 | struct hci_dev *hdev; |
1575 | struct hci_conn *conn; | ||
1577 | int err; | 1576 | int err; |
1578 | 1577 | ||
1579 | BT_DBG(""); | ||
1580 | |||
1581 | if (success) { | ||
1582 | mgmt_op = MGMT_OP_USER_CONFIRM_REPLY; | ||
1583 | hci_op = HCI_OP_USER_CONFIRM_REPLY; | ||
1584 | } else { | ||
1585 | mgmt_op = MGMT_OP_USER_CONFIRM_NEG_REPLY; | ||
1586 | hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY; | ||
1587 | } | ||
1588 | |||
1589 | if (len != sizeof(*cp)) | ||
1590 | return cmd_status(sk, index, mgmt_op, | ||
1591 | MGMT_STATUS_INVALID_PARAMS); | ||
1592 | |||
1593 | hdev = hci_dev_get(index); | 1578 | hdev = hci_dev_get(index); |
1594 | if (!hdev) | 1579 | if (!hdev) |
1595 | return cmd_status(sk, index, mgmt_op, | 1580 | return cmd_status(sk, index, mgmt_op, |
@@ -1598,27 +1583,59 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, | |||
1598 | hci_dev_lock_bh(hdev); | 1583 | hci_dev_lock_bh(hdev); |
1599 | 1584 | ||
1600 | if (!test_bit(HCI_UP, &hdev->flags)) { | 1585 | if (!test_bit(HCI_UP, &hdev->flags)) { |
1601 | err = cmd_status(sk, index, mgmt_op, ENETDOWN); | 1586 | err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED); |
1602 | goto failed; | 1587 | goto done; |
1603 | } | 1588 | } |
1604 | 1589 | ||
1605 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, data, len); | 1590 | cmd = mgmt_pending_add(sk, mgmt_op, hdev, bdaddr, sizeof(*bdaddr)); |
1606 | if (!cmd) { | 1591 | if (!cmd) { |
1607 | err = -ENOMEM; | 1592 | err = -ENOMEM; |
1608 | goto failed; | 1593 | goto done; |
1609 | } | 1594 | } |
1610 | 1595 | ||
1611 | err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr); | 1596 | /* Continue with pairing via HCI */ |
1597 | err = hci_send_cmd(hdev, hci_op, sizeof(*bdaddr), bdaddr); | ||
1612 | if (err < 0) | 1598 | if (err < 0) |
1613 | mgmt_pending_remove(cmd); | 1599 | mgmt_pending_remove(cmd); |
1614 | 1600 | ||
1615 | failed: | 1601 | done: |
1616 | hci_dev_unlock_bh(hdev); | 1602 | hci_dev_unlock_bh(hdev); |
1617 | hci_dev_put(hdev); | 1603 | hci_dev_put(hdev); |
1618 | 1604 | ||
1619 | return err; | 1605 | return err; |
1620 | } | 1606 | } |
1621 | 1607 | ||
1608 | static int user_confirm_reply(struct sock *sk, u16 index, void *data, u16 len) | ||
1609 | { | ||
1610 | struct mgmt_cp_user_confirm_reply *cp = (void *) data; | ||
1611 | |||
1612 | BT_DBG(""); | ||
1613 | |||
1614 | if (len != sizeof(*cp)) | ||
1615 | return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY, | ||
1616 | MGMT_STATUS_INVALID_PARAMS); | ||
1617 | |||
1618 | return user_pairing_resp(sk, index, &cp->bdaddr, | ||
1619 | MGMT_OP_USER_CONFIRM_REPLY, | ||
1620 | HCI_OP_USER_CONFIRM_REPLY, 0); | ||
1621 | } | ||
1622 | |||
1623 | static int user_confirm_neg_reply(struct sock *sk, u16 index, void *data, | ||
1624 | u16 len) | ||
1625 | { | ||
1626 | struct mgmt_cp_user_confirm_reply *cp = (void *) data; | ||
1627 | |||
1628 | BT_DBG(""); | ||
1629 | |||
1630 | if (len != sizeof(*cp)) | ||
1631 | return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_NEG_REPLY, | ||
1632 | MGMT_STATUS_INVALID_PARAMS); | ||
1633 | |||
1634 | return user_pairing_resp(sk, index, &cp->bdaddr, | ||
1635 | MGMT_OP_USER_CONFIRM_NEG_REPLY, | ||
1636 | HCI_OP_USER_CONFIRM_NEG_REPLY, 0); | ||
1637 | } | ||
1638 | |||
1622 | static int set_local_name(struct sock *sk, u16 index, unsigned char *data, | 1639 | static int set_local_name(struct sock *sk, u16 index, unsigned char *data, |
1623 | u16 len) | 1640 | u16 len) |
1624 | { | 1641 | { |
@@ -2070,10 +2087,11 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
2070 | err = pair_device(sk, index, buf + sizeof(*hdr), len); | 2087 | err = pair_device(sk, index, buf + sizeof(*hdr), len); |
2071 | break; | 2088 | break; |
2072 | case MGMT_OP_USER_CONFIRM_REPLY: | 2089 | case MGMT_OP_USER_CONFIRM_REPLY: |
2073 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 1); | 2090 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len); |
2074 | break; | 2091 | break; |
2075 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: | 2092 | case MGMT_OP_USER_CONFIRM_NEG_REPLY: |
2076 | err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0); | 2093 | err = user_confirm_neg_reply(sk, index, buf + sizeof(*hdr), |
2094 | len); | ||
2077 | break; | 2095 | break; |
2078 | case MGMT_OP_SET_LOCAL_NAME: | 2096 | case MGMT_OP_SET_LOCAL_NAME: |
2079 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); | 2097 | err = set_local_name(sk, index, buf + sizeof(*hdr), len); |
@@ -2435,7 +2453,7 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
2435 | NULL); | 2453 | NULL); |
2436 | } | 2454 | } |
2437 | 2455 | ||
2438 | static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 2456 | static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2439 | u8 status, u8 opcode) | 2457 | u8 status, u8 opcode) |
2440 | { | 2458 | { |
2441 | struct pending_cmd *cmd; | 2459 | struct pending_cmd *cmd; |
@@ -2458,14 +2476,14 @@ static int confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
2458 | int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | 2476 | int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, |
2459 | u8 status) | 2477 | u8 status) |
2460 | { | 2478 | { |
2461 | return confirm_reply_complete(hdev, bdaddr, mgmt_status(status), | 2479 | return user_pairing_resp_complete(hdev, bdaddr, status, |
2462 | MGMT_OP_USER_CONFIRM_REPLY); | 2480 | MGMT_OP_USER_CONFIRM_REPLY); |
2463 | } | 2481 | } |
2464 | 2482 | ||
2465 | int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, | 2483 | int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, |
2466 | bdaddr_t *bdaddr, u8 status) | 2484 | bdaddr_t *bdaddr, u8 status) |
2467 | { | 2485 | { |
2468 | return confirm_reply_complete(hdev, bdaddr, mgmt_status(status), | 2486 | return user_pairing_resp_complete(hdev, bdaddr, status, |
2469 | MGMT_OP_USER_CONFIRM_NEG_REPLY); | 2487 | MGMT_OP_USER_CONFIRM_NEG_REPLY); |
2470 | } | 2488 | } |
2471 | 2489 | ||