diff options
Diffstat (limited to 'src/plugins/igmp/igmp_input.c')
-rw-r--r-- | src/plugins/igmp/igmp_input.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/src/plugins/igmp/igmp_input.c b/src/plugins/igmp/igmp_input.c index a49790fe119..1858a1b4d66 100644 --- a/src/plugins/igmp/igmp_input.c +++ b/src/plugins/igmp/igmp_input.c @@ -276,6 +276,7 @@ igmp_parse_query (vlib_main_t * vm, vlib_node_runtime_t * node, b = vlib_get_buffer (vm, bi); igmp = vlib_buffer_get_current (b); ASSERT (igmp->header.type == IGMP_TYPE_membership_query); + len = igmp_membership_query_v3_length (igmp); if (node->flags & VLIB_NODE_FLAG_TRACE) { @@ -283,17 +284,17 @@ igmp_parse_query (vlib_main_t * vm, vlib_node_runtime_t * node, tr = vlib_add_trace (vm, node, b, sizeof (*tr)); tr->next_index = next; tr->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; - tr->len = vlib_buffer_length_in_chain (vm, b); + tr->len = len; clib_memcpy_fast (tr->packet_data, vlib_buffer_get_current (b), sizeof (tr->packet_data)); } - len = igmp_membership_query_v3_length (igmp); /* - * validate that the length on the packet on the wire - * corresponds to the length on the calculated v3 query + * validate that the length on the packet on the wire corresponds + * to at least the length of the calculated v3 query. + * If there's extra, then it will be ignored. */ - if (vlib_buffer_length_in_chain (vm, b) == len) + if (vlib_buffer_length_in_chain (vm, b) >= len) { /* * copy the contents of the query, and the interface, over @@ -309,8 +310,8 @@ igmp_parse_query (vlib_main_t * vm, vlib_node_runtime_t * node, else { /* - * else a packet that is reporting more or less sources - * than it really has, bin it + * else a packet that is reporting more sources than it really + * has; bin it */ b->error = node->errors[IGMP_ERROR_BAD_LENGTH]; } @@ -394,6 +395,7 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node, igmp_input_trace_t *tr; tr = vlib_add_trace (vm, node, b, sizeof (*tr)); tr->next_index = next; + tr->len = len; tr->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; clib_memcpy_fast (tr->packet_data, vlib_buffer_get_current (b), sizeof (tr->packet_data)); @@ -403,7 +405,7 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node, * validate that the length on the packet on the wire * corresponds to the length on the calculated v3 query */ - if (vlib_buffer_length_in_chain (vm, b) == len) + if (vlib_buffer_length_in_chain (vm, b) >= len) { /* * copy the contents of the query, and the interface, over @@ -416,11 +418,15 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node, vl_api_rpc_call_main_thread (igmp_handle_report, (u8 *) args, sizeof (*args) + len); } - /* - * else - * this is a packet with more groups/sources than the - * header reports. bin it - */ + else + { + /* + * this is a packet with more groups/sources than the + * header reports. bin it + */ + b->error = node->errors[IGMP_ERROR_BAD_LENGTH]; + } + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi, next); } |