static void checksum_ipv6_packet(struct packet *packet) { struct ipv6 *ipv6 = packet->ipv6; /* IPv6 has no header checksum. */ /* For now we do not support IPv6 extension headers. */ assert(packet->ip_bytes >= sizeof(*ipv6) + ntohs(ipv6->payload_len)); /* Find the length of layer 4 header, options, and payload. */ const int l4_bytes = ntohs(ipv6->payload_len); assert(l4_bytes > 0); /* Fill in IPv6-based layer 4 checksum. */ if (packet->sctp != NULL) { struct sctp_common_header *sctp = packet->sctp; sctp->crc32c = 0; sctp->crc32c = sctp_crc32c(sctp, l4_bytes); } else if (packet->tcp != NULL) { struct tcp *tcp = packet->tcp; tcp->check = 0; tcp->check = tcp_udp_v6_checksum(&ipv6->src_ip, &ipv6->dst_ip, IPPROTO_TCP, tcp, l4_bytes); } else if (packet->udp != NULL) { struct udp *udp = packet->udp; udp->check = 0; udp->check = tcp_udp_v6_checksum(&ipv6->src_ip, &ipv6->dst_ip, IPPROTO_UDP, udp, l4_bytes); } else if (packet->udplite != NULL) { struct udplite *udplite = packet->udplite; u16 coverage; coverage = ntohs(udplite->cov); if ((coverage == 0) || (coverage > l4_bytes)) coverage = l4_bytes; udplite->check = 0; udplite->check = udplite_v6_checksum(&ipv6->src_ip, &ipv6->dst_ip, IPPROTO_UDPLITE, udplite, l4_bytes, coverage); } else if (packet->icmpv6 != NULL) { /* IPv6 ICMP has a pseudo-header checksum, like TCP. */ struct icmpv6 *icmpv6 = packet->icmpv6; icmpv6->checksum = 0; icmpv6->checksum = tcp_udp_v6_checksum(&ipv6->src_ip, &ipv6->dst_ip, IPPROTO_ICMPV6, icmpv6, l4_bytes); } else { assert(!"not TCP or UDP or UDPLite or ICMP"); } }
static void checksum_ipv6_packet(struct packet *packet) { struct ipv6 *ipv6 = packet->ipv6; /* IPv6 has no header checksum. */ /* For now we do not support IPv6 extension headers. */ assert(packet->ip_bytes >= sizeof(*ipv6) + ntohs(ipv6->payload_len)); /* Find the length of layer 4 header, options, and payload. */ const int l4_bytes = ntohs(ipv6->payload_len); assert(l4_bytes > 0); /* Fill in IPv6-based layer 4 checksum. */ if (packet->tcp != NULL) { struct tcp *tcp = packet->tcp; tcp->check = 0; tcp->check = tcp_udp_v6_checksum(&ipv6->src_ip, &ipv6->dst_ip, IPPROTO_TCP, tcp, l4_bytes); } else if (packet->udp != NULL) { struct udp *udp = packet->udp; udp->check = 0; udp->check = tcp_udp_v6_checksum(&ipv6->src_ip, &ipv6->dst_ip, IPPROTO_UDP, udp, l4_bytes); } else if (packet->icmpv6 != NULL) { /* IPv6 ICMP has a pseudo-header checksum, like TCP. */ struct icmpv6 *icmpv6 = packet->icmpv6; icmpv6->checksum = 0; icmpv6->checksum = tcp_udp_v6_checksum(&ipv6->src_ip, &ipv6->dst_ip, IPPROTO_ICMPV6, icmpv6, l4_bytes); } else { assert(!"not TCP or ICMP"); } }