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