nixos/network-interfaces: add option to set source address

This commit is contained in:
rnhmjoj
2025-06-14 02:37:40 +02:00
parent a1a86470e3
commit 1a8c90128b
4 changed files with 71 additions and 34 deletions

View File

@@ -42,6 +42,14 @@ let
ip link del dev "${i}" 2>/dev/null || true ip link del dev "${i}" 2>/dev/null || true
''; '';
formatIpArgs =
args:
lib.pipe args [
(lib.filterAttrs (n: v: v != null))
(lib.mapAttrsToList (n: v: "${n} ${toString v}"))
(lib.concatStringsSep " ")
];
# warn that these attributes are deprecated (2017-2-2) # warn that these attributes are deprecated (2017-2-2)
# Should be removed in the release after next # Should be removed in the release after next
bondDeprecation = rec { bondDeprecation = rec {
@@ -160,39 +168,41 @@ let
EOF EOF
''} ''}
# Set the default gateway. # Set the default gateway
${optionalString (cfg.defaultGateway != null && cfg.defaultGateway.address != "") '' ${flip concatMapStrings
${optionalString (cfg.defaultGateway.interface != null) '' [
ip route replace ${cfg.defaultGateway.address} dev ${cfg.defaultGateway.interface} ${ {
optionalString (cfg.defaultGateway.metric != null) "metric ${toString cfg.defaultGateway.metric}" version = "-4";
} proto static gateway = cfg.defaultGateway;
''} }
ip route replace default ${ {
optionalString (cfg.defaultGateway.metric != null) "metric ${toString cfg.defaultGateway.metric}" version = "-6";
} via "${cfg.defaultGateway.address}" ${ gateway = cfg.defaultGateway6;
optionalString ( }
cfg.defaultGatewayWindowSize != null ]
) "window ${toString cfg.defaultGatewayWindowSize}" (
} ${ { version, gateway }:
optionalString (cfg.defaultGateway.interface != null) "dev ${cfg.defaultGateway.interface}" optionalString (gateway != null && gateway.address != "") ''
} proto static ${optionalString (gateway.interface != null) ''
''} ip ${version} route replace ${gateway.address} proto static ${
${optionalString (cfg.defaultGateway6 != null && cfg.defaultGateway6.address != "") '' formatIpArgs {
${optionalString (cfg.defaultGateway6.interface != null) '' metric = gateway.metric;
ip -6 route replace ${cfg.defaultGateway6.address} dev ${cfg.defaultGateway6.interface} ${ dev = gateway.interface;
optionalString (cfg.defaultGateway6.metric != null) "metric ${toString cfg.defaultGateway6.metric}" }
} proto static }
''}
ip -6 route replace default ${
optionalString (cfg.defaultGateway6.metric != null) "metric ${toString cfg.defaultGateway6.metric}"
} via "${cfg.defaultGateway6.address}" ${
optionalString (
cfg.defaultGatewayWindowSize != null
) "window ${toString cfg.defaultGatewayWindowSize}"
} ${
optionalString (cfg.defaultGateway6.interface != null) "dev ${cfg.defaultGateway6.interface}"
} proto static
''} ''}
ip ${version} route replace default proto static ${
formatIpArgs {
metric = gateway.metric;
via = gateway.address;
window = cfg.defaultGatewayWindowSize;
dev = gateway.interface;
src = gateway.source;
}
}
''
)
}
''; '';
}; };

View File

@@ -46,6 +46,9 @@ let
// optionalAttrs (gateway.metric != null) { // optionalAttrs (gateway.metric != null) {
Metric = gateway.metric; Metric = gateway.metric;
} }
// optionalAttrs (gateway.source != null) {
PreferredSource = gateway.source;
}
) )
]; ];
}; };

View File

@@ -180,6 +180,12 @@ let
description = "The default gateway metric/preference."; description = "The default gateway metric/preference.";
}; };
source = mkOption {
type = types.nullOr types.str;
default = null;
description = "The default source address.";
};
}; };
}; };
@@ -656,6 +662,7 @@ in
example = { example = {
address = "131.211.84.1"; address = "131.211.84.1";
interface = "enp3s0"; interface = "enp3s0";
source = "131.211.84.2";
}; };
type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts)); type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts));
description = '' description = ''
@@ -669,6 +676,7 @@ in
example = { example = {
address = "2001:4d0:1e04:895::1"; address = "2001:4d0:1e04:895::1";
interface = "enp3s0"; interface = "enp3s0";
source = "2001:4d0:1e04:895::2";
}; };
type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts)); type = types.nullOr (types.coercedTo types.str gatewayCoerce (types.submodule gatewayOpts));
description = '' description = ''

View File

@@ -39,11 +39,23 @@ let
defaultGateway = { defaultGateway = {
address = "192.168.1.1"; address = "192.168.1.1";
interface = "enp1s0"; interface = "enp1s0";
source = "192.168.1.3";
}; };
defaultGateway6 = { defaultGateway6 = {
address = "fd00:1234:5678:1::1"; address = "fd00:1234:5678:1::1";
interface = "enp1s0"; interface = "enp1s0";
source = "fd00:1234:5678:1::3";
}; };
interfaces.enp1s0.ipv6.addresses = [
{
address = "fd00:1234:5678:1::2";
prefixLength = 64;
}
{
address = "fd00:1234:5678:1::3";
prefixLength = 128;
}
];
interfaces.enp1s0.ipv4.addresses = [ interfaces.enp1s0.ipv4.addresses = [
{ {
address = "192.168.1.2"; address = "192.168.1.2";
@@ -89,7 +101,11 @@ let
with subtest("Test default gateway"): with subtest("Test default gateway"):
client.wait_until_succeeds("ping -c 1 192.168.3.1") client.wait_until_succeeds("ping -c 1 192.168.3.1")
client.wait_until_succeeds("ping -c 1 fd00:1234:5678:3::1") client.wait_until_succeeds("ping -c 1 fd00:1234:5678:1::1")
with subtest("Test default addresses"):
client.succeed("ip -4 route show default | grep -q 'src 192.168.1.3'")
client.succeed("ip -6 route show default | grep -q 'src fd00:1234:5678:1::3'")
''; '';
}; };
routeType = { routeType = {