diff --git a/net/devif/ipv4_input.c b/net/devif/ipv4_input.c index 5ea71232e6b..7fbf8d003be 100644 --- a/net/devif/ipv4_input.c +++ b/net/devif/ipv4_input.c @@ -94,6 +94,7 @@ #include #include #include +#include #include "arp/arp.h" #include "inet/inet.h" @@ -118,6 +119,53 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: ipv4_check_opt + * + * Description: + * Check the IP options length. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +static int ipv4_check_opt(FAR struct ipv4_hdr_s *ipv4) +{ + FAR uint8_t *opt = (FAR uint8_t *)(ipv4 + 1); + int optlen; + + optlen = ((ipv4->vhl & IPv4_HLMASK) << 2) - IPv4_HDRLEN; + while (optlen > 0) + { + if (opt[0] == IPOPT_END_TYPE) + { + break; + } + else if (opt[0] == IPOPT_NOOP_TYPE) + { + opt++; + optlen--; + } + else if (optlen > 1) + { + int len = opt[1]; + if (len > optlen) + { + return -EINVAL; + } + + opt += len; + optlen -= len; + } + else + { + return -EINVAL; + } + } + + return OK; +} +#endif + /**************************************************************************** * Name: ipv4_in * @@ -189,7 +237,7 @@ static int ipv4_in(FAR struct net_driver_s *dev) dev->d_len -= NET_LL_HDRLEN(dev); - if (IPv4_HDRLEN > dev->d_len) + if (((ipv4->vhl & IPv4_HLMASK) << 2) > dev->d_len) { nwarn("WARNING: Packet shorter than IPv4 header\n"); goto drop; @@ -242,6 +290,17 @@ static int ipv4_in(FAR struct net_driver_s *dev) goto drop; } +#ifdef CONFIG_DEBUG_FEATURES + if (ipv4_check_opt(ipv4) != OK) + { +#ifdef CONFIG_NET_STATISTICS + g_netstats.ipv4.drop++; +#endif + nwarn("WARNING: IP options error\n"); + goto drop; + } +#endif + #ifdef CONFIG_NET_NAT44 /* Try NAT inbound, rule matching will be performed in NAT module. */