reject invalid reconfigure

This commit is contained in:
Milanka Ringwald 2016-12-14 16:54:02 +01:00
parent e900f5b791
commit 479a52ee79
4 changed files with 56 additions and 35 deletions

View File

@ -331,7 +331,7 @@ typedef struct {
uint8_t in_use; // 1 bit, 0 - not in use, 1 - in use
avdtp_media_type_t media_type; // 4 bit
avdtp_sep_type_t type; // 1 bit, 0 - SRC, 1 - SNK
uint16_t registered_service_categories;
avdtp_capabilities_t capabilities;
} avdtp_sep_t;
@ -347,7 +347,8 @@ typedef enum {
typedef enum {
AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE,
AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS,
AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE
AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE,
AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE
} avdtp_acceptor_connection_state_t;
typedef enum {

View File

@ -97,11 +97,19 @@ static uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connectio
uint16_t registered_service_categories = 0;
int pos = 0;
avdtp_service_category_t category = (avdtp_service_category_t)packet[pos++];
connection->error_code = 0;
if (category < AVDTP_MEDIA_TRANSPORT || category > AVDTP_DELAY_REPORTING){
printf(" avdtp_unpack_service_capabilities wrong category %d\n", category);
printf(" ACP: BAD SERVICE CATEGORY %d\n", category);
connection->reject_service_category = category;
connection->error_code = BAD_SERV_CATEGORY;
return 0;
}
if (connection->signaling_packet.signal_identifier == AVDTP_SI_RECONFIGURE){
if (category != AVDTP_CONTENT_PROTECTION && category != AVDTP_MEDIA_CODEC){
connection->reject_service_category = category;
connection->error_code = INVALID_CAPABILITIES;
}
}
int i;
uint8_t cap_len = packet[pos++];
printf(" ACP: avdtp_unpack_service_capabilities: category %d, capability len %d, record size %d\n", category, cap_len, size);
@ -166,13 +174,13 @@ static uint16_t avdtp_unpack_service_capabilities(avdtp_connection_t * connectio
registered_service_categories = store_bit16(registered_service_categories, category, 1);
processed_cap_len = pos - processed_cap_len;
printf(" ACP: avdtp_unpack_service_capabilities 2: category %d, processed_cap_len %d, pos %d\n", category, processed_cap_len, pos);
if (cap_len <= processed_cap_len && pos < size-2){
category = (avdtp_service_category_t)packet[pos++];
cap_len = packet[pos++];
printf(" ACP: avdtp_unpack_service_capabilities: category %d, capability len %d, remaining record size %d\n", category, cap_len, size-pos);
}
}
// printf(" avdtp_unpack_service_capabilities done\n");
printf(" avdtp_unpack_service_capabilities done error %d\n", connection->error_code);
return registered_service_categories;
}
@ -217,6 +225,7 @@ static int avdtp_acceptor_process_chunk(avdtp_signaling_packet_t * signaling_pac
return signaling_packet->packet_type == AVDTP_SINGLE_PACKET || signaling_packet->packet_type == AVDTP_END_PACKET;
}
int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint, uint8_t * packet, uint16_t size){
if (!stream_endpoint) return 0;
@ -275,7 +284,6 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
break;
}
}
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
}
@ -304,9 +312,17 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_RECONFIGURE %p in state %d (AVDTP_STREAM_ENDPOINT_OPENED %d)\n", stream_endpoint, stream_endpoint->state, AVDTP_STREAM_ENDPOINT_OPENED);
avdtp_sep_t sep;
sep.seid = packet[3] >> 2;
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, packet+4, packet_size-4);
sep.seid = packet[2] >> 2;
sep.registered_service_categories = avdtp_unpack_service_capabilities(connection, &sep.capabilities, connection->signaling_packet.command+3, packet_size-3);
if (connection->error_code){
// fire capabilities parsing errors
printf(" ACP: REJECT CATEGORY, error code by upacking\n");
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
break;
}
// find sep or raise error
int i;
for (i = 0; i < stream_endpoint->remote_seps_num; i++){
@ -316,29 +332,12 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
}
if (stream_endpoint->remote_sep_index == 0xFF){
printf(" ACP: AVDTP_SI_RECONFIGURE, bad state seid %d not found\n", sep.seid);
printf(" ACP: REJECT AVDTP_SI_RECONFIGURE, BAD_ACP_SEID\n");
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
connection->error_code = BAD_ACP_SEID;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
break;
}
// only codec, and
uint16_t remaining_service_categories = sep.registered_service_categories;
if (get_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC-1)){
remaining_service_categories = store_bit16(sep.registered_service_categories, AVDTP_MEDIA_CODEC-1, 0);
}
if (get_bit16(sep.registered_service_categories, AVDTP_CONTENT_PROTECTION-1)){
remaining_service_categories = store_bit16(sep.registered_service_categories, AVDTP_CONTENT_PROTECTION-1, 0);
}
if (!remaining_service_categories) break;
// find first category that shouldn't be reconfigured
for (i = 1; i < 9; i++){
if (get_bit16(sep.registered_service_categories, i-1)){
connection->reject_service_category = i;
}
}
break;
}
case AVDTP_SI_OPEN:
@ -394,7 +393,7 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_st
return request_to_send;
}
static int avdtp_acceptor_send_response_reject_service_category(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t category, uint8_t error_code, uint8_t transaction_label){
int avdtp_acceptor_send_response_reject_service_category(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t category, uint8_t error_code, uint8_t transaction_label){
uint8_t command[4];
command[0] = avdtp_header(transaction_label, AVDTP_SINGLE_PACKET, AVDTP_RESPONSE_REJECT_MSG);
command[1] = (uint8_t)identifier;

View File

@ -55,6 +55,7 @@ int avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, avdtp_s
int avdtp_acceptor_stream_config_subsm_run(avdtp_connection_t * connection, avdtp_stream_endpoint_t * stream_endpoint);
int avdtp_acceptor_send_response_reject_with_error_code(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t error_code, uint8_t transaction_label);
int avdtp_acceptor_send_response_reject_service_category(uint16_t cid, avdtp_signal_identifier_t identifier, uint8_t category, uint8_t error_code, uint8_t transaction_label);
#if defined __cplusplus
}

View File

@ -435,6 +435,10 @@ static void avdtp_sink_handle_can_send_now(avdtp_connection_t * connection, uint
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE;
avdtp_acceptor_send_response_reject_with_error_code(connection->l2cap_signaling_cid, connection->reject_signal_identifier, connection->error_code, connection->acceptor_transaction_label);
break;
case AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE:
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_IDLE;
avdtp_acceptor_send_response_reject_service_category(connection->l2cap_signaling_cid, connection->reject_signal_identifier, connection->reject_service_category, connection->error_code, connection->acceptor_transaction_label);
break;
default:
break;
}
@ -483,13 +487,14 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
avdtp_stream_endpoint_t * stream_endpoint = NULL;
avdtp_read_signaling_header(&connection->signaling_packet, packet, size);
switch (connection->signaling_packet.message_type){
case AVDTP_CMD_MSG:
printf("AVDTP_CMD_MSG: ");
printf_hexdump(packet, size);
printf("\n");
connection->acceptor_transaction_label = connection->signaling_packet.transaction_label;
switch (connection->signaling_packet.signal_identifier){
case AVDTP_SI_DISCOVER:
printf(" -> AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS\n");
if (connection->state != AVDTP_SIGNALING_CONNECTION_OPENED) return 0;
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_ANSWER_DISCOVER_SEPS;
avdtp_sink_request_can_send_now_self(connection, connection->l2cap_signaling_cid);
@ -500,18 +505,32 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
case AVDTP_SI_GET_CONFIGURATION:
case AVDTP_SI_OPEN:
case AVDTP_SI_START:
case AVDTP_SI_RECONFIGURE:
case AVDTP_SI_CLOSE:
case AVDTP_SI_ABORT:
connection->query_seid = packet[2] >> 2;
stream_endpoint = get_avdtp_stream_endpoint_for_active_seid(connection->query_seid);
if (!stream_endpoint){
printf(" ACP: RESPONSE REJECT BAD_ACP_SEID\n");
connection->error_code = BAD_ACP_SEID;
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
break;
return 0;
}
return handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size);
case AVDTP_SI_RECONFIGURE:
connection->query_seid = packet[2] >> 2;
stream_endpoint = get_avdtp_stream_endpoint_for_active_seid(connection->query_seid);
if (!stream_endpoint){
printf(" ACP: CATEGORY RESPONSE REJECT BAD_ACP_SEID\n");
connection->error_code = BAD_ACP_SEID;
connection->reject_service_category = 0;
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
return 0;
}
return handle_l2cap_data_packet_for_stream_endpoint(connection, stream_endpoint, packet, size);
break;
case AVDTP_SI_SUSPEND:{
int i;
for (i=2; i<size; i++){
@ -529,6 +548,8 @@ static int handle_l2cap_data_packet_for_signaling_connection(avdtp_connection_t
}
break;
case AVDTP_RESPONSE_ACCEPT_MSG:
printf("handle_l2cap_data_packet_for_signaling_connection AVDTP_RESPONSE_ACCEPT_MSG\n");
switch (connection->signaling_packet.signal_identifier){
case AVDTP_SI_DISCOVER:
if (connection->signaling_packet.transaction_label != connection->initiator_transaction_label){
@ -645,16 +666,15 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
stream_endpoint = get_avdtp_stream_endpoint_for_l2cap_cid(channel);
if (!stream_endpoint){
if (!connection) break;
printf("avdtp L2CAP_DATA_PACKET: no stream enpoint for local cid 0x%02x found\n", channel);
connection->error_code = BAD_ACP_SEID;
connection->reject_signal_identifier = connection->signaling_packet.signal_identifier;
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_WITH_ERROR_CODE;
connection->acceptor_connection_state = AVDTP_SIGNALING_CONNECTION_ACCEPTOR_W2_REJECT_CATEGORY_WITH_ERROR_CODE;
avdtp_sink_request_can_send_now_self(connection, channel);
printf("avdtp L2CAP_DATA_PACKET: no stream enpoint for local cid 0x%02x found", channel);
break;
}
if (channel == stream_endpoint->connection->l2cap_signaling_cid){
printf(" handle_l2cap_data_packet_for_signaling_connection 1\n");
stream_endpoint_state_machine(stream_endpoint->connection, stream_endpoint, L2CAP_DATA_PACKET, 0, packet, size);
break;
}