summaryrefslogtreecommitdiffstats
path: root/src/plugins/igmp/igmp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/igmp/igmp_input.c')
-rw-r--r--src/plugins/igmp/igmp_input.c68
1 files changed, 43 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);
}