Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157845973
D52394.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D52394.diff
View Options
diff --git a/sbin/dhclient/packet.c b/sbin/dhclient/packet.c
--- a/sbin/dhclient/packet.c
+++ b/sbin/dhclient/packet.c
@@ -135,11 +135,14 @@
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 @@
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 @@
}
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));
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, May 26, 7:33 PM (8 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33536402
Default Alt Text
D52394.diff (2 KB)
Attached To
Mode
D52394: dhclient: improve UDP checksum handling
Attached
Detach File
Event Timeline
Log In to Comment