How to enable UDP checksums

I'm no expert, but the only thing that man 7 udp has to say on the matter suggests that it's enabled by default:

UDP generates and checks checksums to catch transmission errors.

It does not mention any way to disable it.

Edit: I'm too lazy to look up current kernel source, but this page suggests that packets with invalid checksums are simply dropped (the csum_copy_err part).


(I am not an expert. The following may be completely wrong.)

The network interface (or driver or something equivalent) should be checking the checksums of incoming packets. A checksum of all-bits-zero means "The outgoing interface didn't generate a checksum." The interface MUST check any other checksum (including all-bits-one, a.k.a. "negative zero" in the ones' complement encoding used by the checksum field) and MUST drop the packet if it fails the check.

Therefore, you are never allowed to disable UDP checksum checking on incoming packets (if those packets have checksums provided, that is). That's just a mandatory part of the UDP standard.

The receiving interface MAY drop packets with no checksum,[1] or MAY pass them on to the application (or MAY let the application configure its desired behavior, although if this is possible, I don't know how to do it).

The only thing you might possibly be able to control is whether the sending interface generates checksums on outgoing packets. It'll be platform-specific. I've collected some ways below, which might or might not work; caveat lector.

If you just take your platform's default behavior, you will get UDP checksum generation by default — I'd put money on it.

[1] — RFC 8085: "An application is permitted to optionally discard UDP datagrams with a zero checksum [RFC1122]."


This comp.protocols.tcp-ip post from 1999 suggests that on Solaris, you can globally disable the generation of UDP checksums on outgoing packets via ndd at the command line:

ndd -set /dev/udp udp_do_checksum 0

The ndd utility is specific to the Solaris kernel, and does not exist on Linux or FreeBSD. Also, even the Solaris docs say:

udp_do_checksum
  This parameter controls whether UDP calculates the checksum
  on outgoing UDP/IPv4 packets.

Default
  1 (enabled)

When to Change
  Do not change this parameter.

(On Linux and FreeBSD, /dev/udp "doesn't really exist"; it's a fiction provided by Bash. I don't know whether /dev/udp "really exists" on Solaris.)


Microsoft's docs imply that on Windows, you can disable UDP checksum generation programmatically on a per-socket basis, using a documented option:

DWORD trueValue = 1;
int rc = setsockopt(fd, IPPROTO_UDP, UDP_NOCHECKSUM, (const char*)&yes, sizeof yes);
if (rc != 0) { perror("setsockopt"); abort(); }

This thread implies that on FreeBSD (e.g. Mac OS X) you can disable checksum generation programmatically on a per-socket basis, using an otherwise undocumented (but present as of January 2018) option:

int yes = 1;
int rc = setsockopt(sock, IPPROTO_UDP, UDP_NOCKSUM, (void*)&yes, sizeof yes);
if (rc != 0) { perror("setsockopt"); abort(); }

And finally, this thread implies that on Linux you can disable checksum generation programmatically on a per-socket basis, using an otherwise undocumented (but present as of January 2018) option:

int yes = 1;
int rc = setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, (void*)&yes, sizeof yes);
if (rc != 0) { perror("setsockopt"); abort(); }