From a6eebf567f039c50ed9d2d1c9f53baf6df1d685a Mon Sep 17 00:00:00 2001 From: Mike Neilsen <mneilsen@acm.org> Date: Sun, 24 Nov 2013 12:02:59 -0600 Subject: [PATCH] net-test: packetdrill: add ICMPv4 and ICMPv6 packet parsing Handle ICMPv4 and ICMPv6 parsing separately. Return PACKET_BAD if IP and ICMP versions mismatch. Signed-off-by: Mike Neilsen <mneilsen@acm.org> Signed-off-by: Neal Cardwell <ncardwell@google.com> --- gtests/net/packetdrill/packet_parser.c | 85 ++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/gtests/net/packetdrill/packet_parser.c b/gtests/net/packetdrill/packet_parser.c index 697c5aa1..ff64dedb 100644 --- a/gtests/net/packetdrill/packet_parser.c +++ b/gtests/net/packetdrill/packet_parser.c @@ -441,6 +441,83 @@ error_out: return PACKET_BAD; } +/* Parse the ICMPv4 header. Return a packet_parse_result_t. */ +static int parse_icmpv4(struct packet *packet, u8 *layer4_start, + int layer4_bytes, u8 *packet_end, char **error) +{ + struct header *icmp_header = NULL; + const int icmp_header_len = sizeof(struct icmpv4); + u8 *p = layer4_start; + + assert(layer4_bytes >= 0); + /* Make sure the immediately preceding header was IPv4. */ + if (packet_inner_header(packet)->type != HEADER_IPV4) { + asprintf(error, "Bad IP version for IPPROTO_ICMP"); + goto error_out; + } + + if (layer4_bytes < sizeof(struct icmpv4)) { + asprintf(error, "Truncated ICMPv4 header"); + goto error_out; + } + + packet->icmpv4 = (struct icmpv4 *) p; + + icmp_header = packet_append_header(packet, HEADER_ICMPV4, + icmp_header_len); + if (icmp_header == NULL) { + asprintf(error, "Too many nested headers at ICMPV4 header"); + goto error_out; + } + icmp_header->total_bytes = layer4_bytes; + + p += layer4_bytes; + assert(p <= packet_end); + + return PACKET_OK; + +error_out: + return PACKET_BAD; +} + +/* Parse the ICMPv6 header. Return a packet_parse_result_t. */ +static int parse_icmpv6(struct packet *packet, u8 *layer4_start, + int layer4_bytes, u8 *packet_end, char **error) +{ + struct header *icmp_header = NULL; + const int icmp_header_len = sizeof(struct icmpv6); + u8 *p = layer4_start; + + assert(layer4_bytes >= 0); + /* Make sure the immediately preceding header was IPv6. */ + if (packet_inner_header(packet)->type != HEADER_IPV6) { + asprintf(error, "Bad IP version for IPPROTO_ICMPV6"); + goto error_out; + } + if (layer4_bytes < sizeof(struct icmpv6)) { + asprintf(error, "Truncated ICMPv6 header"); + goto error_out; + } + + packet->icmpv6 = (struct icmpv6 *) p; + + icmp_header = packet_append_header(packet, HEADER_ICMPV6, + icmp_header_len); + if (icmp_header == NULL) { + asprintf(error, "Too many nested headers at ICMPV6 header"); + goto error_out; + } + icmp_header->total_bytes = layer4_bytes; + + p += layer4_bytes; + assert(p <= packet_end); + + return PACKET_OK; + +error_out: + return PACKET_BAD; +} + /* Parse the GRE header. Return a packet_parse_result_t. */ static int parse_gre(struct packet *packet, u8 *layer4_start, int layer4_bytes, u8 *packet_end, char **error) @@ -545,6 +622,14 @@ static int parse_layer4(struct packet *packet, u8 *layer4_start, *is_inner = true; /* found inner-most layer 4 */ return parse_udp(packet, layer4_start, layer4_bytes, packet_end, error); + } else if (layer4_protocol == IPPROTO_ICMP) { + *is_inner = true; /* found inner-most layer 4 */ + return parse_icmpv4(packet, layer4_start, layer4_bytes, + packet_end, error); + } else if (layer4_protocol == IPPROTO_ICMPV6) { + *is_inner = true; /* found inner-most layer 4 */ + return parse_icmpv6(packet, layer4_start, layer4_bytes, + packet_end, error); } else if (layer4_protocol == IPPROTO_GRE) { *is_inner = false; return parse_gre(packet, layer4_start, layer4_bytes, packet_end, -- GitLab