Re: [PATCH 2/2] Bluetooth: Add local SSP OOB data to OOB ext data mgmt command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Johan,

> The Read Local Out Of Band Extended Data mgmt command is specified to
> return the SSP values when given a BR/EDR address type as input
> parameter. The returned values may include either the 192-bit variants
> of C and R, or their 256-bit variants, or both, depending on the status
> of Secure Connections and Secure Connections Only modes. If SSP is not
> enabled the command will only return the Class of Device value (like it
> has done so far).
> 
> Signed-off-by: Johan Hedberg <johan.hedberg@xxxxxxxxx>
> ---
> net/bluetooth/mgmt.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 149 insertions(+), 3 deletions(-)
> 
> diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
> index 845dfcc43a20..df721370605b 100644
> --- a/net/bluetooth/mgmt.c
> +++ b/net/bluetooth/mgmt.c
> @@ -6466,6 +6466,140 @@ static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
> 	return eir_len;
> }
> 
> +static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status,
> +					     u16 opcode, struct sk_buff *skb)
> +{
> +	const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
> +	struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
> +	u8 *h192, *r192, *h256, *r256;
> +	struct mgmt_pending_cmd *cmd;
> +	u16 eir_len;
> +	int err;
> +
> +	BT_DBG("%s status %u", hdev->name, status);
> +
> +	cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev);
> +	if (!cmd)
> +		return;
> +
> +	mgmt_cp = cmd->param;
> +
> +	if (status) {
> +		status = mgmt_status(status);
> +		eir_len = 0;
> +	} else if (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
> +		struct hci_rp_read_local_oob_data *rp;
> +
> +		if (skb->len != sizeof(*rp)) {
> +			status = MGMT_STATUS_FAILED;
> +			eir_len = 0;
> +		} else {
> +			status = MGMT_STATUS_SUCCESS;
> +			rp = (void *) skb->data;

I think the coding style proposes (void *)skb->data.

> +
> +			eir_len = 5 + 18 + 18;
> +			h192 = rp->hash;
> +			r192 = rp->rand;
> +			h256 = NULL;
> +			r256 = NULL;
> +		}
> +	} else {
> +		struct hci_rp_read_local_oob_ext_data *rp;
> +
> +		if (skb->len != sizeof(*rp)) {
> +			status = MGMT_STATUS_FAILED;
> +			eir_len = 0;
> +		} else {
> +			status = MGMT_STATUS_SUCCESS;
> +			rp = (void *) skb->data;

Same as above.

> +
> +			if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
> +				eir_len = 5 + 18 + 18;
> +				h192 = NULL;
> +				r192 = NULL;
> +			} else {
> +				eir_len = 5 + 18 + 18 + 18 + 18;
> +				h192 = rp->hash192;
> +				r192 = rp->rand192;
> +			}
> +
> +			h256 = rp->hash256;
> +			r256 = rp->rand256;
> +		}
> +	}
> +
> +	mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
> +	if (!mgmt_rp)
> +		goto done;
> +
> +	if (status)
> +		goto send_rsp;
> +
> +	eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
> +				  hdev->dev_class, 3);
> +
> +	if (h192 && r192) {
> +		eir_len = eir_append_data(mgmt_rp->eir, eir_len,
> +					  EIR_SSP_HASH_C192, h192, 16);
> +		eir_len = eir_append_data(mgmt_rp->eir, eir_len,
> +					  EIR_SSP_RAND_R192, r192, 16);
> +	}
> +
> +	if (h256 && r256) {
> +		eir_len = eir_append_data(mgmt_rp->eir, eir_len,
> +					  EIR_SSP_HASH_C256, h256, 16);
> +		eir_len = eir_append_data(mgmt_rp->eir, eir_len,
> +					  EIR_SSP_RAND_R256, r256, 16);
> +	}
> +
> +send_rsp:
> +	mgmt_rp->type = mgmt_cp->type;
> +	mgmt_rp->eir_len = cpu_to_le16(eir_len);
> +
> +	err = mgmt_cmd_complete(cmd->sk, hdev->id,
> +				MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
> +				mgmt_rp, sizeof(*mgmt_rp) + eir_len);
> +	if (err < 0 || status)
> +		goto done;
> +
> +	hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
> +
> +	err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
> +				 mgmt_rp, sizeof(*mgmt_rp) + eir_len,
> +				 HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
> +done:
> +	kfree(mgmt_rp);
> +	mgmt_pending_remove(cmd);
> +}
> +
> +static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
> +				  struct mgmt_cp_read_local_oob_ext_data *cp)
> +{
> +	struct mgmt_pending_cmd *cmd;
> +	struct hci_request req;
> +	int err;
> +
> +	cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
> +			       cp, sizeof(*cp));
> +	if (!cmd)
> +		return -ENOMEM;
> +
> +	hci_req_init(&req, hdev);
> +
> +	if (bredr_sc_enabled(hdev))
> +		hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
> +	else
> +		hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
> +
> +	err = hci_req_run_skb(&req, read_local_oob_ext_data_complete);
> +	if (err < 0) {
> +		mgmt_pending_remove(cmd);
> +		return err;
> +	}
> +
> +	return 0;
> +}
> +
> static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
> 				   void *data, u16 data_len)
> {
> @@ -6517,9 +6651,21 @@ static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
> 	eir_len = 0;
> 	switch (cp->type) {
> 	case BIT(BDADDR_BREDR):
> -		eir_len = eir_append_data(rp->eir, eir_len, EIR_CLASS_OF_DEV,
> -					  hdev->dev_class, 3);
> -		break;
> +		if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
> +			eir_len = eir_append_data(rp->eir, eir_len,
> +						  EIR_CLASS_OF_DEV,
> +						  hdev->dev_class, 3);
> +			break;
> +		}
> +
> +		err = read_local_ssp_oob_req(hdev, sk, cp);
> +		hci_dev_unlock(hdev);
> +		if (err) {
> +			status = MGMT_STATUS_FAILED;
> +			goto complete;
> +		}
> +
> +		goto done;


So I think in this specific case, doing it with if clauses is cleaner than the break and goto and easier to read:

	if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
		err = read_local_..
		hci_dev_unlock(hdev);
		if (!err)
			goto done;

		status = MGMT_STATUS_..
		goto completed;
	} else {
		eir_len = eir_append_data(..
	}
	break;


> 	case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
> 		if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
> 		    smp_generate_oob(hdev, hash, rand) < 0) {

Regards

Marcel

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux