mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-23 09:41:03 +00:00
l2cap: verify signaling command len for CONNECTION_REQUEST, INFORMATION_REQUEST, and INFORMATION_RESPONSE
This commit is contained in:
parent
ed2ed8e12c
commit
0493bf3a19
106
src/l2cap.c
106
src/l2cap.c
@ -2410,8 +2410,9 @@ static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t *
|
|||||||
btstack_linked_list_iterator_t it;
|
btstack_linked_list_iterator_t it;
|
||||||
|
|
||||||
// get code, signalind identifier and command len
|
// get code, signalind identifier and command len
|
||||||
uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET];
|
uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET];
|
||||||
uint8_t sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET];
|
uint8_t sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET];
|
||||||
|
uint16_t cmd_len = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET);
|
||||||
|
|
||||||
// not for a particular channel, and not CONNECTION_REQUEST, ECHO_[REQUEST|RESPONSE], INFORMATION_RESPONSE
|
// not for a particular channel, and not CONNECTION_REQUEST, ECHO_[REQUEST|RESPONSE], INFORMATION_RESPONSE
|
||||||
if (code < 1 || code == ECHO_RESPONSE || code > INFORMATION_RESPONSE){
|
if (code < 1 || code == ECHO_RESPONSE || code > INFORMATION_RESPONSE){
|
||||||
@ -2422,65 +2423,77 @@ static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t *
|
|||||||
// general commands without an assigned channel
|
// general commands without an assigned channel
|
||||||
switch(code) {
|
switch(code) {
|
||||||
|
|
||||||
case CONNECTION_REQUEST: {
|
case CONNECTION_REQUEST:
|
||||||
uint16_t psm = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
|
if (cmd_len == 4){
|
||||||
uint16_t source_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2);
|
uint16_t psm = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
|
||||||
l2cap_handle_connection_request(handle, sig_id, psm, source_cid);
|
uint16_t source_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2);
|
||||||
|
l2cap_handle_connection_request(handle, sig_id, psm, source_cid);
|
||||||
|
} else {
|
||||||
|
l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
case ECHO_REQUEST:
|
case ECHO_REQUEST:
|
||||||
l2cap_register_signaling_response(handle, code, sig_id, 0, 0);
|
l2cap_register_signaling_response(handle, code, sig_id, 0, 0);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case INFORMATION_REQUEST: {
|
case INFORMATION_REQUEST:
|
||||||
uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
|
if (cmd_len == 2) {
|
||||||
l2cap_register_signaling_response(handle, code, sig_id, 0, info_type);
|
uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
|
||||||
|
l2cap_register_signaling_response(handle, code, sig_id, 0, info_type);
|
||||||
|
} else {
|
||||||
|
l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
|
#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
|
||||||
case INFORMATION_RESPONSE: {
|
case INFORMATION_RESPONSE: {
|
||||||
hci_connection_t * connection = hci_connection_for_handle(handle);
|
hci_connection_t * connection = hci_connection_for_handle(handle);
|
||||||
if (!connection) return;
|
if (!connection) return;
|
||||||
uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
|
if (cmd_len >= 4) {
|
||||||
uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2);
|
uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
|
||||||
if (result != 0) return;
|
uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2);
|
||||||
if (info_type != L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED) return;
|
if (result != 0) return;
|
||||||
connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE;
|
if (info_type != L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED) return;
|
||||||
connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4);
|
if (cmd_len >= 6) {
|
||||||
log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask);
|
connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE;
|
||||||
// trigger connection request
|
connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4);
|
||||||
btstack_linked_list_iterator_init(&it, &l2cap_channels);
|
log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask);
|
||||||
while (btstack_linked_list_iterator_has_next(&it)){
|
// trigger connection request
|
||||||
l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
|
btstack_linked_list_iterator_init(&it, &l2cap_channels);
|
||||||
if (channel->con_handle != handle) continue;
|
while (btstack_linked_list_iterator_has_next(&it)){
|
||||||
// bail if ERTM was requested but is not supported
|
l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
|
||||||
if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){
|
if (channel->con_handle != handle) continue;
|
||||||
if (channel->ertm_mandatory){
|
// bail if ERTM was requested but is not supported
|
||||||
// channel closed
|
if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){
|
||||||
channel->state = L2CAP_STATE_CLOSED;
|
if (channel->ertm_mandatory){
|
||||||
// map l2cap connection response result to BTstack status enumeration
|
// channel closed
|
||||||
l2cap_emit_channel_opened(channel, L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTED);
|
channel->state = L2CAP_STATE_CLOSED;
|
||||||
// discard channel
|
// map l2cap connection response result to BTstack status enumeration
|
||||||
btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel);
|
l2cap_emit_channel_opened(channel, L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTED);
|
||||||
btstack_memory_l2cap_channel_free(channel);
|
// discard channel
|
||||||
continue;
|
btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel);
|
||||||
} else {
|
btstack_memory_l2cap_channel_free(channel);
|
||||||
// fallback to Basic mode
|
continue;
|
||||||
channel->mode = L2CAP_CHANNEL_MODE_BASIC;
|
} else {
|
||||||
|
// fallback to Basic mode
|
||||||
|
channel->mode = L2CAP_CHANNEL_MODE_BASIC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// start connecting
|
||||||
|
if (channel->state == L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES){
|
||||||
|
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
|
||||||
|
}
|
||||||
|
// respond to connection request
|
||||||
|
if (channel->state == L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES){
|
||||||
|
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
|
||||||
|
l2cap_emit_incoming_connection(channel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
return; // cmd len valid
|
||||||
// start connecting
|
|
||||||
if (channel->state == L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES){
|
|
||||||
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
|
|
||||||
}
|
|
||||||
// respond to connection request
|
|
||||||
if (channel->state == L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES){
|
|
||||||
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
|
|
||||||
l2cap_emit_incoming_connection(channel);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2489,7 +2502,6 @@ static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t *
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get potential destination CID
|
// Get potential destination CID
|
||||||
uint16_t dest_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
|
uint16_t dest_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user