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 <zhaohaiyang1@xiaomi.com>
This commit is contained in:
zhaohaiyang1
2026-01-29 14:05:13 +08:00
committed by Xiang Xiao
parent db50f0445a
commit f653ffd723
3 changed files with 114 additions and 33 deletions
+38 -30
View File
@@ -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_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_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_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.
+36 -2
View File
@@ -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.
*/
+40 -1
View File
@@ -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.
*/