net/ipv4: Handle options relevantly
IPv4 header might come with options, unlike IPv6, these are not
encapsulated in option header but are fully part of the IPv4 header.
Zephyr must handles these. Now silently ignoring their content and
setting the cursor to the payload properly.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
diff --git a/subsys/net/ip/ipv4.c b/subsys/net/ip/ipv4.c
index ba4f485..c3975be 100644
--- a/subsys/net/ip/ipv4.c
+++ b/subsys/net/ip/ipv4.c
@@ -164,6 +164,7 @@
union net_proto_header proto_hdr;
struct net_ipv4_hdr *hdr;
union net_ip_header ip;
+ u8_t hdr_len;
int pkt_len;
net_stats_update_ipv4_recv(net_pkt_iface(pkt));
@@ -174,6 +175,14 @@
goto drop;
}
+ hdr_len = (hdr->vhl & NET_IPV4_IHL_MASK) * 4;
+ if (hdr_len < sizeof(struct net_ipv4_hdr)) {
+ NET_DBG("DROP: Invalid hdr length");
+ goto drop;
+ }
+
+ net_pkt_set_ip_hdr_len(pkt, hdr_len);
+
pkt_len = ntohs(hdr->len);
if (real_len < pkt_len) {
NET_DBG("DROP: pkt len per hdr %d != pkt real len %d",
@@ -210,16 +219,23 @@
goto drop;
}
- NET_DBG("IPv4 packet received from %s to %s",
- log_strdup(net_sprint_ipv4_addr(&hdr->src)),
- log_strdup(net_sprint_ipv4_addr(&hdr->dst)));
+ net_pkt_acknowledge_data(pkt, &ipv4_access);
- net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));
+ if (hdr_len > sizeof(struct net_ipv4_hdr)) {
+ /* There are probably options, let's skip them */
+ if (net_pkt_skip(pkt, hdr_len - sizeof(struct net_ipv4_hdr))) {
+ NET_DBG("Header too big? %u", hdr_len);
+ goto drop;
+ }
+ }
+
net_pkt_set_ipv4_ttl(pkt, hdr->ttl);
net_pkt_set_family(pkt, PF_INET);
- net_pkt_acknowledge_data(pkt, &ipv4_access);
+ NET_DBG("IPv4 packet received from %s to %s",
+ log_strdup(net_sprint_ipv4_addr(&hdr->src)),
+ log_strdup(net_sprint_ipv4_addr(&hdr->dst)));
switch (hdr->proto) {
case IPPROTO_ICMP:
diff --git a/subsys/net/ip/ipv4.h b/subsys/net/ip/ipv4.h
index 3f1f7d6..8ef8dff 100644
--- a/subsys/net/ip/ipv4.h
+++ b/subsys/net/ip/ipv4.h
@@ -22,6 +22,8 @@
#include "ipv4.h"
+#define NET_IPV4_IHL_MASK 0x0F
+
/**
* @brief Create IPv4 packet in provided net_pkt.
*