Download raw body.
dhcp daemon checksum fix
On Tue, Feb 04, 2025 at 10:32:12PM GMT, Alexander Bluhm wrote:
> When sending traffic via vio(4) between guests living within a
> single KVM host, the packet checksum is never calculated. A flag
> is set to assume the checksum is correct. Our IP stack handles
> that correctly but when using bpf(4) userland has to care.
>
> jan@ has fixed it for dhcpleased a while ago.
>
> ----------------------------
> revision 1.42
> date: 2024/01/26 21:14:08; author: jan; state: Exp; lines: +17 -12; commitid: nvgEHwLOyfqqyGwh;
> Put checksum flags in bpf_hdr to use them in userland dhcpleased.
>
> Thus, dhcpleased accept non-calculated checksums which were verified by
> hardware/hypervisor.
>
> With tweaks from dlg@
>
> ok bluhm@
> mkay tobhe@
> ----------------------------
>
> But our other dhcp daemons suffer from the same problem. Below is
> the diff for dhcpd(8), dhcrelay(8), and dhcrelay6(8).
>
> While there, I discovered that checksum calculation is suboptimal.
> To verify, calculate the checksum of the received packet and it has
> to be 0. That is what RFC 1071 says and our kernel does.
>
> I did run dhcpleased on a KVM guest and markus@ tested dhcpd.
>
> If you run any of these daemons on KVM guest, please test.
>
> ok?
I tested and reviewd the dhcpleased part. Works and looks correct.
ok jan@
> Index: sbin/dhcpleased/engine.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sbin/dhcpleased/engine.c,v
> diff -u -p -r1.55 engine.c
> --- sbin/dhcpleased/engine.c 21 Nov 2024 13:35:20 -0000 1.55
> +++ sbin/dhcpleased/engine.c 16 Jan 2025 20:14:10 -0000
> @@ -744,7 +744,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 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;
> @@ -850,16 +850,14 @@ parse_dhcp(struct dhcpleased_iface *ifac
> p += sizeof(*udp);
> rem -= sizeof(*udp);
>
> - if ((dhcp->csumflags & M_UDP_CSUM_IN_OK) == 0) {
> - usum = udp->uh_sum;
> - udp->uh_sum = 0;
> -
> - sum = wrapsum(checksum((uint8_t *)udp, sizeof(*udp),
> + if ((dhcp->csumflags & M_UDP_CSUM_IN_OK) == 0 &&
> + udp->uh_sum != 0) {
> + udp->uh_sum = wrapsum(checksum((uint8_t *)udp, sizeof(*udp),
> checksum(p, rem,
> checksum((uint8_t *)&ip->ip_src, 2 * sizeof(ip->ip_src),
> IPPROTO_UDP + ntohs(udp->uh_ulen)))));
>
> - if (usum != 0 && usum != sum) {
> + if (udp->uh_sum != 0) {
> log_warnx("%s: bad UDP checksum", __func__);
> return;
> }
dhcp daemon checksum fix