struct mgmt_hdr *hdr;
struct mgmt_ev_cmd_status *ev;
- BT_DBG("sock %p", sk);
+ BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
if (!skb)
ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
put_unaligned_le16(cmd, &ev->opcode);
- memcpy(ev->data, rp, rp_len);
+
+ if (rp)
+ memcpy(ev->data, rp, rp_len);
if (sock_queue_rcv_skb(sk, skb) < 0)
kfree_skb(skb);
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
int i;
cp = (void *) data;
+
+ if (len < sizeof(*cp))
+ return -EINVAL;
+
key_count = get_unaligned_le16(&cp->key_count);
expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
return err;
}
-static int get_connections(struct sock *sk, u16 index, unsigned char *data,
- u16 len)
+static int get_connections(struct sock *sk, u16 index)
{
- struct mgmt_cp_get_connections *cp;
struct mgmt_rp_get_connections *rp;
struct hci_dev *hdev;
struct list_head *p;
BT_DBG("");
- cp = (void *) data;
-
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+ EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
goto failed;
}
- err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(bdaddr_t),
+ err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
&cp->bdaddr);
if (err < 0)
mgmt_pending_remove(cmd);
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
hdev->io_capability = cp->io_capability;
BT_DBG("%s IO capability set to 0x%02x", hdev->name,
- hdev->io_capability);
+ hdev->io_capability);
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
}
conn = hci_connect(hdev, ACL_LINK, &cp->bdaddr, sec_level, auth_type);
- if (!conn) {
- err = -ENOMEM;
+ if (IS_ERR(conn)) {
+ err = PTR_ERR(conn);
goto unlock;
}
hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
}
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, mgmt_op, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, mgmt_op, ENODEV);
err = disconnect(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_GET_CONNECTIONS:
- err = get_connections(sk, index, buf + sizeof(*hdr), len);
+ err = get_connections(sk, index);
break;
case MGMT_OP_PIN_CODE_REPLY:
err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
struct cmd_lookup match = { discoverable, NULL };
int ret;
- mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index,
- mode_rsp, &match);
+ mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match);
ev.val = discoverable;
MGMT_OP_USER_CONFIRM_REPLY);
}
-int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
- u8 status)
+int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
{
return confirm_reply_complete(index, bdaddr, status,
MGMT_OP_USER_CONFIRM_NEG_REPLY);