static int icmp_extract_err_infos(struct icmp_proto_info *info, uint8_t const *packet, size_t packet_len) { struct icmp_err *err = &info->err; if (packet_len < 20 + 8) { SLOG(LOG_DEBUG, "Bogus ICMP err : packet too short for IP header"); return -1; } struct ip_hdr const *iphdr = (struct ip_hdr const *)packet; size_t iphdr_len = iphdr->hdr_len * 4; if (iphdr_len > packet_len - 8) { SLOG(LOG_DEBUG, "Bogus ICMP packet IP header too long (%zu > %zu)", iphdr_len, packet_len = 8); return -1; } err->protocol = iphdr->protocol; ip_addr_ctor_from_ip4(err->addr+0, iphdr->src); ip_addr_ctor_from_ip4(err->addr+1, iphdr->dst); switch (iphdr->protocol) { case IPPROTO_TCP: case IPPROTO_UDP: info->set_values |= ICMP_ERR_PORT_SET; return icmp_extract_err_ports(err, packet + iphdr_len); default: SLOG(LOG_DEBUG, "ICMP Error for unsuported protocol %u", iphdr->protocol); return 0; } }
static int icmpv6_extract_err_infos(struct icmp_proto_info *info, uint8_t const *packet, size_t packet_len) { struct icmp_err *err = &info->err; struct ipv6_hdr const *iphdr = (struct ipv6_hdr *)packet; if (packet_len < sizeof(*iphdr)) { SLOG(LOG_DEBUG, "Bogus ICMPv6 packet too short for IPv6 header"); return -1; } err->protocol = READ_U8(&iphdr->next); ip_addr_ctor_from_ip6(err->addr+0, &iphdr->src); ip_addr_ctor_from_ip6(err->addr+1, &iphdr->dst); switch (iphdr->next) { case IPPROTO_TCP: case IPPROTO_UDP: if (packet_len >= sizeof(*iphdr) + 4) { info->set_values |= ICMP_ERR_PORT_SET; return icmp_extract_err_ports(err, packet + sizeof(*iphdr)); } break; default: SLOG(LOG_DEBUG, "ICMPv6 Error for unsuported protocol %u", iphdr->next); break; } return 0; }