{
u32 next_index;
u32 sw_if_index;
-
+ u32 len;
u8 packet_data[64];
} igmp_input_trace_t;
CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
igmp_input_trace_t *t = va_arg (*va, igmp_input_trace_t *);
- s = format (s, "sw_if_index %u next-input %u",
- t->sw_if_index, t->next_index);
+ s = format (s, "sw_if_index %u next-input %u len %u",
+ t->sw_if_index, t->next_index, t->len);
s = format (s, "\n%U", format_igmp_query_v3, t->packet_data,
sizeof (t->packet_data));
+ s = format (s, "\n%U", format_hex_bytes,
+ t->packet_data, sizeof (t->packet_data));
return s;
}
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];
- clib_memcpy (tr->packet_data, vlib_buffer_get_current (b),
- sizeof (tr->packet_data));
+ tr->len = vlib_buffer_length_in_chain (vm, b);
+ clib_memcpy_fast (tr->packet_data, vlib_buffer_get_current (b),
+ sizeof (tr->packet_data));
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
{
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];
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)
{
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];
- clib_memcpy (tr->packet_data, vlib_buffer_get_current (b),
- sizeof (tr->packet_data));
+ tr->len = len;
+ clib_memcpy_fast (tr->packet_data, vlib_buffer_get_current (b),
+ sizeof (tr->packet_data));
}
/*
- * 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 at least the length of the calculated v3 query.
+ * If there's extra, then it will be ignored.
*/
- 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));
+ 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
+ {
+ /*
+ * else a packet that is reporting more sources than it really
+ * has; 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);
{
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;
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);
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 (tr->packet_data, vlib_buffer_get_current (b),
- sizeof (tr->packet_data));
+ clib_memcpy_fast (tr->packet_data, vlib_buffer_get_current (b),
+ sizeof (tr->packet_data));
}
/*
- * 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
*/
- 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));
+ 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
+ */
+ 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);
static clib_error_t *
igmp_input_init (vlib_main_t * vm)
{
- clib_error_t *error;
-
- if ((error = vlib_call_init_function (vm, igmp_init)))
- return error;
-
ip4_register_protocol (IP_PROTOCOL_IGMP, igmp_input_node.index);
IGMP_DBG ("input-initialized");
- return (error);
+ return (0);
}
-VLIB_INIT_FUNCTION (igmp_input_init);
+/* *INDENT-OFF* */
+VLIB_INIT_FUNCTION (igmp_input_init) =
+{
+ .runs_after = VLIB_INITS("igmp_init"),
+};
+/* *INDENT-ON* */
/*
* fd.io coding-style-patch-verification: ON