diff options
Diffstat (limited to 'src/plugins/igmp')
-rw-r--r-- | src/plugins/igmp/igmp_input.c | 68 | ||||
-rw-r--r-- | src/plugins/igmp/igmp_query.c | 4 | ||||
-rw-r--r-- | src/plugins/igmp/igmp_report.c | 8 |
3 files changed, 55 insertions, 25 deletions
diff --git a/src/plugins/igmp/igmp_input.c b/src/plugins/igmp/igmp_input.c index d4563bf366d..5f54a0ba223 100644 --- a/src/plugins/igmp/igmp_input.c +++ b/src/plugins/igmp/igmp_input.c @@ -259,8 +259,8 @@ igmp_parse_query (vlib_main_t * vm, vlib_node_runtime_t * node, { igmp_membership_query_v3_t *igmp; igmp_query_args_t *args; + u32 bi, next, len; vlib_buffer_t *b; - u32 bi, next; next = IGMP_PARSE_QUERY_NEXT_DROP; bi = from[0]; @@ -283,20 +283,29 @@ igmp_parse_query (vlib_main_t * vm, vlib_node_runtime_t * node, clib_memcpy (tr->packet_data, vlib_buffer_get_current (b), sizeof (tr->packet_data)); } + len = igmp_membership_query_v3_length (igmp); /* - * copy the contents of the query, and the interface, over - * to the main thread for processing + * 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) + { + /* + * copy the contents of the query, and the interface, over + * to the main thread for processing + */ + vlib_buffer_advance (b, -sizeof (u32)); + args = vlib_buffer_get_current (b); + args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; + + vl_api_rpc_call_main_thread (igmp_handle_query, + (u8 *) args, sizeof (*args) + len); + } + /* + * else a packet that is reporting more or less sources + * than it really has, bin it */ - vlib_buffer_advance (b, -sizeof (u32)); - args = vlib_buffer_get_current (b); - args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; - - vl_api_rpc_call_main_thread (igmp_handle_query, - (u8 *) args, - sizeof (*args) + - igmp_membership_query_v3_length - (igmp)); vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi, next); @@ -351,7 +360,7 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node, { igmp_membership_report_v3_t *igmp; igmp_report_args_t *args; - u32 bi, next; + u32 bi, next, len; vlib_buffer_t *b; next = IGMP_PARSE_REPORT_NEXT_DROP; @@ -368,6 +377,7 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node, error = IGMP_ERROR_NONE; b->error = error_node->errors[error]; igmp = vlib_buffer_get_current (b); + len = igmp_membership_report_v3_length (igmp); ASSERT (igmp->header.type == IGMP_TYPE_membership_report_v3); @@ -382,19 +392,27 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node, } /* - * copy the contents of the query, and the interface, over - * to the main thread for processing + * 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) + { + /* + * copy the contents of the query, and the interface, over + * to the main thread for processing + */ + vlib_buffer_advance (b, -sizeof (u32)); + args = vlib_buffer_get_current (b); + args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; + + 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 */ - vlib_buffer_advance (b, -sizeof (u32)); - args = vlib_buffer_get_current (b); - args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX]; - - vl_api_rpc_call_main_thread (igmp_handle_report, - (u8 *) args, - sizeof (*args) + - igmp_membership_report_v3_length - (igmp)); - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi, next); } diff --git a/src/plugins/igmp/igmp_query.c b/src/plugins/igmp/igmp_query.c index 1513023df2e..ae9a4d51e95 100644 --- a/src/plugins/igmp/igmp_query.c +++ b/src/plugins/igmp/igmp_query.c @@ -36,6 +36,10 @@ igmp_query_mk_source_list (const igmp_membership_query_v3_t * q) const ip4_address_t *s; u16 ii, n; + /* + * we validated this packet when we accepted it in the DP, so + * this number is safe to use + */ n = clib_net_to_host_u16 (q->n_src_addresses); if (0 == n) diff --git a/src/plugins/igmp/igmp_report.c b/src/plugins/igmp/igmp_report.c index 328b890c15e..2caa9361b70 100644 --- a/src/plugins/igmp/igmp_report.c +++ b/src/plugins/igmp/igmp_report.c @@ -25,6 +25,10 @@ igmp_group_mk_source_list (const igmp_membership_group_v3_t * r) const ip4_address_t *s; u16 ii, n; + /* + * we validated this packet when we accepted it in the DP, so + * this number is safe to use + */ n = clib_net_to_host_u16 (r->n_src_addresses); if (0 == n) @@ -172,6 +176,10 @@ igmp_handle_report (const igmp_report_args_t * args) return; } + /* + * we validated this packet when we accepted it in the DP, so + * this number is safe to use + */ n_groups = clib_net_to_host_u16 (args->report[0].n_groups); igmp_group = args->report[0].groups; |