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.
        */
 

Reply via email to