This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new f653ffd7237 forward: Add IFF_NOSRC_FORWARD and IFF_NODST_FORWARD flags.
f653ffd7237 is described below
commit f653ffd7237db9190053036066dd70f0cee8fc84
Author: zhaohaiyang1 <[email protected]>
AuthorDate: Thu Jan 29 14:05:13 2026 +0800
forward: Add IFF_NOSRC_FORWARD and IFF_NODST_FORWARD flags.
* IFF_NOSRC_FORWARD: Controls whether device prohibits forwarding packets
inputs
* IFF_NODST_FORWARD: Controls whether device prohibits forwarding packets
outputs
This allows users to selectively enable/disable forwarding on specific
devices, improving network flexibility and security.
Signed-off-by: zhaohaiyang1 <[email protected]>
---
include/net/if.h | 72 ++++++++++++++++++++++++--------------------
net/ipforward/ipv4_forward.c | 38 +++++++++++++++++++++--
net/ipforward/ipv6_forward.c | 41 ++++++++++++++++++++++++-
3 files changed, 116 insertions(+), 35 deletions(-)
diff --git a/include/net/if.h b/include/net/if.h
index 3727d924b5a..db49af71b25 100644
--- a/include/net/if.h
+++ b/include/net/if.h
@@ -63,41 +63,49 @@
#define IFF_NOTRAILERS (1 << 17) /* Avoid use of trailers. */
#define IFF_PROMISC (1 << 18) /* Receive all packets. */
#define IFF_ALLMULTI (1 << 19) /* Receive all multicast packets. */
+#define IFF_NOSRC_FORWARD (1 << 20) /* Device prohibits forwarding packets
inputs */
+#define IFF_NODST_FORWARD (1 << 21) /* Device prohibits forwarding packets
outputs */
/* Interface flag helpers */
-#define IFF_SET_UP(f) do { (f) |= IFF_UP; } while (0)
-#define IFF_SET_RUNNING(f) do { (f) |= IFF_RUNNING; } while (0)
-#define IFF_SET_NOARP(f) do { (f) |= IFF_NOARP; } while (0)
-#define IFF_SET_NAT(f) do { (f) |= IFF_NAT; } while (0)
-#define IFF_SET_LOOPBACK(f) do { (f) |= IFF_LOOPBACK; } while (0)
-#define IFF_SET_POINTOPOINT(f) do { (f) |= IFF_POINTOPOINT; } while (0)
-#define IFF_SET_MULTICAST(f) do { (f) |= IFF_MULTICAST; } while (0)
-#define IFF_SET_BROADCAST(f) do { (f) |= IFF_BROADCAST; } while (0)
-#define IFF_SET_SLAVE(f) do { (f) |= IFF_SLAVE; } while (0)
-#define IFF_SET_DYNAMIC(f) do { (f) |= IFF_DYNAMIC; } while (0)
-
-#define IFF_CLR_UP(f) do { (f) &= ~IFF_UP; } while (0)
-#define IFF_CLR_RUNNING(f) do { (f) &= ~IFF_RUNNING; } while (0)
-#define IFF_CLR_NOARP(f) do { (f) &= ~IFF_NOARP; } while (0)
-#define IFF_CLR_NAT(f) do { (f) &= ~IFF_NAT; } while (0)
-#define IFF_CLR_LOOPBACK(f) do { (f) &= ~IFF_LOOPBACK; } while (0)
-#define IFF_CLR_POINTOPOINT(f) do { (f) &= ~IFF_POINTOPOINT; } while (0)
-#define IFF_CLR_MULTICAST(f) do { (f) &= ~IFF_MULTICAST; } while (0)
-#define IFF_CLR_BROADCAST(f) do { (f) &= ~IFF_BROADCAST; } while (0)
-#define IFF_CLR_SLAVE(f) do { (f) &= ~IFF_SLAVE; } while (0)
-#define IFF_CLR_DYNAMIC(f) do { (f) &= ~IFF_DYNAMIC; } while (0)
-
-#define IFF_IS_UP(f) (((f) & IFF_UP) != 0)
-#define IFF_IS_RUNNING(f) (((f) & IFF_RUNNING) != 0)
-#define IFF_IS_NOARP(f) (((f) & IFF_NOARP) != 0)
-#define IFF_IS_NAT(f) (((f) & IFF_NAT) != 0)
-#define IFF_IS_LOOPBACK(f) (((f) & IFF_LOOPBACK) != 0)
-#define IFF_IS_POINTOPOINT(f) (((f) & IFF_POINTOPOINT) != 0)
-#define IFF_IS_MULTICAST(f) (((f) & IFF_MULTICAST) != 0)
-#define IFF_IS_BROADCAST(f) (((f) & IFF_BROADCAST) != 0)
-#define IFF_IS_SLAVE(f) (((f) & IFF_SLAVE) != 0)
-#define IFF_IS_DYNAMIC(f) (((f) & IFF_DYNAMIC) != 0)
+#define IFF_SET_UP(f) do { (f) |= IFF_UP; } while (0)
+#define IFF_SET_RUNNING(f) do { (f) |= IFF_RUNNING; } while (0)
+#define IFF_SET_NOARP(f) do { (f) |= IFF_NOARP; } while (0)
+#define IFF_SET_NAT(f) do { (f) |= IFF_NAT; } while (0)
+#define IFF_SET_LOOPBACK(f) do { (f) |= IFF_LOOPBACK; } while (0)
+#define IFF_SET_POINTOPOINT(f) do { (f) |= IFF_POINTOPOINT; } while (0)
+#define IFF_SET_MULTICAST(f) do { (f) |= IFF_MULTICAST; } while (0)
+#define IFF_SET_BROADCAST(f) do { (f) |= IFF_BROADCAST; } while (0)
+#define IFF_SET_SLAVE(f) do { (f) |= IFF_SLAVE; } while (0)
+#define IFF_SET_DYNAMIC(f) do { (f) |= IFF_DYNAMIC; } while (0)
+#define IFF_SET_NOSRC_FORWARD(f) do { (f) |= IFF_NOSRC_FORWARD; } while (0)
+#define IFF_SET_NODST_FORWARD(f) do { (f) |= IFF_NODST_FORWARD; } while (0)
+
+#define IFF_CLR_UP(f) do { (f) &= ~IFF_UP; } while (0)
+#define IFF_CLR_RUNNING(f) do { (f) &= ~IFF_RUNNING; } while (0)
+#define IFF_CLR_NOARP(f) do { (f) &= ~IFF_NOARP; } while (0)
+#define IFF_CLR_NAT(f) do { (f) &= ~IFF_NAT; } while (0)
+#define IFF_CLR_LOOPBACK(f) do { (f) &= ~IFF_LOOPBACK; } while (0)
+#define IFF_CLR_POINTOPOINT(f) do { (f) &= ~IFF_POINTOPOINT; } while (0)
+#define IFF_CLR_MULTICAST(f) do { (f) &= ~IFF_MULTICAST; } while (0)
+#define IFF_CLR_BROADCAST(f) do { (f) &= ~IFF_BROADCAST; } while (0)
+#define IFF_CLR_SLAVE(f) do { (f) &= ~IFF_SLAVE; } while (0)
+#define IFF_CLR_DYNAMIC(f) do { (f) &= ~IFF_DYNAMIC; } while (0)
+#define IFF_CLR_NOSRC_FORWARD(f) do { (f) &= ~IFF_NOSRC_FORWARD; } while (0)
+#define IFF_CLR_NODST_FORWARD(f) do { (f) &= ~IFF_NODST_FORWARD; } while (0)
+
+#define IFF_IS_UP(f) (((f) & IFF_UP) != 0)
+#define IFF_IS_RUNNING(f) (((f) & IFF_RUNNING) != 0)
+#define IFF_IS_NOARP(f) (((f) & IFF_NOARP) != 0)
+#define IFF_IS_NAT(f) (((f) & IFF_NAT) != 0)
+#define IFF_IS_LOOPBACK(f) (((f) & IFF_LOOPBACK) != 0)
+#define IFF_IS_POINTOPOINT(f) (((f) & IFF_POINTOPOINT) != 0)
+#define IFF_IS_MULTICAST(f) (((f) & IFF_MULTICAST) != 0)
+#define IFF_IS_BROADCAST(f) (((f) & IFF_BROADCAST) != 0)
+#define IFF_IS_SLAVE(f) (((f) & IFF_SLAVE) != 0)
+#define IFF_IS_DYNAMIC(f) (((f) & IFF_DYNAMIC) != 0)
+#define IFF_IS_NOSRC_FORWARD(f) (((f) & IFF_NOSRC_FORWARD) != 0)
+#define IFF_IS_NODST_FORWARD(f) (((f) & IFF_NODST_FORWARD) != 0)
/* We only need to manage the IPv6 bit if both IPv6 and IPv4 are supported.
* Otherwise, we can save a few bytes by ignoring it.
diff --git a/net/ipforward/ipv4_forward.c b/net/ipforward/ipv4_forward.c
index 96dc64f88df..3774481a75e 100644
--- a/net/ipforward/ipv4_forward.c
+++ b/net/ipforward/ipv4_forward.c
@@ -217,6 +217,14 @@ static int ipv4_dev_forward(FAR struct net_driver_s *dev,
#endif
int ret;
+ if (IFF_IS_NODST_FORWARD(fwddev->d_flags))
+ {
+ nwarn("WARNING: IP forwarding disabled on destination device %s\n",
+ fwddev->d_ifname);
+ ret = -EOPNOTSUPP;
+ goto errout;
+ }
+
#ifdef CONFIG_NET_IPFILTER
/* Do filter before forwarding, to make sure we drop silently before
* replying any other errors.
@@ -465,6 +473,14 @@ int ipv4_forward(FAR struct net_driver_s *dev, FAR struct
ipv4_hdr_s *ipv4)
int icmp_reply_code;
#endif /* CONFIG_NET_ICMP */
+ if (IFF_IS_NOSRC_FORWARD(dev->d_flags))
+ {
+ nwarn("WARNING: IP forwarding disabled on source device %s\n",
+ dev->d_ifname);
+ ret = -EOPNOTSUPP;
+ goto drop;
+ }
+
/* Search for a device that can forward this packet. */
destipaddr = net_ip4addr_conv32(ipv4->destipaddr);
@@ -512,7 +528,7 @@ int ipv4_forward(FAR struct net_driver_s *dev, FAR struct
ipv4_hdr_s *ipv4)
#endif
- nwarn("WARNING: Packet forwarding to same device not supportedN\n");
+ nwarn("WARNING: Packet forwarding to same device not supported\n");
ret = -ENOSYS;
goto drop;
}
@@ -547,6 +563,11 @@ drop:
icmp_reply_code = ICMP_EXC_TTL;
goto reply;
+ case -EOPNOTSUPP:
+ icmp_reply_type = ICMP_DEST_UNREACHABLE;
+ icmp_reply_code = ICMP_HOST_UNREACH;
+ goto reply;
+
default:
break; /* We don't know how to reply, just go on (to drop). */
}
@@ -600,11 +621,24 @@ reply:
void ipv4_forward_broadcast(FAR struct net_driver_s *dev,
FAR struct ipv4_hdr_s *ipv4)
{
+ /* Check if source device supports IP forwarding capability.
+ * Broadcast/multicast forwarding is only allowed if the receiving
+ * device has SRC_FORWARD enabled. This is consistent with the unicast
+ * forwarding policy enforced in ipv4_forward().
+ */
+
+ if (IFF_IS_NOSRC_FORWARD(dev->d_flags))
+ {
+ nwarn("WARNING: IP broadcast forwarding disabled "
+ "on source device %s\n", dev->d_ifname);
+ return;
+ }
+
/* Don't bother if the TTL would expire */
if (ipv4->ttl > 1)
{
- /* Forward the the broadcast/multicast packet to all devices except,
+ /* Forward the broadcast/multicast packet to all devices except,
* of course, the device that received the packet.
*/
diff --git a/net/ipforward/ipv6_forward.c b/net/ipforward/ipv6_forward.c
index c56d5d8a5ef..c41327a4393 100644
--- a/net/ipforward/ipv6_forward.c
+++ b/net/ipforward/ipv6_forward.c
@@ -340,6 +340,16 @@ static int ipv6_dev_forward(FAR struct net_driver_s *dev,
#endif
int ret;
+ /* Check if destination device supports IP forwarding capability */
+
+ if (IFF_IS_NODST_FORWARD(fwddev->d_flags))
+ {
+ nwarn("WARNING: IP forwarding disabled on destination device %s\n",
+ fwddev->d_ifname);
+ ret = -EOPNOTSUPP;
+ goto errout;
+ }
+
#ifdef CONFIG_NET_IPFILTER
/* Do filter before forwarding, to make sure we drop silently before
* replying any other errors.
@@ -603,6 +613,16 @@ int ipv6_forward(FAR struct net_driver_s *dev, FAR struct
ipv6_hdr_s *ipv6)
int icmpv6_reply_data;
#endif /* CONFIG_NET_ICMP */
+ /* Check if source device supports IP forwarding capability */
+
+ if (IFF_IS_NOSRC_FORWARD(dev->d_flags))
+ {
+ nwarn("WARNING: IP forwarding disabled on source device %s\n",
+ dev->d_ifname);
+ ret = -EOPNOTSUPP;
+ goto drop;
+ }
+
/* Search for a device that can forward this packet. */
fwddev = netdev_findby_ripv6addr(ipv6->srcipaddr, ipv6->destipaddr);
@@ -718,6 +738,12 @@ drop:
icmpv6_reply_data = 0;
goto reply;
+ case -EOPNOTSUPP:
+ icmpv6_reply_type = ICMPv6_DEST_UNREACHABLE;
+ icmpv6_reply_code = ICMPv6_ADDR_UNREACH;
+ icmpv6_reply_data = 0;
+ goto reply;
+
default:
break; /* We don't know how to reply, just go on (to drop). */
}
@@ -771,11 +797,24 @@ reply:
void ipv6_forward_broadcast(FAR struct net_driver_s *dev,
FAR struct ipv6_hdr_s *ipv6)
{
+ /* Check if source device supports IP forwarding capability.
+ * Broadcast/multicast forwarding is only allowed if the receiving
+ * device has SRC_FORWARD enabled. This is consistent with the unicast
+ * forwarding policy enforced in ipv6_forward().
+ */
+
+ if (IFF_IS_NOSRC_FORWARD(dev->d_flags))
+ {
+ nwarn("WARNING: IP broadcast forwarding disabled "
+ "on source device %s\n", dev->d_ifname);
+ return;
+ }
+
/* Don't bother if the TTL would expire */
if (ipv6->ttl > 1)
{
- /* Forward the the broadcast/multicast packet to all devices except,
+ /* Forward the broadcast/multicast packet to all devices except,
* of course, the device that received the packet.
*/