Skip to content

Commit

Permalink
ipv6: Allow accepting RA from local IP addresses.
Browse files Browse the repository at this point in the history
This can be used in virtual networking applications, and
may have other uses as well.  The option is disabled by
default.

A specific use case is setting up virtual routers, bridges, and
hosts on a single OS without the use of network namespaces or
virtual machines.  With proper use of ip rules, routing tables,
veth interface pairs and/or other virtual interfaces,
and applications that can bind to interfaces and/or IP addresses,
it is possibly to create one or more virtual routers with multiple
hosts attached.  The host interfaces can act as IPv6 systems,
with radvd running on the ports in the virtual routers.  With the
option provided in this patch enabled, those hosts can now properly
obtain IPv6 addresses from the radvd.

Signed-off-by: Ben Greear <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
greearb authored and davem330 committed Jul 1, 2014
1 parent f2a762d commit d933319
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 8 deletions.
12 changes: 12 additions & 0 deletions Documentation/networking/ip-sysctl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,18 @@ accept_ra_defrtr - BOOLEAN
Functional default: enabled if accept_ra is enabled.
disabled if accept_ra is disabled.

accept_ra_from_local - BOOLEAN
Accept RA with source-address that is found on local machine
if the RA is otherwise proper and able to be accepted.
Default is to NOT accept these as it may be an un-intended
network loop.

Functional default:
enabled if accept_ra_from_local is enabled
on a specific interface.
disabled if accept_ra_from_local is disabled
on a specific interface.

accept_ra_pinfo - BOOLEAN
Learn Prefix Information in Router Advertisement.

Expand Down
1 change: 1 addition & 0 deletions include/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct ipv6_devconf {
#endif
__s32 proxy_ndp;
__s32 accept_source_route;
__s32 accept_ra_from_local;
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
__s32 optimistic_dad;
#endif
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ enum {
DEVCONF_MLDV1_UNSOLICITED_REPORT_INTERVAL,
DEVCONF_MLDV2_UNSOLICITED_REPORT_INTERVAL,
DEVCONF_SUPPRESS_FRAG_NDISC,
DEVCONF_ACCEPT_RA_FROM_LOCAL,
DEVCONF_MAX
};

Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/sysctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ enum {
NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22,
NET_IPV6_PROXY_NDP=23,
NET_IPV6_ACCEPT_SOURCE_ROUTE=25,
NET_IPV6_ACCEPT_RA_FROM_LOCAL=26,
__NET_IPV6_MAX
};

Expand Down
1 change: 1 addition & 0 deletions kernel/sysctl_binary.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ static const struct bin_table bin_net_ipv6_conf_var_table[] = {
{ CTL_INT, NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, "accept_ra_rt_info_max_plen" },
{ CTL_INT, NET_IPV6_PROXY_NDP, "proxy_ndp" },
{ CTL_INT, NET_IPV6_ACCEPT_SOURCE_ROUTE, "accept_source_route" },
{ CTL_INT, NET_IPV6_ACCEPT_RA_FROM_LOCAL, "accept_ra_from_local" },
{}
};

Expand Down
10 changes: 10 additions & 0 deletions net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.max_desync_factor = MAX_DESYNC_FACTOR,
.max_addresses = IPV6_MAX_ADDRESSES,
.accept_ra_defrtr = 1,
.accept_ra_from_local = 0,
.accept_ra_pinfo = 1,
#ifdef CONFIG_IPV6_ROUTER_PREF
.accept_ra_rtr_pref = 1,
Expand Down Expand Up @@ -222,6 +223,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.max_desync_factor = MAX_DESYNC_FACTOR,
.max_addresses = IPV6_MAX_ADDRESSES,
.accept_ra_defrtr = 1,
.accept_ra_from_local = 0,
.accept_ra_pinfo = 1,
#ifdef CONFIG_IPV6_ROUTER_PREF
.accept_ra_rtr_pref = 1,
Expand Down Expand Up @@ -4321,6 +4323,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc;
array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local;
}

static inline size_t inet6_ifla6_size(void)
Expand Down Expand Up @@ -5167,6 +5170,13 @@ static struct addrconf_sysctl_table
.mode = 0644,
.proc_handler = proc_dointvec
},
{
.procname = "accept_ra_from_local",
.data = &ipv6_devconf.accept_ra_from_local,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
/* sentinel */
}
Expand Down
21 changes: 13 additions & 8 deletions net/ipv6/ndisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1148,11 +1148,15 @@ static void ndisc_router_discovery(struct sk_buff *skb)
goto skip_defrtr;
}

if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
NULL, 0)) {
/* Do not accept RA with source-addr found on local machine unless
* accept_ra_from_local is set to true.
*/
if (!(in6_dev->cnf.accept_ra_from_local ||
ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
NULL, 0))) {
ND_PRINTK(2, info,
"RA: %s, chk_addr failed for dev: %s\n",
__func__, skb->dev->name);
"RA from local address detected on dev: %s: default router ignored\n",
skb->dev->name);
goto skip_defrtr;
}

Expand Down Expand Up @@ -1290,11 +1294,12 @@ static void ndisc_router_discovery(struct sk_buff *skb)
}

#ifdef CONFIG_IPV6_ROUTE_INFO
if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
NULL, 0)) {
if (!(in6_dev->cnf.accept_ra_from_local ||
ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
NULL, 0))) {
ND_PRINTK(2, info,
"RA: %s, chk-addr (route info) is false for dev: %s\n",
__func__, skb->dev->name);
"RA from local address detected on dev: %s: router info ignored.\n",
skb->dev->name);
goto skip_routeinfo;
}

Expand Down

0 comments on commit d933319

Please sign in to comment.