From: Jan Klemkow Subject: dhcpleased(8): fix pseudo csum from vio(4) offloading To: tech@openbsd.org Date: Sun, 7 Jan 2024 13:38:23 +0100 Hi, we get packets with pseudo checksums from vio(4), since we use checksum offloading. Thus, programs which are dealing with raw packets like dhcpleased(8) also need to check for this kind of checksums or return errors. ok? bye, Jan Index: checksum.c =================================================================== RCS file: /cvs/src/sbin/dhcpleased/checksum.c,v diff -u -p -r1.1 checksum.c --- checksum.c 26 Feb 2021 16:16:37 -0000 1.1 +++ checksum.c 7 Jan 2024 12:17:23 -0000 @@ -78,3 +78,26 @@ wrapsum(uint32_t sum) sum = ~sum & 0xFFFF; return htons(sum); } + +/* + * Compute significant parts of the IPv4 checksum pseudo-header + * for use in a delayed TCP/UDP checksum calculation. + */ +uint16_t +checksum_phdr(uint32_t src, uint32_t dst, uint32_t lenproto) +{ + uint32_t sum; + + sum = lenproto + + (uint16_t)(src >> 16) + + (uint16_t)(src /*& 0xffff*/) + + (uint16_t)(dst >> 16) + + (uint16_t)(dst /*& 0xffff*/); + + sum = (uint16_t)(sum >> 16) + (uint16_t)(sum /*& 0xffff*/); + + if (sum > 0xffff) + sum -= 0xffff; + + return (sum); +} Index: checksum.h =================================================================== RCS file: /cvs/src/sbin/dhcpleased/checksum.h,v diff -u -p -r1.1 checksum.h --- checksum.h 26 Feb 2021 16:16:37 -0000 1.1 +++ checksum.h 7 Jan 2024 12:17:23 -0000 @@ -42,3 +42,4 @@ uint32_t checksum(uint8_t *, uint32_t, uint32_t); uint32_t wrapsum(uint32_t); +uint16_t checksum_phdr(uint32_t, uint32_t, uint32_t); Index: engine.c =================================================================== RCS file: /cvs/src/sbin/dhcpleased/engine.c,v diff -u -p -r1.41 engine.c --- engine.c 14 Dec 2023 09:58:37 -0000 1.41 +++ engine.c 7 Jan 2024 12:17:23 -0000 @@ -729,7 +729,7 @@ parse_dhcp(struct dhcpleased_iface *ifac struct in_addr nameservers[MAX_RDNS_COUNT]; struct dhcp_route routes[MAX_DHCP_ROUTES]; size_t rem, i; - uint32_t sum, usum, lease_time = 0, renewal_time = 0; + uint32_t sum, usum, psum, lease_time = 0, renewal_time = 0; uint32_t rebinding_time = 0; uint32_t ipv6_only_time = 0; uint8_t *p, dho = DHO_PAD, dho_len, slen; @@ -841,7 +841,10 @@ parse_dhcp(struct dhcpleased_iface *ifac checksum((uint8_t *)&ip->ip_src, 2 * sizeof(ip->ip_src), IPPROTO_UDP + ntohs(udp->uh_ulen))))); - if (usum != 0 && usum != sum) { + psum = checksum_phdr(ip->ip_src.s_addr, ip->ip_dst.s_addr, + htonl(ntohs(ip->ip_len) - (ip->ip_hl << 2) + ip->ip_p)); + + if (usum != 0 && usum != sum && usum != psum) { log_warnx("%s: bad UDP checksum", __func__); return; }