You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2026/08/01 20:40:15 UTC
(nuttx) branch master updated (db6ab892a24 -> 9aa6eb56715)
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
from db6ab892a24 fs/binfmt: close symlink TOCTOU and harden setuid/setgid exec hygiene
new 682ce1db2f3 net/ipv4: Forward fragments before local reassembly
new 0ed3a386382 net/nat: Reassemble IPv6 fragments before NAT66
new 9aa6eb56715 net/ipfilter: Reassemble IPv6 fragments before filtering
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
net/devif/ipv4_input.c | 69 ++++++++++++++++++++++++++++++++++----------
net/devif/ipv6_input.c | 53 +++++++++++++++++++++++++---------
net/ipforward/ipv4_forward.c | 5 ++++
net/ipfrag/ipv4_frag.c | 16 ++++++++--
net/nat/ipv6_nat.c | 2 +-
5 files changed, 112 insertions(+), 33 deletions(-)
(nuttx) 03/03: net/ipfilter: Reassemble IPv6 fragments before filtering
Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 9aa6eb56715bcd41311b3386f4b5124f5657b92a
Author: shichunma <ma...@gmail.com>
AuthorDate: Sat Aug 1 22:09:51 2026 +0800
net/ipfilter: Reassemble IPv6 fragments before filtering
IPv6 input currently lets fragmented packets continue into the IP filter path before reassembly. Forwarded IP filter rules can inspect L4 fields, but non-first IPv6 fragments do not carry the transport header.
Consume IPv6 fragments through the existing reassembly/drop helper before NAT66 or IP filter processing. This keeps plain IPv6 forwarding unchanged when neither L4-dependent feature is enabled, while avoiding filtering incomplete fragments.
Signed-off-by: shichunma <sh...@bestechnic.com>
---
net/devif/ipv6_input.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/devif/ipv6_input.c b/net/devif/ipv6_input.c
index 7236d320a10..3400fdebd79 100644
--- a/net/devif/ipv6_input.c
+++ b/net/devif/ipv6_input.c
@@ -151,7 +151,7 @@ static bool check_destipaddr(FAR struct net_driver_s *dev,
return false;
}
-#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66)
+#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66) || defined(CONFIG_NET_IPFILTER)
/****************************************************************************
* Name: ipv6_fragin_or_drop
*
@@ -225,7 +225,7 @@ static int ipv6_in(FAR struct net_driver_s *dev)
#ifdef CONFIG_NET_IPFORWARD
int ret;
#endif
-#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66)
+#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66) || defined(CONFIG_NET_IPFILTER)
bool isfrag = false;
#endif
@@ -317,7 +317,7 @@ static int ipv6_in(FAR struct net_driver_s *dev)
if (nxthdr == NEXT_FRAGMENT_EH)
{
extlen = EXTHDR_FRAG_LEN;
-#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66)
+#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66) || defined(CONFIG_NET_IPFILTER)
isfrag = true;
#endif
}
@@ -331,12 +331,14 @@ static int ipv6_in(FAR struct net_driver_s *dev)
nxthdr = exthdr->nxthdr;
}
-#ifdef CONFIG_NET_NAT66
+#if defined(CONFIG_NET_NAT66) || defined(CONFIG_NET_IPFILTER)
if (isfrag)
{
return ipv6_fragin_or_drop(dev);
}
+#endif
+#ifdef CONFIG_NET_NAT66
/* Try NAT inbound, rule matching will be performed in NAT module. */
ipv6_nat_inbound(dev, ipv6);
(nuttx) 02/03: net/nat: Reassemble IPv6 fragments before NAT66
Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 0ed3a386382f8367508b036b161485a912a442e6
Author: shichunma <ma...@gmail.com>
AuthorDate: Sat Aug 1 21:54:32 2026 +0800
net/nat: Reassemble IPv6 fragments before NAT66
NAT66 needs transport headers to create or match address and port mappings. Consume IPv6 fragments through local reassembly before NAT66 processing so forwarded fragmented traffic is not translated fragment-by-fragment without L4 context.
Also dispatch inbound NAT66 using the parsed IPv6 next-header value, matching the outbound path and allowing packets with extension headers before the transport header to be translated.
Signed-off-by: shichunma <sh...@bestechnic.com>
---
net/devif/ipv6_input.c | 51 +++++++++++++++++++++++++++++++++++++-------------
net/nat/ipv6_nat.c | 2 +-
2 files changed, 39 insertions(+), 14 deletions(-)
diff --git a/net/devif/ipv6_input.c b/net/devif/ipv6_input.c
index dc1c04360de..7236d320a10 100644
--- a/net/devif/ipv6_input.c
+++ b/net/devif/ipv6_input.c
@@ -151,6 +151,36 @@ static bool check_destipaddr(FAR struct net_driver_s *dev,
return false;
}
+#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66)
+/****************************************************************************
+ * Name: ipv6_fragin_or_drop
+ *
+ * Description:
+ * Reassemble an incoming IPv6 fragment for NAT or local processing or drop
+ * it if fragment reassembly is not available.
+ *
+ ****************************************************************************/
+
+static int ipv6_fragin_or_drop(FAR struct net_driver_s *dev)
+{
+#ifdef CONFIG_NET_IPFRAG
+ if (ipv6_fragin(dev) == OK)
+ {
+ return OK;
+ }
+#endif
+
+#ifdef CONFIG_NET_STATISTICS
+ g_netstats.ipv6.drop++;
+ g_netstats.ipv6.fragerr++;
+#endif
+ nwarn("WARNING: IPv6 fragment dropped\n");
+
+ dev->d_len = 0;
+ return OK;
+}
+#endif
+
/****************************************************************************
* Name: ipv6_in
*
@@ -195,7 +225,7 @@ static int ipv6_in(FAR struct net_driver_s *dev)
#ifdef CONFIG_NET_IPFORWARD
int ret;
#endif
-#ifdef CONFIG_NET_IPFRAG
+#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66)
bool isfrag = false;
#endif
@@ -287,7 +317,7 @@ static int ipv6_in(FAR struct net_driver_s *dev)
if (nxthdr == NEXT_FRAGMENT_EH)
{
extlen = EXTHDR_FRAG_LEN;
-#ifdef CONFIG_NET_IPFRAG
+#if defined(CONFIG_NET_IPFRAG) || defined(CONFIG_NET_NAT66)
isfrag = true;
#endif
}
@@ -302,6 +332,11 @@ static int ipv6_in(FAR struct net_driver_s *dev)
}
#ifdef CONFIG_NET_NAT66
+ if (isfrag)
+ {
+ return ipv6_fragin_or_drop(dev);
+ }
+
/* Try NAT inbound, rule matching will be performed in NAT module. */
ipv6_nat_inbound(dev, ipv6);
@@ -410,17 +445,7 @@ static int ipv6_in(FAR struct net_driver_s *dev)
#ifdef CONFIG_NET_IPFRAG
if (isfrag)
{
- if (ipv6_fragin(dev) == OK)
- {
- return OK;
- }
- else
- {
-#ifdef CONFIG_NET_STATISTICS
- g_netstats.ipv6.fragerr++;
-#endif
- goto drop;
- }
+ return ipv6_fragin_or_drop(dev);
}
#endif
diff --git a/net/nat/ipv6_nat.c b/net/nat/ipv6_nat.c
index 1c0f16ec955..4a40d2cc4be 100644
--- a/net/nat/ipv6_nat.c
+++ b/net/nat/ipv6_nat.c
@@ -540,7 +540,7 @@ ipv6_nat_inbound_internal(FAR struct ipv6_hdr_s *ipv6,
uint8_t proto;
FAR void *l4hdr = net_ipv6_payload(ipv6, &proto);
- switch (ipv6->proto)
+ switch (proto)
{
#ifdef CONFIG_NET_TCP
case IP_PROTO_TCP:
(nuttx) 01/03: net/ipv4: Forward fragments before local reassembly
Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 682ce1db2f3bb6c3afd3c101ff89068cb3f21b93
Author: shichunma <ma...@gmail.com>
AuthorDate: Sat Aug 1 17:33:52 2026 +0800
net/ipv4: Forward fragments before local reassembly
Allow non-local IPv4 fragments to reach the forwarding path before local fragment reassembly. This lets routers forward fragmented datagrams without requiring local reassembly state.
Keep NAT44 and IP filter builds on the existing reassembly path because those features can depend on L4 headers. Preserve the original fragment offset and MF flag when fragout must split an already-fragmented packet for a smaller egress MTU.
Signed-off-by: shichunma <sh...@bestechnic.com>
---
net/devif/ipv4_input.c | 69 ++++++++++++++++++++++++++++++++++----------
net/ipforward/ipv4_forward.c | 5 ++++
net/ipfrag/ipv4_frag.c | 16 ++++++++--
3 files changed, 71 insertions(+), 19 deletions(-)
diff --git a/net/devif/ipv4_input.c b/net/devif/ipv4_input.c
index 77ea651499b..eb880ad2e90 100644
--- a/net/devif/ipv4_input.c
+++ b/net/devif/ipv4_input.c
@@ -84,6 +84,7 @@
#include <sys/ioctl.h>
#include <stdint.h>
+#include <stdbool.h>
#include <nuttx/debug.h>
#include <string.h>
@@ -166,6 +167,34 @@ static int ipv4_check_opt(FAR struct ipv4_hdr_s *ipv4)
}
#endif
+/****************************************************************************
+ * Name: ipv4_fragin_or_drop
+ *
+ * Description:
+ * Reassemble an incoming IPv4 fragment for local processing or drop it if
+ * fragment reassembly is not available.
+ *
+ ****************************************************************************/
+
+static int ipv4_fragin_or_drop(FAR struct net_driver_s *dev)
+{
+#ifdef CONFIG_NET_IPFRAG
+ if (ipv4_fragin(dev) == OK)
+ {
+ return OK;
+ }
+#endif
+
+#ifdef CONFIG_NET_STATISTICS
+ g_netstats.ipv4.drop++;
+ g_netstats.ipv4.fragerr++;
+#endif
+ nwarn("WARNING: IP fragment dropped\n");
+
+ dev->d_len = 0;
+ return OK;
+}
+
/****************************************************************************
* Name: ipv4_in
*
@@ -199,6 +228,7 @@ static int ipv4_in(FAR struct net_driver_s *dev)
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
in_addr_t destipaddr;
uint16_t totlen;
+ bool isfrag;
int ret = OK;
/* Handle ARP on input then give the IPv4 packet to the network layer */
@@ -273,22 +303,7 @@ static int ipv4_in(FAR struct net_driver_s *dev)
/* Check the fragment flag. */
- if ((ipv4->ipoffset[0] & 0x3f) != 0 || ipv4->ipoffset[1] != 0)
- {
-#ifdef CONFIG_NET_IPFRAG
- if (ipv4_fragin(dev) == OK)
- {
- return OK;
- }
-
-#endif
-#ifdef CONFIG_NET_STATISTICS
- g_netstats.ipv4.drop++;
- g_netstats.ipv4.fragerr++;
-#endif
- nwarn("WARNING: IP fragment dropped\n");
- goto drop;
- }
+ isfrag = (ipv4->ipoffset[0] & 0x3f) != 0 || ipv4->ipoffset[1] != 0;
#ifdef CONFIG_DEBUG_FEATURES
if (ipv4_check_opt(ipv4) != OK)
@@ -301,6 +316,13 @@ static int ipv4_in(FAR struct net_driver_s *dev)
}
#endif
+#if defined(CONFIG_NET_NAT44) || defined(CONFIG_NET_IPFILTER)
+ if (isfrag)
+ {
+ return ipv4_fragin_or_drop(dev);
+ }
+#endif
+
#ifdef CONFIG_NET_NAT44
/* Try NAT inbound, rule matching will be performed in NAT module. */
@@ -334,6 +356,11 @@ static int ipv4_in(FAR struct net_driver_s *dev)
ipv4_forward_broadcast(dev, ipv4);
#endif
+ if (isfrag)
+ {
+ return ipv4_fragin_or_drop(dev);
+ }
+
#if defined(CONFIG_NET_BROADCAST) && defined(NET_UDP_HAVE_STACK)
if (ipv4->proto == IP_PROTO_UDP)
{
@@ -406,6 +433,16 @@ static int ipv4_in(FAR struct net_driver_s *dev)
}
}
+ /* Forwarding has already had a chance to consume non-local unicast
+ * fragments. Any remaining fragments are for local input and must be
+ * reassembled before the transport layer sees them.
+ */
+
+ if (isfrag)
+ {
+ return ipv4_fragin_or_drop(dev);
+ }
+
#ifdef CONFIG_NET_IPV4_CHECKSUMS
if (((dev->d_features & NETDEV_RX_CSUM) == 0)
&& (ipv4_chksum(IPv4BUF) != 0xffff))
diff --git a/net/ipforward/ipv4_forward.c b/net/ipforward/ipv4_forward.c
index 5bd509042e7..24e2d256b24 100644
--- a/net/ipforward/ipv4_forward.c
+++ b/net/ipforward/ipv4_forward.c
@@ -77,6 +77,11 @@ static int ipv4_hdrsize(FAR struct ipv4_hdr_s *ipv4)
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
+ if ((ipv4->ipoffset[0] & 0x3f) != 0 || ipv4->ipoffset[1] != 0)
+ {
+ return iphdrlen;
+ }
+
/* Size is also determined by the following protocol header, */
switch (ipv4->proto)
diff --git a/net/ipfrag/ipv4_frag.c b/net/ipfrag/ipv4_frag.c
index b5628f28a78..314ec3f15f6 100644
--- a/net/ipfrag/ipv4_frag.c
+++ b/net/ipfrag/ipv4_frag.c
@@ -360,6 +360,8 @@ int32_t ipv4_fragout(FAR struct net_driver_s *dev, uint16_t mtu)
uint32_t iter;
uint32_t nfrags;
uint16_t offset = 0;
+ uint16_t fragoff;
+ uint16_t morefrags;
uint16_t hdrlen;
FAR struct iob_s *frag = NULL;
FAR struct ipv4_hdr_s *ref = NULL;
@@ -374,6 +376,14 @@ int32_t ipv4_fragout(FAR struct net_driver_s *dev, uint16_t mtu)
hdrlen = (IPv4BUF->vhl & IPv4_HLMASK) << 2;
+ /* Preserve the original fragment offset when splitting an
+ * already-fragmented packet for a smaller egress MTU.
+ */
+
+ fragoff = (IPv4BUF->ipoffset[0] << 8) + IPv4BUF->ipoffset[1];
+ morefrags = fragoff & IP_FLAG_MOREFRAGS;
+ fragoff &= 0x1fff;
+
/* Reconstruct I/O Buffer according to MTU, which will reserve
* the space for the L3 header
*/
@@ -401,13 +411,13 @@ int32_t ipv4_fragout(FAR struct net_driver_s *dev, uint16_t mtu)
/* Update the IPv4 header of the first fragment */
ipv4_fragout_buildipv4header(ref, ref, frag->io_pktlen,
- IP_FLAG_MOREFRAGS);
+ fragoff | IP_FLAG_MOREFRAGS);
}
else
{
- uint16_t ipoff = (offset - iter * hdrlen) >> 3;
+ uint16_t ipoff = fragoff + ((offset - iter * hdrlen) >> 3);
- if (iter < nfrags - 1)
+ if (iter < nfrags - 1 || morefrags)
{
ipoff |= IP_FLAG_MOREFRAGS;
}