From 1cf68d3dacd359b4d732e508045b45d9f8e3094a Mon Sep 17 00:00:00 2001 From: Piotr Narajowski Date: Fri, 20 Sep 2024 15:10:09 +0200 Subject: [PATCH] nimble/host: add eatt opcode check in ble_eatt_l2cap_event_fn Att opcode check caused l2cap disconnection when opcode included in received data was write command which is supported and can be used on eatt. Also, the comment seemed irrelevant. Fixes GATT/SR/GAW/BV-01-C --- nimble/host/src/ble_att.c | 45 ++++++++++++++++++++++++++++++ nimble/host/src/ble_att_cmd_priv.h | 2 ++ nimble/host/src/ble_eatt.c | 17 +++++------ 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/nimble/host/src/ble_att.c b/nimble/host/src/ble_att.c index 5e221824c3..f5d7588527 100644 --- a/nimble/host/src/ble_att.c +++ b/nimble/host/src/ble_att.c @@ -635,6 +635,51 @@ ble_att_create_chan(uint16_t conn_handle) return chan; } +bool +ble_eatt_supported_op(uint8_t opcode) +{ + switch (opcode) { + case BLE_ATT_OP_WRITE_CMD: + case BLE_ATT_OP_FIND_INFO_REQ: + case BLE_ATT_OP_FIND_TYPE_VALUE_REQ: + case BLE_ATT_OP_READ_TYPE_REQ: + case BLE_ATT_OP_READ_REQ: + case BLE_ATT_OP_READ_BLOB_REQ: + case BLE_ATT_OP_READ_MULT_REQ: + case BLE_ATT_OP_READ_GROUP_TYPE_REQ: + case BLE_ATT_OP_WRITE_REQ: + case BLE_ATT_OP_PREP_WRITE_REQ: + case BLE_ATT_OP_EXEC_WRITE_REQ: + case BLE_ATT_OP_INDICATE_REQ: + case BLE_ATT_OP_READ_MULT_VAR_REQ: + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + return true; + } + return false; +} + +bool +ble_eatt_supported_rsp(uint8_t opcode) +{ + switch (opcode) { + case BLE_ATT_OP_ERROR_RSP: + case BLE_ATT_OP_FIND_INFO_RSP: + case BLE_ATT_OP_FIND_TYPE_VALUE_RSP: + case BLE_ATT_OP_READ_TYPE_RSP: + case BLE_ATT_OP_INDICATE_RSP: + case BLE_ATT_OP_READ_RSP: + case BLE_ATT_OP_READ_BLOB_RSP: + case BLE_ATT_OP_READ_MULT_RSP: + case BLE_ATT_OP_READ_GROUP_TYPE_RSP: + case BLE_ATT_OP_WRITE_RSP: + case BLE_ATT_OP_PREP_WRITE_RSP: + case BLE_ATT_OP_EXEC_WRITE_RSP: + case BLE_ATT_OP_READ_MULT_VAR_RSP: + return true; + } + return false; +} + bool ble_att_is_request_op(uint8_t opcode) { diff --git a/nimble/host/src/ble_att_cmd_priv.h b/nimble/host/src/ble_att_cmd_priv.h index 78c60d5ef4..2fc7aed03b 100644 --- a/nimble/host/src/ble_att_cmd_priv.h +++ b/nimble/host/src/ble_att_cmd_priv.h @@ -462,6 +462,8 @@ int ble_att_tx_with_conn(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, struct os_mbuf *txom); bool ble_att_is_response_op(uint8_t opcode); bool ble_att_is_request_op(uint8_t opcode); +bool ble_eatt_supported_op(uint8_t opcode); +bool ble_eatt_supported_rsp(uint8_t opcode); #ifdef __cplusplus } #endif diff --git a/nimble/host/src/ble_eatt.c b/nimble/host/src/ble_eatt.c index c15f545b6d..bf88f4cc55 100644 --- a/nimble/host/src/ble_eatt.c +++ b/nimble/host/src/ble_eatt.c @@ -266,15 +266,16 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg) case BLE_L2CAP_EVENT_COC_DATA_RECEIVED: assert(eatt->chan == event->receive.chan); opcode = event->receive.sdu_rx->om_data[0]; - if (ble_att_is_response_op(opcode)) { + if (ble_eatt_supported_rsp(opcode)) { ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); - } else if (!ble_att_is_request_op(opcode)) { - /* As per BLE 5.4 Standard, Vol. 3, Part F, section 5.3.2 - * (ENHANCED ATT BEARER L2CAP INTEROPERABILITY REQUIREMENTS: - * Channel Requirements): - * All packets sent on this L2CAP channel shall be Attribute PDUs. - * - * Disconnect peer with invalid behavior. + } else if (!ble_eatt_supported_op(opcode)) { + /* If an ATT PDU is supported on any ATT bearer, then it shall be + * supported on all supported ATT bearers with the following + * exceptions: + * • The Exchange MTU sub-procedure shall only be supported on the + * LE Fixed Channel Unenhanced ATT bearer. + * • The Signed Write Without Response sub-procedure shall only be + * supported on the LE Fixed Channel Unenhanced ATT bearer. */ ble_l2cap_disconnect(eatt->chan); return BLE_HS_EREJECT;