Skip to content
Permalink
Browse files

net/udp: Accept UDP packet with missing checksum

Having a checksum of zeros in UDP means "missing checksum" and is a
valid case as per RFC 768:

"An all zero transmitted checksum value means that the transmitter
generated no checksum (for debugging or for higher level protocols
that don't care)."

Such support is made possible by adding a new Kconfig option named
CONFIG_NET_UDP_MISSING_CHECKSUM.

However, that is valid only for IPv4. For IPv6, see the RFC 2460
section 8.1:

"Unlike IPv4, when UDP packets are originated by an IPv6 node, the UDP
checksum is not optional."

So the UDP checksum will always be verified in IPv6.

Fixes #16375

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
  • Loading branch information...
tbursztyka authored and jukkar committed May 27, 2019
1 parent 7706258 commit 274db4f33de590926c8fa01d0b3acbae79f9eeea
Showing with 22 additions and 7 deletions.
  1. +9 −0 subsys/net/ip/Kconfig
  2. +13 −7 subsys/net/ip/udp.c
@@ -304,6 +304,15 @@ config NET_UDP_CHECKSUM
Enables UDP handler to check UDP checksum. If the checksum is invalid,
then the packet is discarded.

config NET_UDP_MISSING_CHECKSUM
bool "Accept missing checksum (IPv4 only)"
depends on NET_UDP && NET_IPV4
help
RFC 768 states the possibility to have a missing checksum, for
debugging purposes for instance. That feature is however valid only
for IPv4 and on reception only, since Zephyr will always compute the
UDP checksum in transmission path.

if NET_UDP
module = NET_UDP
module-dep = NET_LOG
@@ -148,19 +148,25 @@ struct net_udp_hdr *net_udp_input(struct net_pkt *pkt,
{
struct net_udp_hdr *udp_hdr;

if (IS_ENABLED(CONFIG_NET_UDP_CHECKSUM) &&
net_if_need_calc_rx_checksum(net_pkt_iface(pkt)) &&
net_calc_verify_chksum_udp(pkt) != 0U) {
NET_DBG("DROP: checksum mismatch");
goto drop;
}

udp_hdr = (struct net_udp_hdr *)net_pkt_get_data(pkt, udp_access);
if (!udp_hdr || net_pkt_set_data(pkt, udp_access)) {
NET_DBG("DROP: corrupted header");
goto drop;
}

if (IS_ENABLED(CONFIG_NET_UDP_CHECKSUM) &&
net_if_need_calc_rx_checksum(net_pkt_iface(pkt))) {
if (IS_ENABLED(CONFIG_NET_UDP_MISSING_CHECKSUM) &&
net_pkt_family(pkt) == AF_INET && !udp_hdr->chksum) {
goto out;
}

if (net_calc_verify_chksum_udp(pkt) != 0U) {
NET_DBG("DROP: checksum mismatch");
goto drop;
}
}
out:
return udp_hdr;
drop:
net_stats_update_udp_chkerr(net_pkt_iface(pkt));

0 comments on commit 274db4f

Please sign in to comment.
You can’t perform that action at this time.