Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UDP checksum algorithm is buggy (or at least badly documented) #585

Open
heikki-heikkila opened this issue Sep 27, 2022 · 0 comments
Open

Comments

@heikki-heikkila
Copy link

File pnet_packet/src/udp.rs contains routines ipv4_chekcsum() and ipv4_checksum_adv(), which are supposed to calculate the correct UDP checksum to the UDP header. Also, there is a unit test function "udp_header_ipv4_test()", which is apparently meant to show the correct use of function ipv4_checksum().

However, if a user calculates UDP checksums as shown in udp_header_ipv4_test(), the result is wrong, with probability of 0.000015. Specifically, routine util::ipv4_checksum() calculates the mathematically correct TCP checksum, which is in range 0..0xFFFE, inclusive. However, RFC768 says that UDP checksum has a special rule that differs from all other checksum calculations: if "the computed checksum is zero, it is transmitted as all ones", so a zero value (whose probability is 1/65535), must be changed to 0xFFFF before storing to UDP header. The algorithm, as shown, fails to do this change.

The result of this bug is hard to reveal, because if the sender sets the checksum to zero (as mentioned, this happens with probability 1/65535), the receiver is unlikely to notice the error, because, for the receiver, zero checksum is an indication that the sender has refused to calculate the checksum, and so the receiver omits the checksum calculation and accepts the UDP packet. So the net result is that transmissions errors, which are meant to be detected with checksum, are not detected.

Also, a similar bug is in documentation of routine pnet::util::ipv4_checksum. That routine is meant for "UDP and TCP", but the user is not warned against the special case of zero checksum.

A fix should be simple:

let mut checksum = ipv4_checksum(. . .);
if checksum == 0 {
    // UDP rules require that zero is represented as follows:
    checksum = 0xFFFF;
}
udp_header.set_checksum(checksum);

And further, the routines for IPv6 appear to have the same issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant