/* Parse the IPv6 header and the TCP header inside. We do not * currently support parsing IPv6 extension headers or any layer 4 * protocol other than TCP. Return a packet_parse_result_t. * Note that packet_end points to the byte beyond the end of packet. */ static int parse_ipv6(struct packet *packet, u8 *header_start, u8 *packet_end, char **error) { u8 *p = header_start; packet->ipv6 = (struct ipv6 *) (p); /* Check that header fits in sniffed packet. */ const int ip_header_bytes = packet_ip_header_len(packet); assert(ip_header_bytes >= 0); assert(ip_header_bytes == sizeof(*packet->ipv6)); if (p + ip_header_bytes > packet_end) { asprintf(error, "IPv6 header overflows packet"); goto error_out; } /* Check that payload fits in sniffed packet. */ const int ip_total_bytes = (ip_header_bytes + ntohs(packet->ipv6->payload_len)); packet->ip_bytes = ip_total_bytes; if (p + ip_total_bytes > packet_end) { asprintf(error, "IPv6 payload overflows packet"); goto error_out; } assert(ip_header_bytes <= ip_total_bytes); /* Move on to the header inside. */ p += ip_header_bytes; assert(p <= packet_end); if (DEBUG_LOGGING) { char src_string[ADDR_STR_LEN]; char dst_string[ADDR_STR_LEN]; struct ip_address src_ip, dst_ip; ip_from_ipv6(&packet->ipv6->src_ip, &src_ip); ip_from_ipv6(&packet->ipv6->dst_ip, &dst_ip); DEBUGP("src IP: %s\n", ip_to_string(&src_ip, src_string)); DEBUGP("dst IP: %s\n", ip_to_string(&dst_ip, dst_string)); } /* Examine the L4 header. */ const int layer4_bytes = ip_total_bytes - ip_header_bytes; const int layer4_protocol = packet->ipv6->next_header; return parse_layer4(packet, p, layer4_protocol, layer4_bytes, packet_end, error); error_out: return PACKET_BAD; }
/* Parse the IPv6 header and the TCP header inside. We do not * currently support parsing IPv6 extension headers or any layer 4 * protocol other than TCP. Return a packet_parse_result_t. * Note that packet_end points to the byte beyond the end of packet. */ static int parse_ipv6(struct packet *packet, u8 *header_start, u8 *packet_end, char **error) { struct header *ip_header = NULL; u8 *p = header_start; const bool is_outer = (packet->ip_bytes == 0); bool is_inner = false; struct ipv6 *ipv6 = (struct ipv6 *) (p); enum packet_parse_result_t result = PACKET_BAD; /* Check that header fits in sniffed packet. */ const int ip_header_bytes = sizeof(*ipv6); if (p + ip_header_bytes > packet_end) { asprintf(error, "IPv6 header overflows packet"); goto error_out; } /* Check that payload fits in sniffed packet. */ const int ip_total_bytes = (ip_header_bytes + ntohs(ipv6->payload_len)); if (p + ip_total_bytes > packet_end) { asprintf(error, "IPv6 payload overflows packet"); goto error_out; } assert(ip_header_bytes <= ip_total_bytes); ip_header = packet_append_header(packet, HEADER_IPV6, ip_header_bytes); if (ip_header == NULL) { asprintf(error, "Too many nested headers at IPv6 header"); goto error_out; } ip_header->total_bytes = ip_total_bytes; /* Move on to the header inside. */ p += ip_header_bytes; assert(p <= packet_end); if (DEBUG_LOGGING) { char src_string[ADDR_STR_LEN]; char dst_string[ADDR_STR_LEN]; struct ip_address src_ip, dst_ip; ip_from_ipv6(&ipv6->src_ip, &src_ip); ip_from_ipv6(&ipv6->dst_ip, &dst_ip); DEBUGP("src IP: %s\n", ip_to_string(&src_ip, src_string)); DEBUGP("dst IP: %s\n", ip_to_string(&dst_ip, dst_string)); } /* Examine the L4 header. */ const int layer4_bytes = ip_total_bytes - ip_header_bytes; const int layer4_protocol = ipv6->next_header; result = parse_layer4(packet, p, layer4_protocol, layer4_bytes, packet_end, &is_inner, error); /* If this is the innermost IP header then this is the primary. */ if (is_inner) packet->ipv6 = ipv6; /* If this is the outermost IP header then this is the packet length. */ if (is_outer) packet->ip_bytes = ip_total_bytes; return result; error_out: return PACKET_BAD; }