net/bluetooth/hci_event.c

Source file repositories/reference/linux-study-clean/net/bluetooth/hci_event.c

File Facts

System
Linux kernel
Corpus path
net/bluetooth/hci_event.c
Extension
.c
Size
205571 bytes
Lines
7873
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

hci_dev_test_flag(hdev, HCI_CONFIG)) {
		hdev->hci_ver = rp->hci_ver;
		hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
		hdev->lmp_ver = rp->lmp_ver;
		hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
		hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
	}

	return rp->status;
}

static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data,
				   struct sk_buff *skb)
{
	struct hci_rp_read_enc_key_size *rp = data;
	struct hci_conn *conn;
	u16 handle;
	u8 status = rp->status;

	bt_dev_dbg(hdev, "status 0x%2.2x", status);

	handle = le16_to_cpu(rp->handle);

	hci_dev_lock(hdev);

	conn = hci_conn_hash_lookup_handle(hdev, handle);
	if (!conn) {
		status = 0xFF;
		goto done;
	}

	/* While unexpected, the read_enc_key_size command may fail. The most
	 * secure approach is to then assume the key size is 0 to force a
	 * disconnection.
	 */
	if (status) {
		bt_dev_err(hdev, "failed to read key size for handle %u",
			   handle);
		conn->enc_key_size = 0;
	} else {
		u8 *key_enc_size = hci_conn_key_enc_size(conn);

		conn->enc_key_size = rp->key_size;
		status = 0;

		/* Attempt to check if the key size is too small or if it has
		 * been downgraded from the last time it was stored as part of
		 * the link_key.
		 */
		if (conn->enc_key_size < hdev->min_enc_key_size ||
		    (key_enc_size && conn->enc_key_size < *key_enc_size)) {
			/* As slave role, the conn->state has been set to
			 * BT_CONNECTED and l2cap conn req might not be received
			 * yet, at this moment the l2cap layer almost does
			 * nothing with the non-zero status.
			 * So we also clear encrypt related bits, and then the
			 * handler of l2cap conn req will get the right secure
			 * state at a later time.
			 */
			status = HCI_ERROR_AUTH_FAILURE;
			clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
			clear_bit(HCI_CONN_AES_CCM, &conn->flags);
		}

		/* Update the key encryption size with the connection one */
		if (key_enc_size && *key_enc_size != conn->enc_key_size)
			*key_enc_size = conn->enc_key_size;
	}

	hci_encrypt_cfm(conn, status);

done:
	hci_dev_unlock(hdev);

	return status;
}

static u8 hci_cc_read_local_commands(struct hci_dev *hdev, void *data,
				     struct sk_buff *skb)
{
	struct hci_rp_read_local_commands *rp = data;

	bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);

	if (rp->status)
		return rp->status;

	if (hci_dev_test_flag(hdev, HCI_SETUP) ||
	    hci_dev_test_flag(hdev, HCI_CONFIG))
		memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));

Annotation

Implementation Notes