net: conn: Check UDP and TCP checksum before accepting packet

We did not check UDP or TCP checksum to be valid after receiving
the packet. Fix this so that the checksum is validated when
packet is received in connection handler. As the checksum validation
can be resource intensive, do it after we have verified that
there is a connection handler for this connection.

The checksum calculation can be turned OFF if needed, but it is
ON by default.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2017-05-17 10:43:18 +03:00
commit 69b25c0788
4 changed files with 63 additions and 8 deletions

View file

@ -94,6 +94,14 @@ config NET_TCP
help help
The value depends on your network needs. The value depends on your network needs.
config NET_TCP_CHECKSUM
bool "Check TCP checksum"
default y
depends on NET_TCP
help
Enables TCP handler to check TCP checksum. If the checksum is invalid,
then the packet is discarded.
config NET_DEBUG_TCP config NET_DEBUG_TCP
bool "Debug TCP" bool "Debug TCP"
default n default n
@ -127,6 +135,14 @@ config NET_UDP
help help
The value depends on your network needs. The value depends on your network needs.
config NET_UDP_CHECKSUM
bool "Check UDP checksum"
default y
depends on NET_UDP
help
Enables UDP handler to check UDP checksum. If the checksum is invalid,
then the packet is discarded.
config NET_DEBUG_UDP config NET_DEBUG_UDP
bool "Debug UDP" bool "Debug UDP"
default n default n

View file

@ -740,6 +740,7 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
{ {
int i, best_match = -1; int i, best_match = -1;
s16_t best_rank = -1; s16_t best_rank = -1;
u16_t chksum;
#if defined(CONFIG_NET_CONN_CACHE) #if defined(CONFIG_NET_CONN_CACHE)
enum net_verdict verdict; enum net_verdict verdict;
@ -752,15 +753,13 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
} }
#endif #endif
if (proto == IPPROTO_TCP) {
chksum = NET_TCP_HDR(pkt)->chksum;
} else {
chksum = NET_UDP_HDR(pkt)->chksum;
}
if (IS_ENABLED(CONFIG_NET_DEBUG_CONN)) { if (IS_ENABLED(CONFIG_NET_DEBUG_CONN)) {
u16_t chksum;
if (proto == IPPROTO_TCP) {
chksum = NET_TCP_HDR(pkt)->chksum;
} else {
chksum = NET_UDP_HDR(pkt)->chksum;
}
NET_DBG("Check %s listener for pkt %p src port %u dst port %u " NET_DBG("Check %s listener for pkt %p src port %u dst port %u "
"family %d chksum 0x%04x", net_proto2str(proto), pkt, "family %d chksum 0x%04x", net_proto2str(proto), pkt,
ntohs(NET_CONN_HDR(pkt)->src_port), ntohs(NET_CONN_HDR(pkt)->src_port),
@ -819,6 +818,40 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
} }
if (best_match >= 0) { if (best_match >= 0) {
/* If packet has a listener configured, then check also the
* protocol checksum if that checking is enabled.
* If the checksum calculation fails, then discard the message.
*/
if (IS_ENABLED(CONFIG_NET_UDP_CHECKSUM) &&
proto == IPPROTO_UDP) {
u16_t chksum_calc;
NET_UDP_HDR(pkt)->chksum = 0;
chksum_calc = ~net_calc_chksum_udp(pkt);
if (chksum != chksum_calc) {
net_stats_update_udp_chkerr();
goto drop;
}
NET_UDP_HDR(pkt)->chksum = chksum;
} else if (IS_ENABLED(CONFIG_NET_TCP_CHECKSUM) &&
proto == IPPROTO_TCP) {
u16_t chksum_calc;
NET_TCP_HDR(pkt)->chksum = 0;
chksum_calc = ~net_calc_chksum_tcp(pkt);
if (chksum != chksum_calc) {
net_stats_update_tcp_seg_chkerr();
goto drop;
}
NET_TCP_HDR(pkt)->chksum = chksum;
}
#if defined(CONFIG_NET_CONN_CACHE) #if defined(CONFIG_NET_CONN_CACHE)
NET_DBG("[%d] match found cb %p ud %p rank 0x%02x cache 0x%x", NET_DBG("[%d] match found cb %p ud %p rank 0x%02x cache 0x%x",
best_match, best_match,

View file

@ -21,3 +21,6 @@ CONFIG_NET_IPV6=n
CONFIG_NET_MGMT=y CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y CONFIG_NET_MGMT_EVENT=y
# Turn off UDP checksum checking as the test fails otherwise.
CONFIG_NET_UDP_CHECKSUM=n

View file

@ -21,3 +21,6 @@ CONFIG_NET_DEBUG_CORE=y
CONFIG_NET_DEBUG_CONN=y CONFIG_NET_DEBUG_CONN=y
#CONFIG_NET_DEBUG_NET_PKT=y #CONFIG_NET_DEBUG_NET_PKT=y
#CONFIG_NET_DEBUG_IF=y #CONFIG_NET_DEBUG_IF=y
# Turn off UDP checksum checking as the test fails otherwise.
CONFIG_NET_UDP_CHECKSUM=n