aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/ip/ip4_to_ip6.h21
-rw-r--r--src/vnet/ip/ip6_to_ip4.h14
2 files changed, 33 insertions, 2 deletions
diff --git a/src/vnet/ip/ip4_to_ip6.h b/src/vnet/ip/ip4_to_ip6.h
index d356fd5411c..3c14a59f174 100644
--- a/src/vnet/ip/ip4_to_ip6.h
+++ b/src/vnet/ip/ip4_to_ip6.h
@@ -37,6 +37,20 @@ static u8 icmp_to_icmp6_updater_pointer_table[] =
#define frag_id_4to6(id) (id)
+always_inline u64
+icmp_type_is_error_message (u8 icmp_type)
+{
+ int bmp = 0;
+ bmp |= 1 << ICMP4_destination_unreachable;
+ bmp |= 1 << ICMP4_time_exceeded;
+ bmp |= 1 << ICMP4_parameter_problem;
+ bmp |= 1 << ICMP4_source_quench;
+ bmp |= 1 << ICMP4_redirect;
+ bmp |= 1 << ICMP4_alternate_host_address;
+
+ return (1ULL << icmp_type) & bmp;
+}
+
/**
* @brief Get TCP/UDP port number or ICMP id from IPv4 packet.
*
@@ -70,9 +84,14 @@ ip4_get_port (ip4_header_t *ip, u8 sender)
* - outer ICMP header length (2*sizeof (icmp46_header_t))
* - inner IP header length
* - first 8 bytes of payload of original packet in case of ICMP error
+ *
+ * Also make sure we only attempt to parse payload as IP packet if it's
+ * an ICMP error.
*/
else if (clib_net_to_host_u16 (ip->length) >=
- 2 * sizeof (ip4_header_t) + 2 * sizeof (icmp46_header_t) + 8)
+ 2 * sizeof (ip4_header_t) + 2 * sizeof (icmp46_header_t) +
+ 8 &&
+ icmp_type_is_error_message (icmp->type))
{
ip = (ip4_header_t *) (icmp + 2);
if (PREDICT_TRUE ((ip->protocol == IP_PROTOCOL_TCP) ||
diff --git a/src/vnet/ip/ip6_to_ip4.h b/src/vnet/ip/ip6_to_ip4.h
index ebabcd0b797..931d2da0fa3 100644
--- a/src/vnet/ip/ip6_to_ip4.h
+++ b/src/vnet/ip/ip6_to_ip4.h
@@ -168,7 +168,19 @@ ip6_get_port (vlib_main_t *vm, vlib_buffer_t *b, ip6_header_t *ip6,
if (dst_port)
*dst_port = ((u16 *) (icmp))[2];
}
- else if (clib_net_to_host_u16 (ip6->payload_length) >= 64)
+ /*
+ * if there is enough data and ICMP type indicates ICMP error, then parse
+ * inner packet
+ *
+ * ICMP6 errors are:
+ * 1 - destination_unreachable
+ * 2 - packet_too_big
+ * 3 - time_exceeded
+ * 4 - parameter_problem
+ */
+ else if (clib_net_to_host_u16 (ip6->payload_length) >= 64 &&
+ icmp->type >= ICMP6_destination_unreachable &&
+ icmp->type <= ICMP6_parameter_problem)
{
u16 ip6_pay_len;
ip6_header_t *inner_ip6;