static void checksum_ipv4_packet(struct packet *packet) { struct ipv4 *ipv4 = packet->ipv4; /* Fill in IPv4 header checksum. */ ipv4->check = 0; ipv4->check = ipv4_checksum(ipv4, ipv4_header_len(ipv4)); assert(packet->ip_bytes >= ntohs(ipv4->tot_len)); /* Find the length of layer 4 header, options, and payload. */ const int l4_bytes = ntohs(ipv4->tot_len) - ipv4_header_len(ipv4); assert(l4_bytes > 0); /* Fill in IPv4-based layer 4 checksum. */ if (packet->tcp != NULL) { struct tcp *tcp = packet->tcp; tcp->check = 0; tcp->check = tcp_udp_v4_checksum(ipv4->src_ip, ipv4->dst_ip, IPPROTO_TCP, tcp, l4_bytes); } else if (packet->udp != NULL) { struct udp *udp = packet->udp; udp->check = 0; udp->check = tcp_udp_v4_checksum(ipv4->src_ip, ipv4->dst_ip, IPPROTO_UDP, udp, l4_bytes); } else if (packet->icmpv4 != NULL) { struct icmpv4 *icmpv4 = packet->icmpv4; icmpv4->checksum = 0; icmpv4->checksum = ipv4_checksum(icmpv4, l4_bytes); } else { assert(!"not TCP or ICMP"); } }
static void checksum_ipv4_packet(struct packet *packet) { struct ipv4 *ipv4 = packet->ipv4; /* Fill in IPv4 header checksum. */ ipv4->check = 0; ipv4->check = ipv4_checksum(ipv4, ipv4_header_len(ipv4)); assert(packet->ip_bytes >= ntohs(ipv4->tot_len)); /* Find the length of layer 4 header, options, and payload. */ const int l4_bytes = ntohs(ipv4->tot_len) - ipv4_header_len(ipv4); assert(l4_bytes > 0); /* Fill in IPv4-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_v4_checksum(ipv4->src_ip, ipv4->dst_ip, IPPROTO_TCP, tcp, l4_bytes); } else if (packet->udp != NULL) { struct udp *udp = packet->udp; udp->check = 0; udp->check = tcp_udp_v4_checksum(ipv4->src_ip, ipv4->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_v4_checksum(ipv4->src_ip, ipv4->dst_ip, IPPROTO_UDPLITE, udplite, l4_bytes, coverage); } else if (packet->icmpv4 != NULL) { struct icmpv4 *icmpv4 = packet->icmpv4; icmpv4->checksum = 0; icmpv4->checksum = ipv4_checksum(icmpv4, l4_bytes); } else { assert(!"not SCTP or TCP or UDP or UDPLite or ICMP"); } }
0xa0, 0x12, 0x16, 0xa0, 0x54, 0x12, 0x00, 0x00, 0x02, 0x04, 0x05, 0xb4, 0x04, 0x02, 0x08, 0x0a, 0x00, 0x00, 0x02, 0xbc, 0x00, 0x06, 0x0a, 0xd8, 0x01, 0x03, 0x03, 0x07, }; struct in_addr src_ip, dst_ip; struct tcp *tcp = (struct tcp *) (data + sizeof(struct ipv4)); int len = sizeof(data) - sizeof(struct ipv4); u16 checksum = 0; assert(inet_pton(AF_INET, "1.1.1.1", &src_ip) == 1); assert(inet_pton(AF_INET, "192.168.0.1", &dst_ip) == 1); checksum = ntohs(tcp_udp_v4_checksum(src_ip, dst_ip, IPPROTO_TCP, tcp, len)); assert(checksum == 0); tcp->check = 0; checksum = ntohs(tcp_udp_v4_checksum(src_ip, dst_ip, IPPROTO_TCP, tcp, len)); assert(checksum == 0x5412); } static void test_tcp_udp_v6_checksum(void) { u8 data[] __aligned(4) = { 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0xff, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x3d, 0xfa, 0x7b, 0xd1, 0x7d, 0x00, 0x00,