*** From dhcp-server -- To unsubscribe, see the end of this message. ***
Looks ok...
"sum -= 0xffff" <==>
"sum += -0xffff" <==>
"sum += 0xffff0001"
Since "0x10000 <= sum <= 0x1fffe" before this addition, afterwards we
will have: "0x0001 <= sum <= 0xffff". The net effect is still to
mask the upper half of the 32-bit sum and to add one for every carry
from the upper half of the 16-bit checksum.
You might want to start the sum at negative zero instead of 0. It
should be impossible for wrapsum() to return 0xffff unless all the
data is zero, but one should never underestimate how clever the
(mis)user can be. :/
Since the checksum is being computed for UDP, it might be a good idea
to change positive zero/no checksum into negative zero. (Outside of
wrapsum(), of course.)
As for complexity, the UDP pseudo-header stuff might be clearer if one
dumped the relevant data into a single memory buffer and then computed
the checksum on that (instead of the nested "checksum()" calls).
All other things being equal, I tend to prefer things to be as similar
to the underlying specification as possible. As such, I would say
that the more similar the code is to the RFC's example code, the less
"complicated" it is. The BSD code (from FreeBSD's netinet/in_cksum.c)
is more along the lines of your original code (with separate
accumulation and "wrap"/REDUCE phases):
sum = (sum >> 16) + (sum & 0xffff); /* done with a union in the
BSD code */
if(sum > 65535) sum -= 65535;
Compared to the minimal fix of the existing common/packet.c code:
while (sum >= 0x10000) {
sum = (sum >> 16) + (sum & 0xFFFF);
}
______________________________ Reply Separator _________________________________
Subject: Re: 2.0b1pl26 Checksum Issues
Author: Ted Lemon <[EMAIL PROTECTED]> at smtplink-pen
Date: 4/23/99 10:43 AM
I've come up with my own change to the checksum code based on the BSD
checksum code. My reasoning is that the current code is a bit more
complicated than it needs to be. Can you try this patch out and let
me know if it also solves your problem?
Thanks!
_MelloN_
Index: packet.c
===================================================================
RCS file: /proj/src/isc/cvs-1/DHCP/common/packet.c,v
retrieving revision 1.24
diff -c -r1.24 packet.c
*** packet.c 1999/04/12 21:37:03 1.24
--- packet.c 1999/04/23 14:41:58
***************
*** 52,57 ****
--- 52,60 ----
log_debug ("sum = %x", sum);
#endif
sum += (u_int16_t) ntohs(*((u_int16_t *)(buf + i)));
+ /* Add carry. */
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
}
/* If there's a single byte left over, checksum it, too. Network
***************
*** 61,73 ****
log_debug ("sum = %x", sum);
#endif
sum += buf [i] << 8;
}
return sum;
}
! /* Fold the upper sixteen bits of the checksum down into the lower bits,
! complement the sum, and then put it into network byte order. */
u_int32_t wrapsum (sum)
u_int32_t sum;
--- 64,78 ----
log_debug ("sum = %x", sum);
#endif
sum += buf [i] << 8;
+ /* Add carry. */
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
}
return sum;
}
! /* Finish computing the checksum, and then put it into network byte order. */
u_int32_t wrapsum (sum)
u_int32_t sum;
***************
*** 76,93 ****
log_debug ("wrapsum (%x)", sum);
#endif
! while (sum > 0x10000) {
! sum = (sum >> 16) + (sum & 0xFFFF);
#ifdef DEBUG_CHECKSUM_VERBOSE
- log_debug ("sum = %x", sum);
- #endif
- sum += (sum >> 16);
- #ifdef DEBUG_CHECKSUM_VERBOSE
- log_debug ("sum = %x", sum);
- #endif
- }
- sum = sum ^ 0xFFFF;
- #ifdef DEBUG_CHECKSUM_VERBOSE
log_debug ("sum = %x", sum);
#endif
--- 81,88 ----
log_debug ("wrapsum (%x)", sum);
#endif
! sum = ~sum & 0xFFFF;
#ifdef DEBUG_CHECKSUM_VERBOSE
log_debug ("sum = %x", sum);
#endif
***************
*** 250,261 ****
return -1;
#endif /* USERLAND_FILTER */
- ++ip_packets_seen;
/* Check the IP header checksum - it should be zero. */
if (wrapsum (checksum (buf + bufix, ip_len, 0))) {
++ip_packets_bad_checksum;
if (ip_packets_seen > 4 &&
! (++ip_packets_seen / ++ip_packets_bad_checksum) < 2) {
log_info ("%d bad IP checksums seen in %d packets",
ip_packets_bad_checksum, ip_packets_seen);
ip_packets_seen = ip_packets_bad_checksum = 0;
--- 245,256 ----
return -1;
#endif /* USERLAND_FILTER */
/* Check the IP header checksum - it should be zero. */
+ ++ip_packets_seen;
if (wrapsum (checksum (buf + bufix, ip_len, 0))) {
++ip_packets_bad_checksum;
if (ip_packets_seen > 4 &&
! (ip_packets_seen / ip_packets_bad_checksum) < 2) {
log_info ("%d bad IP checksums seen in %d packets",
ip_packets_bad_checksum, ip_packets_seen);
ip_packets_seen = ip_packets_bad_checksum = 0;
***************
*** 279,285 ****
data = buf + bufix + ip_len + sizeof *udp;
len = ntohs (udp -> uh_ulen) - sizeof *udp;
++udp_packets_length_checked;
! if (len + data > buf + buflen) {
++udp_packets_length_overflow;
if (udp_packets_length_checked > 4 &&
(udp_packets_length_checked /
--- 274,280 ----
data = buf + bufix + ip_len + sizeof *udp;
len = ntohs (udp -> uh_ulen) - sizeof *udp;
++udp_packets_length_checked;
! if (len + data > buf + bufix + buflen) {
++udp_packets_length_overflow;
if (udp_packets_length_checked > 4 &&
(udp_packets_length_checked /
***************
*** 287,294 ****
log_info ("%d udp packets in %d too long - dropped",
udp_packets_length_overflow,
udp_packets_length_checked);
! udp_packets_length_overflow
! = udp_packets_length_checked = 0;
}
return -1;
}
--- 282,289 ----
log_info ("%d udp packets in %d too long - dropped",
udp_packets_length_overflow,
udp_packets_length_checked);
! udp_packets_length_overflow =
! udp_packets_length_checked = 0;
}
return -1;
}
***************
*** 310,319 ****
++udp_packets_seen;
if (usum && usum != sum) {
! ++udp_packets_bad_checksum;
if (udp_packets_seen > 4 &&
(udp_packets_seen / udp_packets_bad_checksum) < 2) {
! log_info ("%d bad udp checksums seen in %d packets",
udp_packets_bad_checksum, udp_packets_seen);
udp_packets_seen = udp_packets_bad_checksum = 0;
}
--- 305,314 ----
++udp_packets_seen;
if (usum && usum != sum) {
! udp_packets_bad_checksum++;
if (udp_packets_seen > 4 &&
(udp_packets_seen / udp_packets_bad_checksum) < 2) {
! log_info ("%d bad udp checksums in %d packets",
udp_packets_bad_checksum, udp_packets_seen);
udp_packets_seen = udp_packets_bad_checksum = 0;
}
------------------------------------------------------------------------------
To unsubscribe from this list, please visit http://www.fugue.com/dhcp/lists
If you are without web access, or if you are having trouble with the web page,
please send mail to [EMAIL PROTECTED] Please try to use the web
page first - it will take a long time for your request to be processed by hand.
Archives for this mailing list are available at
http://www.webnology.com/list-archives/dhcp/dhcp-server
------------------------------------------------------------------------------