From 708d1327308f84e690009d822fffcb0b82feb76b Mon Sep 17 00:00:00 2001 From: Lumpiasty Date: Sat, 13 Jun 2026 02:45:21 +0200 Subject: [PATCH] Enable 464CLAT on acer --- hosts/acer.nix | 3 + modules/default.nix | 1 + modules/system/ipv6-mostly.nix | 27 ++ overlays/pkgs.nix | 7 + .../clat-skip-deprecated-prefixes.patch | 14 + .../fix-install-paths.patch | 16 ++ pkgs/networkmanager-dev/fix-paths.patch | 48 ++++ pkgs/networkmanager-dev/package.nix | 241 ++++++++++++++++++ 8 files changed, 357 insertions(+) create mode 100644 modules/system/ipv6-mostly.nix create mode 100644 pkgs/networkmanager-dev/clat-skip-deprecated-prefixes.patch create mode 100644 pkgs/networkmanager-dev/fix-install-paths.patch create mode 100644 pkgs/networkmanager-dev/fix-paths.patch create mode 100644 pkgs/networkmanager-dev/package.nix diff --git a/hosts/acer.nix b/hosts/acer.nix index 04950ff..53930d1 100644 --- a/hosts/acer.nix +++ b/hosts/acer.nix @@ -89,6 +89,7 @@ rec { laptop = true; gaming = true; enableTailscale = true; + ipv6Mostly = true; }; virtualisation.vmVariant = { @@ -158,6 +159,8 @@ rec { }; }; + programs.wireshark.enable = true; + # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions diff --git a/modules/default.nix b/modules/default.nix index a4036ec..5f874a7 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -15,6 +15,7 @@ system/users.nix system/ssh.nix system/gaming.nix + system/ipv6-mostly.nix system/nix.nix system/zfs.nix diff --git a/modules/system/ipv6-mostly.nix b/modules/system/ipv6-mostly.nix new file mode 100644 index 0000000..d72a6f3 --- /dev/null +++ b/modules/system/ipv6-mostly.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: + +# IPv6-mostly support via NetworkManager (RFC 8925 + RFC 6877 / 464XLAT). +# Requires NetworkManager >= 1.58 (pkgs.networkmanager-clat in practice). +# Sets ipv4.clat=auto and ipv4.dhcp-ipv6-only-preferred=auto as connection +# defaults, mirroring the Fedora 45 change: +# https://fedoraproject.org/wiki/Changes/IPv6-Mostly_Support_In_NetworkManager +{ + options.lumpiasty.ipv6Mostly = lib.mkEnableOption "Enable IPv6-mostly (RFC 8925 + CLAT/464XLAT) support in NetworkManager"; + + config = lib.mkIf config.lumpiasty.ipv6Mostly { + # Use the patched NM build with CLAT support, without replacing pkgs.networkmanager + # globally (which would cascade rebuilds across the entire system closure). + networking.networkmanager.package = pkgs.networkmanager-clat; + + # Drop a conf.d snippet that sets connection-level defaults. + # NM reads /etc/NetworkManager/conf.d/*.conf in addition to NetworkManager.conf. + environment.etc."NetworkManager/conf.d/99-ipv6-mostly.conf".text = '' + # IPv6-mostly: automatically enable CLAT (464XLAT) and DHCPv4 option 108 + # when the network advertises PREF64 and/or option 108 (RFC 8925). + # On networks without these, behaviour is unchanged (native IPv4 proceeds). + [connection-defaults] + ipv4.clat=auto + ipv4.dhcp-ipv6-only-preferred=auto + ''; + }; +} diff --git a/overlays/pkgs.nix b/overlays/pkgs.nix index 2bba112..5bd8538 100644 --- a/overlays/pkgs.nix +++ b/overlays/pkgs.nix @@ -10,5 +10,12 @@ openldap = prev.openldap.overrideAttrs { doCheck = !prev.stdenv.hostPlatform.isi686; }; + # NetworkManager 1.57.4-dev: adds ipv4.clat (CLAT/464XLAT) needed for IPv6-mostly. + # Used via networking.networkmanager.package — does not replace pkgs.networkmanager globally. + # Remove once nixpkgs ships networkmanager >= 1.58 stable. + networkmanager-clat = assert final.lib.assertMsg + (final.lib.versionOlder prev.networkmanager.version "1.58") + "nixpkgs now ships NetworkManager ${prev.networkmanager.version} >= 1.58 — remove the override in overlays/pkgs.nix and pkgs/networkmanager-dev/"; + prev.callPackage ../pkgs/networkmanager-dev/package.nix { }; }) ] diff --git a/pkgs/networkmanager-dev/clat-skip-deprecated-prefixes.patch b/pkgs/networkmanager-dev/clat-skip-deprecated-prefixes.patch new file mode 100644 index 0000000..57d0e93 --- /dev/null +++ b/pkgs/networkmanager-dev/clat-skip-deprecated-prefixes.patch @@ -0,0 +1,14 @@ +--- a/src/core/nm-l3cfg.c 2026-06-13 01:43:36.576149959 +0200 ++++ b/src/core/nm-l3cfg.c 2026-06-13 01:43:46.979332451 +0200 +@@ -4261,6 +4261,11 @@ + * draft-ietf-v6ops-claton-14 Section 7 */ + nm_l3_config_data_iter_ip6_address_for_each (&iter, l3cd, &ip6_entry) { + if (ip6_entry->addr_source == NM_IP_CONFIG_SOURCE_NDISC && ip6_entry->plen == 64) { ++ /* RFC 6724 rule 3: avoid deprecated addresses. Skip prefixes ++ * advertised with a zero preferred lifetime, they are being ++ * phased out and must not be used for new communication. */ ++ if (ip6_entry->lifetime != 0 && ip6_entry->preferred == 0) ++ continue; + if (_clat_prefix_is_better(best_prefix, ip6_entry, &pref64)) + best_prefix = ip6_entry; + } diff --git a/pkgs/networkmanager-dev/fix-install-paths.patch b/pkgs/networkmanager-dev/fix-install-paths.patch new file mode 100644 index 0000000..6b5f581 --- /dev/null +++ b/pkgs/networkmanager-dev/fix-install-paths.patch @@ -0,0 +1,16 @@ +diff --git a/meson.build b/meson.build +index 61c025b9d7..d2ae60da34 100644 +--- a/meson.build ++++ b/meson.build +@@ -1025,9 +1025,9 @@ meson.add_install_script( + join_paths('tools', 'meson-post-install.sh'), + nm_datadir, + nm_bindir, +- nm_pkgconfdir, ++ nm_prefix + nm_pkgconfdir, + nm_pkglibdir, +- nm_pkgstatedir, ++ nm_prefix + nm_pkgstatedir, + nm_mandir, + nm_sysconfdir, + enable_docs ? '1' : '0', diff --git a/pkgs/networkmanager-dev/fix-paths.patch b/pkgs/networkmanager-dev/fix-paths.patch new file mode 100644 index 0000000..228f06c --- /dev/null +++ b/pkgs/networkmanager-dev/fix-paths.patch @@ -0,0 +1,48 @@ +diff --git a/data/84-nm-drivers.rules b/data/84-nm-drivers.rules +index 148acade5c..6395fbfbe5 100644 +--- a/data/84-nm-drivers.rules ++++ b/data/84-nm-drivers.rules +@@ -7,6 +7,6 @@ ACTION!="add|change|move", GOTO="nm_drivers_end" + # Determine ID_NET_DRIVER if there's no ID_NET_DRIVER or DRIVERS (old udev?) + ENV{ID_NET_DRIVER}=="?*", GOTO="nm_drivers_end" + DRIVERS=="?*", GOTO="nm_drivers_end" +-PROGRAM="/bin/sh -c '/usr/sbin/ethtool -i $$1 |/usr/bin/sed -n s/^driver:\ //p' -- $env{INTERFACE}", ENV{ID_NET_DRIVER}="%c" ++PROGRAM="@runtimeShell@ -c '@ethtool@/bin/ethtool -i $$1 |@gnused@/bin/sed -n s/^driver:\ //p' -- $env{INTERFACE}", ENV{ID_NET_DRIVER}="%c" + + LABEL="nm_drivers_end" +diff --git a/src/libnmc-base/nm-vpn-helpers.c b/src/libnmc-base/nm-vpn-helpers.c +index cbe76f5f1c..6ec684f9fe 100644 +--- a/src/libnmc-base/nm-vpn-helpers.c ++++ b/src/libnmc-base/nm-vpn-helpers.c +@@ -284,15 +284,6 @@ nm_vpn_openconnect_authenticate_helper(NMSettingVpn *s_vpn, GPtrArray *secrets, + const char *const *iter; + const char *path; + const char *opt; +- const char *const DEFAULT_PATHS[] = { +- "/sbin/", +- "/usr/sbin/", +- "/usr/local/sbin/", +- "/bin/", +- "/usr/bin/", +- "/usr/local/bin/", +- NULL, +- }; + const char *oc_argv[(12 + 2 * G_N_ELEMENTS(oc_property_args))]; + const char *gw; + int port; +@@ -311,13 +302,8 @@ nm_vpn_openconnect_authenticate_helper(NMSettingVpn *s_vpn, GPtrArray *secrets, + + port = extract_url_port(gw); + +- path = nm_utils_file_search_in_paths("openconnect", +- "/usr/sbin/openconnect", +- DEFAULT_PATHS, +- G_FILE_TEST_IS_EXECUTABLE, +- NULL, +- NULL, +- error); ++ path = g_find_program_in_path("openconnect"); ++ + if (!path) + return FALSE; + diff --git a/pkgs/networkmanager-dev/package.nix b/pkgs/networkmanager-dev/package.nix new file mode 100644 index 0000000..f6a24c5 --- /dev/null +++ b/pkgs/networkmanager-dev/package.nix @@ -0,0 +1,241 @@ +# NetworkManager 1.57.4-dev — development snapshot with ipv4.clat (CLAT/464XLAT) support. +# Required for IPv6-mostly / RFC 8925 + RFC 6877 on NixOS until 1.58 stable lands in nixpkgs. +# Remove this override once nixpkgs ships networkmanager >= 1.58. +{ + lib, + stdenv, + fetchurl, + replaceVars, + gettext, + pkg-config, + dbus, + gitUpdater, + libuuid, + polkit, + gnutls, + ppp, + dhcpcd, + iptables, + nftables, + python3, + vala, + libgcrypt, + dnsmasq, + bluez5, + readline, + libselinux, + audit, + gobject-introspection, + perl, + modemmanager, + openresolv, + libndp, + newt, + ethtool, + gnused, + iputils, + kmod, + jansson, + elfutils, + gtk-doc, + libxslt, + docbook_xsl, + docbook_xml_dtd_412, + docbook_xml_dtd_42, + docbook_xml_dtd_43, + curl, + meson, + mesonEmulatorHook, + ninja, + bpftools, + llvmPackages, + libbpf, + libnvme, + libpsl, + mobile-broadband-provider-info, + runtimeShell, + buildPackages, + nixosTests, + systemd, + udev, + udevCheckHook, + withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd, + withNbft ? false, +}: + +let + pythonForDocs = python3.pythonOnBuildForHost.withPackages (pkgs: with pkgs; [ pygobject3 ]); +in +stdenv.mkDerivation (finalAttrs: { + pname = "networkmanager"; + version = "1.57.4-dev"; + + src = fetchurl { + # Use the stable release tarball (not the git archive) — GitLab git archives are not content-stable. + url = "https://gitlab.freedesktop.org/api/v4/projects/411/packages/generic/NetworkManager/${finalAttrs.version}/NetworkManager-${finalAttrs.version}.tar.xz"; + hash = "sha256-ThYPO/0YsmFSc2Qol1ZAoQb1qdtjPRg+rvxpUzKe0sA="; + }; + + outputs = [ + "out" + "dev" + "devdoc" + "man" + "doc" + ]; + + mesonFlags = [ + "--sysconfdir=/etc" + "--localstatedir=/var" + (lib.mesonOption "systemdsystemunitdir" ( + if withSystemd then "${placeholder "out"}/etc/systemd/system" else "no" + )) + "-Dudev_dir=${placeholder "out"}/lib/udev" + "-Ddbus_conf_dir=${placeholder "out"}/share/dbus-1/system.d" + "-Dkernel_firmware_dir=/run/current-system/firmware" + + "-Dmodprobe=${kmod}/bin/modprobe" + (lib.mesonOption "session_tracking" (if withSystemd then "systemd" else "no")) + (lib.mesonBool "systemd_journal" withSystemd) + "-Dlibaudit=yes-disabled-by-default" + "-Dpolkit_agent_helper_1=/run/wrappers/bin/polkit-agent-helper-1" + + "-Diwd=true" + "-Dpppd=${ppp}/bin/pppd" + "-Diptables=${iptables}/bin/iptables" + "-Dnft=${nftables}/bin/nft" + "-Dmodem_manager=true" + "-Dnmtui=true" + "-Ddnsmasq=${dnsmasq}/bin/dnsmasq" + "-Dqt=false" + (lib.mesonBool "nbft" withNbft) + + "-Dresolvconf=${openresolv}/bin/resolvconf" + "-Ddhcpcd=${dhcpcd}/bin/dhcpcd" + + "-Ddocs=${lib.boolToString (stdenv.buildPlatform == stdenv.hostPlatform)}" + "-Dman=${lib.boolToString (stdenv.buildPlatform == stdenv.hostPlatform)}" + "-Dtests=no" + "-Dcrypto=gnutls" + "-Dmobile_broadband_provider_info_database=${mobile-broadband-provider-info}/share/mobile-broadband-provider-info/serviceproviders.xml" + ]; + + patches = [ + (replaceVars ./fix-paths.patch { + inherit + ethtool + gnused + ; + inherit runtimeShell; + }) + ./fix-install-paths.patch + # CLAT prefix selection ignores RFC 6724 rule 3 (avoid deprecated addresses): + # a deprecated prefix (preferred lifetime 0) can win the selection and break + # CLAT with an unroutable source address. Report upstream, then drop this. + ./clat-skip-deprecated-prefixes.patch + ]; + + buildInputs = [ + (if withSystemd then systemd else udev) + libselinux + audit + libpsl + libuuid + polkit + ppp + libndp + curl + mobile-broadband-provider-info + bluez5 + dnsmasq + modemmanager + readline + newt + jansson + dbus + libbpf + ] + ++ lib.optionals withNbft [ + libnvme + ]; + + propagatedBuildInputs = [ + gnutls + libgcrypt + ]; + + # Disable hardening flags that break clang -target bpf (CLAT BPF compilation). + # Same workaround as nixpkgs systemd package. + hardeningDisable = [ "zerocallusedregs" "shadowstack" "pacret" ]; + + nativeBuildInputs = [ + meson + ninja + gettext + pkg-config + # BPF compiler for CLAT/464XLAT — must use buildPackages to avoid splicing issues + bpftools + buildPackages.llvmPackages.clang + buildPackages.llvmPackages.libllvm + vala + gobject-introspection + perl + elfutils + gtk-doc + libxslt + docbook_xsl + docbook_xml_dtd_412 + docbook_xml_dtd_42 + docbook_xml_dtd_43 + pythonForDocs + udevCheckHook + ] + ++ lib.optionals (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) [ + mesonEmulatorHook + ]; + + doCheck = false; + + postPatch = '' + patchShebangs ./tools + patchShebangs libnm/generate-setting-docs.py + + # TODO: submit upstream + substituteInPlace meson.build \ + --replace "'vala', req" "'vala', native: false, req" + '' + + lib.optionalString withSystemd '' + substituteInPlace data/NetworkManager.service.in \ + --replace-fail /usr/bin/busctl ${systemd}/bin/busctl + ''; + + preBuild = '' + mkdir -p ${placeholder "out"}/lib + ln -s $PWD/src/libnm-client-impl/libnm.so.0 ${placeholder "out"}/lib/libnm.so.0 + ''; + + postFixup = lib.optionalString (stdenv.buildPlatform != stdenv.hostPlatform) '' + cp -r ${buildPackages.networkmanager.devdoc} $devdoc + cp -r ${buildPackages.networkmanager.man} $man + ''; + + doInstallCheck = true; + + passthru = { + tests = { + inherit (nixosTests.networking) networkmanager; + }; + }; + + meta = { + homepage = "https://networkmanager.dev"; + description = "Network configuration and management tool (1.57.4-dev with CLAT/ipv6-mostly support)"; + license = lib.licenses.gpl2Plus; + maintainers = with lib.maintainers; [ obadz ]; + teams = [ lib.teams.freedesktop ]; + platforms = lib.platforms.linux; + badPlatforms = [ + lib.systems.inspect.platformPatterns.isStatic + ]; + }; +})