From nobody Sun Sep 14 20:26:53 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4cQ07d6Qmmz67QjD; Sun, 14 Sep 2025 20:26:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4cQ07d5HZJz40lV; Sun, 14 Sep 2025 20:26:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1757881613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=h8Y6HxurKy5xmnTmClzos2MOCzs6zQP1nLRzg8eJZ0M=; b=xjyF/ALUavKfqUsJ4UwSO6BulEVO42y+H4PZD5rac37YI5I68FwjFe0VuWLkrfbw5KmBoj 8CE7UvWx2U+40uyWAi0tmGwUpXaLQz/s60rRs+nExZNRooQesbFk7VtXOahivLCDOrwfan YNsE7mdw1acsUGaJghpQa39FZzd3Ii4Xc0qEf9CVH9B1PbXKq9JNSQBXJGWKYl7jFNSWYN dlQqxgxFpGMTN5pNT17emmEfpaRIjEV4aN1WvW5teAh2BiOXXHiM6IZFD9s96FtGwjacXT 4TFp9YRl7Xezh7HC9YcMUHEaESx8LKbjexMNKpVWXKHbqHwP96uRe1opZdxD4Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1757881613; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=h8Y6HxurKy5xmnTmClzos2MOCzs6zQP1nLRzg8eJZ0M=; b=MT1Fs+RG0Kdu2JB+x74cJH95Q5w9iNqAV1Xy1jO1H+v8U1GoDB1zlksnWbLeT8NA9eSEVw OUVxDGhRISiKe+6gALPUOxE3+vrxArqpRq8rELOA1ez1zHH6Y0etoqbjoRbWMof5dGksux RHy1iGN2S8sHqmhKy0+G/kG1qlyVZZOp0X8Xh0XvNjVR01hW1cC2BbKRKUA73oEiOwjXNa foG+KdQ0U8hZDdG3ae/U+4ZjHe+6CZMkBS4kEeh5LE2MKYDSQVoF8o59Y0f0x4Ic330jv5 fjFwRKkEO0Ca/oDT2bhMoxxK+cmZYK87rwSnyyBxEGAYXloqlYZ8fe9NyejM1Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1757881613; a=rsa-sha256; cv=none; b=ygj+9Qa3BNVv6Sgz9oGV9BFbALrhGvSpmXNVkYi+vlqNrec6YF6entoDA1HgFsNh+2f6BO Wj3YiCiQsJIZZlZ91+8t0bp6ngKsUPDJ6ufDhP9W/UXB1P+fU03W8LO8F73qOaqli5x7SD 1XeCz/lcJGq7EqEjgm8sVXs3KOp8to/Kb2erUB6yeOM4D7UUSALZCceNx4MXAEYzATSzYZ T3vK1tTneF8wDOKMjO+z5qVUaz5WaDU4BMSLBCjatdNmZVqgTsafcpl4nsQgYHY3fV+ruK BBHM+erg1DH5ud9mptaWMGkr3zKpvXMwcG9tfgzWqwV9WK9GM6c+MbgvNnMrEQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4cQ07d4kpPz8N1; Sun, 14 Sep 2025 20:26:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 58EKQrJ8085913; Sun, 14 Sep 2025 20:26:53 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 58EKQrIu085910; Sun, 14 Sep 2025 20:26:53 GMT (envelope-from git) Date: Sun, 14 Sep 2025 20:26:53 GMT Message-Id: <202509142026.58EKQrIu085910@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Michael Tuexen Subject: git: 1162a78e0d40 - stable/15 - dhclient: improve UDP checksum handling List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: tuexen X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 1162a78e0d403c4619dae3fed99ce9a923bc4795 Auto-Submitted: auto-generated The branch stable/15 has been updated by tuexen: URL: https://cgit.FreeBSD.org/src/commit/?id=1162a78e0d403c4619dae3fed99ce9a923bc4795 commit 1162a78e0d403c4619dae3fed99ce9a923bc4795 Author: Michael Tuexen AuthorDate: 2025-09-10 15:13:35 +0000 Commit: Michael Tuexen CommitDate: 2025-09-14 20:15:57 +0000 dhclient: improve UDP checksum handling When sending UDP packets: * compute the checksum in the correct order. This only has an impact if the length of the payload is odd. * don't send packet with a checksum of zero, use 0xffff instead as required. When receiving UDP packets: * don't do any computations when the checksum is zero. * compute the checksum in the correct order. This only has an impact if the length of the payload is odd. * when computing the checksum, store the pseudo header checksum * if the checksum is computed as zero, use 0xffff instead. * also accept packets, when the checksum in the packet is the pseudo header checksum. The last point fixes a problem when the DHCP client runs in a VM, the DHCP server runs on the host serving the VM and the network interface supports transmit checksum offloading. Since dhclient doesn't use UDP sockets but bpf devices to read the packets, the checksum will be incorrect and only contain the checksum of the pseudo header. PR: 263229 Reviewed by: markj, Timo Völker Tested by: danilo Differential Revision: https://reviews.freebsd.org/D52394 (cherry picked from commit 187ee62c71f2be62870f26ae98de865e330121be) --- sbin/dhclient/packet.c | 53 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/sbin/dhclient/packet.c b/sbin/dhclient/packet.c index 3d7390c06ee0..fc0305a8cb0c 100644 --- a/sbin/dhclient/packet.c +++ b/sbin/dhclient/packet.c @@ -135,11 +135,14 @@ assemble_udp_ip_header(unsigned char *buf, int *bufix, u_int32_t from, udp.uh_ulen = htons(sizeof(udp) + len); memset(&udp.uh_sum, 0, sizeof(udp.uh_sum)); - udp.uh_sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp), - checksum(data, len, checksum((unsigned char *)&ip.ip_src, + udp.uh_sum = wrapsum(checksum(data, len, checksum((unsigned char *)&udp, + sizeof(udp), checksum((unsigned char *)&ip.ip_src, 2 * sizeof(ip.ip_src), IPPROTO_UDP + (u_int32_t)ntohs(udp.uh_ulen))))); + if (udp.uh_sum == htons(0)) + udp.uh_sum = htons(0xffff); + memcpy(&buf[*bufix], &udp, sizeof(udp)); *bufix += sizeof(udp); } @@ -166,7 +169,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from, struct ip *ip; struct udphdr *udp; u_int32_t ip_len = (buf[bufix] & 0xf) << 2; - u_int32_t sum, usum; + u_int32_t sum, usum, pseudo_sum; static int ip_packets_seen; static int ip_packets_bad_checksum; static int udp_packets_seen; @@ -224,23 +227,37 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from, } usum = udp->uh_sum; - udp->uh_sum = 0; - - sum = wrapsum(checksum((unsigned char *)udp, sizeof(*udp), - checksum(data, len, checksum((unsigned char *)&ip->ip_src, - 2 * sizeof(ip->ip_src), - IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen))))); - udp_packets_seen++; - if (usum && usum != sum) { - udp_packets_bad_checksum++; - if (udp_packets_seen > 4 && udp_packets_bad_checksum != 0 && - (udp_packets_seen / udp_packets_bad_checksum) < 2) { - note("%d bad udp checksums in %d packets", - udp_packets_bad_checksum, udp_packets_seen); - udp_packets_seen = udp_packets_bad_checksum = 0; + + if (usum != htons(0)) { + udp->uh_sum = 0; + + pseudo_sum = checksum((unsigned char *)&ip->ip_src, + 2 * sizeof(ip->ip_src), + IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen)); + sum = wrapsum(checksum(data, len, + checksum((unsigned char *)udp, sizeof(*udp), pseudo_sum))); + if (sum == htons(0)) + sum = htons(0xffff); + + /* + * In addition to accepting UDP packets with the correct + * checksum in the checksum field, accept also the ones which + * have the correct pseudo header checksum in the checksum + * field. This allows to process UDP packets, which have been + * marked for transmit checksum offloading by the sender side. + */ + if (usum != sum && usum != htons(pseudo_sum & 0x0000ffff)) { + udp_packets_bad_checksum++; + if (udp_packets_seen > 4 && + udp_packets_bad_checksum != 0 && + (udp_packets_seen / udp_packets_bad_checksum) < 2) { + note("%d bad udp checksums in %d packets", + udp_packets_bad_checksum, udp_packets_seen); + udp_packets_seen = udp_packets_bad_checksum = 0; + } + return (-1); } - return (-1); } memcpy(&from->sin_port, &udp->uh_sport, sizeof(udp->uh_sport));