nixos/network-interfaces: let networkd handle privacy extensions (#431967)
This commit is contained in:
commit
bcc20cad16
@ -1884,6 +1884,11 @@ let
|
||||
networkdOptions = {
|
||||
networkConfig = mkOption {
|
||||
default = { };
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
IPv6PrivacyExtensions = true;
|
||||
}
|
||||
'';
|
||||
example = {
|
||||
SpeedMeter = true;
|
||||
ManageForeignRoutingPolicyRules = false;
|
||||
@ -3127,7 +3132,10 @@ let
|
||||
};
|
||||
|
||||
config = {
|
||||
networkConfig = optionalAttrs (config.routeTables != { }) {
|
||||
networkConfig = {
|
||||
IPv6PrivacyExtensions = lib.mkOptionDefault true;
|
||||
}
|
||||
// optionalAttrs (config.routeTables != { }) {
|
||||
RouteTable = mapAttrsToList (name: number: "${name}:${toString number}") config.routeTables;
|
||||
};
|
||||
};
|
||||
|
||||
@ -1813,146 +1813,147 @@ in
|
||||
|
||||
virtualisation.vswitch = mkIf (cfg.vswitches != { }) { enable = true; };
|
||||
|
||||
services.udev.packages = [
|
||||
(pkgs.writeTextFile rec {
|
||||
name = "ipv6-privacy-extensions.rules";
|
||||
destination = "/etc/udev/rules.d/98-${name}";
|
||||
text =
|
||||
let
|
||||
sysctl-value = tempaddrValues.${cfg.tempAddresses}.sysctl;
|
||||
in
|
||||
''
|
||||
# enable and prefer IPv6 privacy addresses by default
|
||||
ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.bash}/bin/sh -c 'echo ${sysctl-value} > /proc/sys/net/ipv6/conf/$name/use_tempaddr'"
|
||||
'';
|
||||
})
|
||||
(pkgs.writeTextFile rec {
|
||||
name = "ipv6-privacy-extensions.rules";
|
||||
destination = "/etc/udev/rules.d/99-${name}";
|
||||
text = concatMapStrings (
|
||||
i:
|
||||
let
|
||||
opt = i.tempAddress;
|
||||
val = tempaddrValues.${opt}.sysctl;
|
||||
msg = tempaddrValues.${opt}.description;
|
||||
in
|
||||
''
|
||||
# override to ${msg} for ${i.name}
|
||||
ACTION=="add", SUBSYSTEM=="net", NAME=="${i.name}", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${
|
||||
replaceStrings [ "." ] [ "/" ] i.name
|
||||
}.use_tempaddr=${val}"
|
||||
''
|
||||
) (filter (i: i.tempAddress != cfg.tempAddresses) interfaces);
|
||||
})
|
||||
]
|
||||
++ lib.optional (cfg.wlanInterfaces != { }) (
|
||||
pkgs.writeTextFile {
|
||||
name = "99-zzz-40-wlanInterfaces.rules";
|
||||
destination = "/etc/udev/rules.d/99-zzz-40-wlanInterfaces.rules";
|
||||
text =
|
||||
let
|
||||
# Collect all interfaces that are defined for a device
|
||||
# as device:interface key:value pairs.
|
||||
wlanDeviceInterfaces =
|
||||
let
|
||||
allDevices = unique (mapAttrsToList (_: v: v.device) cfg.wlanInterfaces);
|
||||
interfacesOfDevice = d: filterAttrs (_: v: v.device == d) cfg.wlanInterfaces;
|
||||
in
|
||||
genAttrs allDevices (d: interfacesOfDevice d);
|
||||
|
||||
# Convert device:interface key:value pairs into a list, and if it exists,
|
||||
# place the interface which is named after the device at the beginning.
|
||||
wlanListDeviceFirst =
|
||||
device: interfaces:
|
||||
if hasAttr device interfaces then
|
||||
mapAttrsToList (n: v: v // { _iName = n; }) (filterAttrs (n: _: n == device) interfaces)
|
||||
++ mapAttrsToList (n: v: v // { _iName = n; }) (filterAttrs (n: _: n != device) interfaces)
|
||||
else
|
||||
mapAttrsToList (n: v: v // { _iName = n; }) interfaces;
|
||||
|
||||
# Udev script to execute for the default WLAN interface with the persistend udev name.
|
||||
# The script creates the required, new WLAN interfaces interfaces and configures the
|
||||
# existing, default interface.
|
||||
curInterfaceScript =
|
||||
device: current: new:
|
||||
pkgs.writeScript "udev-run-script-wlan-interfaces-${device}.sh" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
# Change the wireless phy device to a predictable name.
|
||||
${pkgs.iw}/bin/iw phy `${pkgs.coreutils}/bin/cat /sys/class/net/$INTERFACE/phy80211/name` set name ${device}
|
||||
|
||||
# Add new WLAN interfaces
|
||||
${flip concatMapStrings new (i: ''
|
||||
${pkgs.iw}/bin/iw phy ${device} interface add ${i._iName} type managed
|
||||
'')}
|
||||
|
||||
# Configure the current interface
|
||||
${pkgs.iw}/bin/iw dev ${device} set type ${current.type}
|
||||
${optionalString (
|
||||
current.type == "mesh" && current.meshID != null
|
||||
) "${pkgs.iw}/bin/iw dev ${device} set meshid ${current.meshID}"}
|
||||
${optionalString (
|
||||
current.type == "monitor" && current.flags != null
|
||||
) "${pkgs.iw}/bin/iw dev ${device} set monitor ${current.flags}"}
|
||||
${optionalString (
|
||||
current.type == "managed" && current.fourAddr != null
|
||||
) "${pkgs.iw}/bin/iw dev ${device} set 4addr ${if current.fourAddr then "on" else "off"}"}
|
||||
${optionalString (
|
||||
current.mac != null
|
||||
) "${pkgs.iproute2}/bin/ip link set dev ${device} address ${current.mac}"}
|
||||
'';
|
||||
|
||||
# Udev script to execute for a new WLAN interface. The script configures the new WLAN interface.
|
||||
newInterfaceScript =
|
||||
new:
|
||||
pkgs.writeScript "udev-run-script-wlan-interfaces-${new._iName}.sh" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
# Configure the new interface
|
||||
${pkgs.iw}/bin/iw dev ${new._iName} set type ${new.type}
|
||||
${optionalString (
|
||||
new.type == "mesh" && new.meshID != null
|
||||
) "${pkgs.iw}/bin/iw dev ${new._iName} set meshid ${new.meshID}"}
|
||||
${optionalString (
|
||||
new.type == "monitor" && new.flags != null
|
||||
) "${pkgs.iw}/bin/iw dev ${new._iName} set monitor ${new.flags}"}
|
||||
${optionalString (
|
||||
new.type == "managed" && new.fourAddr != null
|
||||
) "${pkgs.iw}/bin/iw dev ${new._iName} set 4addr ${if new.fourAddr then "on" else "off"}"}
|
||||
${optionalString (
|
||||
new.mac != null
|
||||
) "${pkgs.iproute2}/bin/ip link set dev ${new._iName} address ${new.mac}"}
|
||||
'';
|
||||
|
||||
# Udev attributes for systemd to name the device and to create a .device target.
|
||||
systemdAttrs =
|
||||
n:
|
||||
''NAME:="${n}", ENV{INTERFACE}="${n}", ENV{SYSTEMD_ALIAS}="/sys/subsystem/net/devices/${n}", TAG+="systemd"'';
|
||||
in
|
||||
flip (concatMapStringsSep "\n") (attrNames wlanDeviceInterfaces) (
|
||||
device:
|
||||
services.udev.packages =
|
||||
lib.optionals (!config.systemd.network.enable) [
|
||||
(pkgs.writeTextFile rec {
|
||||
name = "ipv6-privacy-extensions.rules";
|
||||
destination = "/etc/udev/rules.d/98-${name}";
|
||||
text =
|
||||
let
|
||||
interfaces = wlanListDeviceFirst device wlanDeviceInterfaces.${device};
|
||||
curInterface = elemAt interfaces 0;
|
||||
newInterfaces = drop 1 interfaces;
|
||||
sysctl-value = tempaddrValues.${cfg.tempAddresses}.sysctl;
|
||||
in
|
||||
''
|
||||
# It is important to have that rule first as overwriting the NAME attribute also prevents the
|
||||
# next rules from matching.
|
||||
${flip (concatMapStringsSep "\n") (wlanListDeviceFirst device wlanDeviceInterfaces.${device}) (
|
||||
interface:
|
||||
''ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", ENV{INTERFACE}=="${interface._iName}", ${systemdAttrs interface._iName}, RUN+="${newInterfaceScript interface}"''
|
||||
)}
|
||||
|
||||
# Add the required, new WLAN interfaces to the default WLAN interface with the
|
||||
# persistent, default name as assigned by udev.
|
||||
ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", NAME=="${device}", ${systemdAttrs curInterface._iName}, RUN+="${
|
||||
curInterfaceScript device curInterface newInterfaces
|
||||
}"
|
||||
# Generate the same systemd events for both 'add' and 'move' udev events.
|
||||
ACTION=="move", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", NAME=="${device}", ${systemdAttrs curInterface._iName}
|
||||
# enable and prefer IPv6 privacy addresses by default
|
||||
ACTION=="add", SUBSYSTEM=="net", RUN+="${pkgs.bash}/bin/sh -c 'echo ${sysctl-value} > /proc/sys/net/ipv6/conf/$name/use_tempaddr'"
|
||||
'';
|
||||
})
|
||||
(pkgs.writeTextFile rec {
|
||||
name = "ipv6-privacy-extensions.rules";
|
||||
destination = "/etc/udev/rules.d/99-${name}";
|
||||
text = concatMapStrings (
|
||||
i:
|
||||
let
|
||||
opt = i.tempAddress;
|
||||
val = tempaddrValues.${opt}.sysctl;
|
||||
msg = tempaddrValues.${opt}.description;
|
||||
in
|
||||
''
|
||||
);
|
||||
}
|
||||
);
|
||||
# override to ${msg} for ${i.name}
|
||||
ACTION=="add", SUBSYSTEM=="net", NAME=="${i.name}", RUN+="${pkgs.procps}/bin/sysctl net.ipv6.conf.${
|
||||
replaceStrings [ "." ] [ "/" ] i.name
|
||||
}.use_tempaddr=${val}"
|
||||
''
|
||||
) (filter (i: i.tempAddress != cfg.tempAddresses) interfaces);
|
||||
})
|
||||
]
|
||||
++ lib.optional (cfg.wlanInterfaces != { }) (
|
||||
pkgs.writeTextFile {
|
||||
name = "99-zzz-40-wlanInterfaces.rules";
|
||||
destination = "/etc/udev/rules.d/99-zzz-40-wlanInterfaces.rules";
|
||||
text =
|
||||
let
|
||||
# Collect all interfaces that are defined for a device
|
||||
# as device:interface key:value pairs.
|
||||
wlanDeviceInterfaces =
|
||||
let
|
||||
allDevices = unique (mapAttrsToList (_: v: v.device) cfg.wlanInterfaces);
|
||||
interfacesOfDevice = d: filterAttrs (_: v: v.device == d) cfg.wlanInterfaces;
|
||||
in
|
||||
genAttrs allDevices (d: interfacesOfDevice d);
|
||||
|
||||
# Convert device:interface key:value pairs into a list, and if it exists,
|
||||
# place the interface which is named after the device at the beginning.
|
||||
wlanListDeviceFirst =
|
||||
device: interfaces:
|
||||
if hasAttr device interfaces then
|
||||
mapAttrsToList (n: v: v // { _iName = n; }) (filterAttrs (n: _: n == device) interfaces)
|
||||
++ mapAttrsToList (n: v: v // { _iName = n; }) (filterAttrs (n: _: n != device) interfaces)
|
||||
else
|
||||
mapAttrsToList (n: v: v // { _iName = n; }) interfaces;
|
||||
|
||||
# Udev script to execute for the default WLAN interface with the persistend udev name.
|
||||
# The script creates the required, new WLAN interfaces interfaces and configures the
|
||||
# existing, default interface.
|
||||
curInterfaceScript =
|
||||
device: current: new:
|
||||
pkgs.writeScript "udev-run-script-wlan-interfaces-${device}.sh" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
# Change the wireless phy device to a predictable name.
|
||||
${pkgs.iw}/bin/iw phy `${pkgs.coreutils}/bin/cat /sys/class/net/$INTERFACE/phy80211/name` set name ${device}
|
||||
|
||||
# Add new WLAN interfaces
|
||||
${flip concatMapStrings new (i: ''
|
||||
${pkgs.iw}/bin/iw phy ${device} interface add ${i._iName} type managed
|
||||
'')}
|
||||
|
||||
# Configure the current interface
|
||||
${pkgs.iw}/bin/iw dev ${device} set type ${current.type}
|
||||
${optionalString (
|
||||
current.type == "mesh" && current.meshID != null
|
||||
) "${pkgs.iw}/bin/iw dev ${device} set meshid ${current.meshID}"}
|
||||
${optionalString (
|
||||
current.type == "monitor" && current.flags != null
|
||||
) "${pkgs.iw}/bin/iw dev ${device} set monitor ${current.flags}"}
|
||||
${optionalString (
|
||||
current.type == "managed" && current.fourAddr != null
|
||||
) "${pkgs.iw}/bin/iw dev ${device} set 4addr ${if current.fourAddr then "on" else "off"}"}
|
||||
${optionalString (
|
||||
current.mac != null
|
||||
) "${pkgs.iproute2}/bin/ip link set dev ${device} address ${current.mac}"}
|
||||
'';
|
||||
|
||||
# Udev script to execute for a new WLAN interface. The script configures the new WLAN interface.
|
||||
newInterfaceScript =
|
||||
new:
|
||||
pkgs.writeScript "udev-run-script-wlan-interfaces-${new._iName}.sh" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
# Configure the new interface
|
||||
${pkgs.iw}/bin/iw dev ${new._iName} set type ${new.type}
|
||||
${optionalString (
|
||||
new.type == "mesh" && new.meshID != null
|
||||
) "${pkgs.iw}/bin/iw dev ${new._iName} set meshid ${new.meshID}"}
|
||||
${optionalString (
|
||||
new.type == "monitor" && new.flags != null
|
||||
) "${pkgs.iw}/bin/iw dev ${new._iName} set monitor ${new.flags}"}
|
||||
${optionalString (
|
||||
new.type == "managed" && new.fourAddr != null
|
||||
) "${pkgs.iw}/bin/iw dev ${new._iName} set 4addr ${if new.fourAddr then "on" else "off"}"}
|
||||
${optionalString (
|
||||
new.mac != null
|
||||
) "${pkgs.iproute2}/bin/ip link set dev ${new._iName} address ${new.mac}"}
|
||||
'';
|
||||
|
||||
# Udev attributes for systemd to name the device and to create a .device target.
|
||||
systemdAttrs =
|
||||
n:
|
||||
''NAME:="${n}", ENV{INTERFACE}="${n}", ENV{SYSTEMD_ALIAS}="/sys/subsystem/net/devices/${n}", TAG+="systemd"'';
|
||||
in
|
||||
flip (concatMapStringsSep "\n") (attrNames wlanDeviceInterfaces) (
|
||||
device:
|
||||
let
|
||||
interfaces = wlanListDeviceFirst device wlanDeviceInterfaces.${device};
|
||||
curInterface = elemAt interfaces 0;
|
||||
newInterfaces = drop 1 interfaces;
|
||||
in
|
||||
''
|
||||
# It is important to have that rule first as overwriting the NAME attribute also prevents the
|
||||
# next rules from matching.
|
||||
${flip (concatMapStringsSep "\n") (wlanListDeviceFirst device wlanDeviceInterfaces.${device}) (
|
||||
interface:
|
||||
''ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", ENV{INTERFACE}=="${interface._iName}", ${systemdAttrs interface._iName}, RUN+="${newInterfaceScript interface}"''
|
||||
)}
|
||||
|
||||
# Add the required, new WLAN interfaces to the default WLAN interface with the
|
||||
# persistent, default name as assigned by udev.
|
||||
ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", NAME=="${device}", ${systemdAttrs curInterface._iName}, RUN+="${
|
||||
curInterfaceScript device curInterface newInterfaces
|
||||
}"
|
||||
# Generate the same systemd events for both 'add' and 'move' udev events.
|
||||
ACTION=="move", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", NAME=="${device}", ${systemdAttrs curInterface._iName}
|
||||
''
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user