Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

route: add support for directed broadcast forwarding

This patch implements the feature described in rfc1812#section-5.3.5.2
and rfc2644. It allows the router to forward directed broadcast when
sysctl bc_forwarding is enabled.

Note that this feature could be done by iptables -j TEE, but it would
cause some problems:
- target TEE's gateway param has to be set with a specific address,
and it's not flexible especially when the route wants forward all
directed broadcasts.
- this duplicates the directed broadcasts so this may cause side
effects to applications.

Besides, to keep consistent with other os router like BSD, it's also
necessary to implement it in the route rx path.

Note that route cache needs to be flushed when bc_forwarding is
changed.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Xin Long and committed by
David S. Miller
5cbf777c d0c1f011

+19 -1
+1
include/linux/inetdevice.h
··· 93 93 94 94 #define IN_DEV_FORWARD(in_dev) IN_DEV_CONF_GET((in_dev), FORWARDING) 95 95 #define IN_DEV_MFORWARD(in_dev) IN_DEV_ANDCONF((in_dev), MC_FORWARDING) 96 + #define IN_DEV_BFORWARD(in_dev) IN_DEV_ANDCONF((in_dev), BC_FORWARDING) 96 97 #define IN_DEV_RPFILTER(in_dev) IN_DEV_MAXCONF((in_dev), RP_FILTER) 97 98 #define IN_DEV_SRC_VMARK(in_dev) IN_DEV_ORCONF((in_dev), SRC_VMARK) 98 99 #define IN_DEV_SOURCE_ROUTE(in_dev) IN_DEV_ANDCONF((in_dev), \
+1
include/uapi/linux/ip.h
··· 168 168 IPV4_DEVCONF_IGNORE_ROUTES_WITH_LINKDOWN, 169 169 IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, 170 170 IPV4_DEVCONF_DROP_GRATUITOUS_ARP, 171 + IPV4_DEVCONF_BC_FORWARDING, 171 172 __IPV4_DEVCONF_MAX 172 173 }; 173 174
+1
include/uapi/linux/netconf.h
··· 18 18 NETCONFA_PROXY_NEIGH, 19 19 NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN, 20 20 NETCONFA_INPUT, 21 + NETCONFA_BC_FORWARDING, 21 22 __NETCONFA_MAX 22 23 }; 23 24 #define NETCONFA_MAX (__NETCONFA_MAX - 1)
+11
net/ipv4/devinet.c
··· 1827 1827 size += nla_total_size(4); 1828 1828 if (all || type == NETCONFA_MC_FORWARDING) 1829 1829 size += nla_total_size(4); 1830 + if (all || type == NETCONFA_BC_FORWARDING) 1831 + size += nla_total_size(4); 1830 1832 if (all || type == NETCONFA_PROXY_NEIGH) 1831 1833 size += nla_total_size(4); 1832 1834 if (all || type == NETCONFA_IGNORE_ROUTES_WITH_LINKDOWN) ··· 1874 1872 if ((all || type == NETCONFA_MC_FORWARDING) && 1875 1873 nla_put_s32(skb, NETCONFA_MC_FORWARDING, 1876 1874 IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0) 1875 + goto nla_put_failure; 1876 + if ((all || type == NETCONFA_BC_FORWARDING) && 1877 + nla_put_s32(skb, NETCONFA_BC_FORWARDING, 1878 + IPV4_DEVCONF(*devconf, BC_FORWARDING)) < 0) 1877 1879 goto nla_put_failure; 1878 1880 if ((all || type == NETCONFA_PROXY_NEIGH) && 1879 1881 nla_put_s32(skb, NETCONFA_PROXY_NEIGH, ··· 2149 2143 if ((new_value == 0) && (old_value != 0)) 2150 2144 rt_cache_flush(net); 2151 2145 2146 + if (i == IPV4_DEVCONF_BC_FORWARDING - 1 && 2147 + new_value != old_value) 2148 + rt_cache_flush(net); 2149 + 2152 2150 if (i == IPV4_DEVCONF_RP_FILTER - 1 && 2153 2151 new_value != old_value) { 2154 2152 ifindex = devinet_conf_ifindex(net, cnf); ··· 2269 2259 DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding", 2270 2260 devinet_sysctl_forward), 2271 2261 DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"), 2262 + DEVINET_SYSCTL_RW_ENTRY(BC_FORWARDING, "bc_forwarding"), 2272 2263 2273 2264 DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"), 2274 2265 DEVINET_SYSCTL_RW_ENTRY(SECURE_REDIRECTS, "secure_redirects"),
+5 -1
net/ipv4/route.c
··· 1996 1996 goto no_route; 1997 1997 } 1998 1998 1999 - if (res->type == RTN_BROADCAST) 1999 + if (res->type == RTN_BROADCAST) { 2000 + if (IN_DEV_BFORWARD(in_dev)) 2001 + goto make_route; 2000 2002 goto brd_input; 2003 + } 2001 2004 2002 2005 if (res->type == RTN_LOCAL) { 2003 2006 err = fib_validate_source(skb, saddr, daddr, tos, ··· 2017 2014 if (res->type != RTN_UNICAST) 2018 2015 goto martian_destination; 2019 2016 2017 + make_route: 2020 2018 err = ip_mkroute_input(skb, res, in_dev, daddr, saddr, tos, flkeys); 2021 2019 out: return err; 2022 2020