Fix #785: disable global IPv6 fwd by default

Enabled by user enabling IPv6 forwarding on any interface.  This change
also enables net.ipv6.conf.all.accept_ra (=2) to accept any IPv6 route
advertisements even when acting as a router.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2025-02-25 17:31:32 +01:00
parent 888f0c4207
commit b70129f178
3 changed files with 64 additions and 19 deletions
+7 -2
View File
@@ -2,10 +2,15 @@
net.ipv6.route.max_size=131072
net.ipv6.conf.all.ignore_routes_with_linkdown=1
# IP Routing
net.ipv6.conf.all.forwarding=1
# IP Routing is disabled by default, enabled globally, and per
# interface, for each interface in confd. See also accept_ra.
net.ipv6.conf.all.forwarding=0
net.ipv6.conf.default.forwarding=0
# Accept router advertisements even when forwarding is enabled
net.ipv6.conf.all.accept_ra=2
net.ipv6.conf.default.accept_ra=2
# IPv6 SLAAC
net.ipv6.conf.all.autoconf=0
net.ipv6.conf.default.autoconf=0
+19 -15
View File
@@ -1183,23 +1183,27 @@ received on this interface can be forwarded.
### IPv6 forwarding
This flag behaves totally different than for IPv4. For IPv6 the
ability to route between interfaces is always enabled, instead this
flag controls if the interface will be in host/router mode.
Due to how the Linux kernel manages IPv6 forwarding, we can not fully
control it per interface via this setting like how IPv4 works. Instead,
IPv6 forwarding is globally enabled when at least one interface enable
forwarding, otherwise it is disabled.
| **Feature** | **Forward enabled** | **Forward disabled** |
|:-----------------------------------------|:--------------------|:---------------------|
| IsRouter set in Neighbour Advertisements | Yes | No |
| Transmit Router Solicitations | No | Yes |
| Router Advertisements are ignored | No | Yes |
| Accept Redirects | No | Yes |
The following table shows the system IPv6 features that the `forwarding`
setting control when it is *Enabled* or *Disabled:
```
admin@example:/config/> edit interface eth0
admin@example:/config/interface/eth0/> set ipv6 forwarding
admin@example:/config/interface/eth0/> leave
admin@example:/>
```
| **IPv6 Feature** | **Enabled** | **Disabled** |
|:-----------------------------------------|:------------|:-------------|
| IsRouter set in Neighbour Advertisements | Yes | No |
| Transmit Router Solicitations | No | Yes |
| Router Advertisements are ignored | Yes | Yes |
| Accept Redirects | No | Yes |
```
admin@example:/config/> edit interface eth0
admin@example:/config/interface/eth0/> set ipv6 forwarding
admin@example:/config/interface/eth0/> leave
admin@example:/>
```
## Routing support
+38 -2
View File
@@ -350,6 +350,39 @@ skip_mtu:
return err;
}
/*
* The global IPv6 forwarding lever is off by default, enabled when any
* interface has IPv6 forwarding enabled.
*/
static int netdag_ipv6_forwarding(struct lyd_node *cifs, struct dagger *net)
{
struct lyd_node *cif;
FILE *sysctl = NULL;
int ena = 0;
LYX_LIST_FOR_EACH(cifs, cif, "interface")
ena |= lydx_is_enabled(lydx_get_child(cif, "ipv6"), "forwarding");
if (ena)
sysctl = dagger_fopen_next(net, "init", "@post", NETDAG_INIT_POST, "ipv6.sysctl");
else
sysctl = dagger_fopen_current(net, "exit", "@pre", NETDAG_EXIT_PRE, "ipv6.sysctl");
if (!sysctl) {
/*
* Cannot create exit code in gen: -1. Safe to ignore
* since ipv6 forwarding is disabled by default.
*/
if (dagger_is_bootstrap(net) && !ena)
return 0;
return -EIO;
}
fprintf(sysctl, "net.ipv6.conf.all.forwarding = %d\n", ena);
fclose(sysctl);
return 0;
}
static int dummy_gen(struct lyd_node *dif, struct lyd_node *cif, FILE *ip)
{
const char *ifname = lydx_get_cattr(cif, "name");
@@ -707,7 +740,10 @@ static sr_error_t netdag_init(sr_session_ctx_t *session, struct dagger *net,
static sr_error_t ifchange_post(sr_session_ctx_t *session, struct dagger *net,
struct lyd_node *cifs, struct lyd_node *difs)
{
int err;
int err = 0;
/* Figure out value of global IPv6 forwarding flag. Issue #785 */
err |= netdag_ipv6_forwarding(cifs, net);
/* For each configured bridge, the corresponding multicast
* querier settings depend on both the bridge config and on
@@ -717,7 +753,7 @@ static sr_error_t ifchange_post(sr_session_ctx_t *session, struct dagger *net,
* regenerate the full config for mcd every time by walking
* the full configuration.
*/
err = bridge_mcd_gen(cifs);
err |= bridge_mcd_gen(cifs);
/* Whenever at least one bridge has spanning tree enabled,
* start mstpd; otherwise, stop it.