2
0

enable ipv6 autoconfig when dhcp6c is specified

DHCP6 and autoconfig work in tandem not in opposition! dhcp6 does not
provide a default gateway: it depends on router solicitation/router
adverts for that

Tl;dr the network/site admin will ensure that router adverts are being
sent periodically. The adverts will have either Autonomous or Managed
bits set and that is what tells the host to use SLAAC or to use DHCP6
This commit is contained in:
2025-11-11 21:00:16 +00:00
parent ff7aaec874
commit 40194d5351
4 changed files with 111 additions and 14 deletions
+20 -14
View File
@@ -2,26 +2,32 @@
liminix,
odhcp6c,
odhcp-script,
svc
svc,
}:
{ interface }:
let
inherit (liminix.services) longrun;
inherit (liminix) outputRef;
name = "dhcp6c.${interface.name}";
service =
longrun {
inherit name;
notification-fd = 10;
run = ''
export SERVICE_STATE=$SERVICE_OUTPUTS/${name}
ifname=$(output ${interface} ifname)
test -n "$ifname" && ${odhcp6c}/bin/odhcp6c -s ${odhcp-script} -e -v -p /run/${name}.pid -P0 $ifname
)
'';
dependencies = [ interface ];
};
in svc.secrets.subscriber.build {
autoconf = svc.ipv6.autoconfig.build {
inherit interface;
};
service = longrun {
inherit name;
notification-fd = 10;
run = ''
export SERVICE_STATE=$SERVICE_OUTPUTS/${name}
ifname=$(output ${interface} ifname)
test -n "$ifname" && ${odhcp6c}/bin/odhcp6c -s ${odhcp-script} -e -v -p /run/${name}.pid -P0 $ifname
)
'';
dependencies = [
interface
autoconf
];
};
in
svc.secrets.subscriber.build {
# if the ppp service gets restarted, the interface may be different and
# we will have to restart dhcp on the new one
watch = [ (outputRef interface "ifindex") ];
+3
View File
@@ -20,6 +20,9 @@ let
inherit (pkgs) liminix;
in
{
imports = [
../ipv6-autoconfig
];
options = {
system.service.dhcp6c = {
client = mkOption { type = liminix.lib.types.serviceDefn; };
+37
View File
@@ -0,0 +1,37 @@
{
liminix,
writeAshScript,
serviceFns,
lib,
}:
{
interface,
role,
sysctl,
}:
let
inherit (liminix.services) oneshot;
inherit (lib) recursiveUpdate;
name = "${interface.name}.autoconfig";
sysctls =
let
s = recursiveUpdate {
autoconf = "1";
accept_ra = (role == "host");
} sysctl;
in
liminix.writeSysctls s;
in
oneshot {
inherit name;
dependencies = [ interface ];
up = ''
cd /proc/sys/net/ipv6/conf/$(output ${interface} ifname)
${sysctls}
'';
down = ''
cd /proc/sys/net/ipv6/conf/$(output ${interface} ifname)
echo "0" > autoconf
echo "0" > accept_ra
'';
}
+51
View File
@@ -0,0 +1,51 @@
## IPv6 Autoconfiguration
## ======================
##
## Enable IPv6 neighbour discovery for an interface and allow it
## to participate in router solicitation/router advertisement.
##
## You need this if you want to get an IPv6 address (or addresses)
## whether by stateless allocation (SLAAC) or by DHCP6. You don't
## need this on interfaces that are members of bridges, because they
## shouldn't have addresses of their own.
{
lib,
pkgs,
config,
...
}:
let
inherit (lib) mkOption types;
inherit (pkgs) liminix;
in
{
options.system.service.ipv6.autoconfig = mkOption {
type = liminix.lib.types.serviceDefn;
};
config.system.service.ipv6 = {
autoconfig = config.system.callService ./autoconfig.nix {
interface = mkOption {
type = liminix.lib.types.interface;
};
role = mkOption {
description = "configure as host or router (controls whether accept_ra sis set)";
type = types.enum [
"host"
"router"
];
default = "host";
};
sysctl = mkOption {
type = types.attrsOf types.str;
description = "additional sysctl settings to apply to /proc/sys/net/ipv6/conf/<ifname>";
default = { };
example = {
dad_transmits = 1;
hop_limit = 64;
};
};
};
};
}