From 2a31d7e083a2887c37a9ac1ea471c36afab9f43d Mon Sep 17 00:00:00 2001 From: nukdokplex Date: Thu, 12 Jun 2025 13:39:34 +0500 Subject: [PATCH 1/4] lib.mkEUI64Suffix: init --- lib/default.nix | 3 +++ lib/network/default.nix | 52 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/lib/default.nix b/lib/default.nix index d45e6de0c33f..f6984e3f53ee 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -567,6 +567,9 @@ let inherit (self.versions) splitVersion ; + inherit (self.network.ipv6) + mkEUI64Suffix + ; } ); in diff --git a/lib/network/default.nix b/lib/network/default.nix index e0c583ee7506..14d801244966 100644 --- a/lib/network/default.nix +++ b/lib/network/default.nix @@ -1,6 +1,14 @@ { lib }: let inherit (import ./internal.nix { inherit lib; }) _ipv6; + inherit (lib.strings) match concatStringsSep toLower; + inherit (lib.trivial) + pipe + bitXor + fromHexString + toHexString + ; + inherit (lib.lists) elemAt; in { ipv6 = { @@ -45,5 +53,49 @@ in { inherit address prefixLength; }; + + /** + Converts a 48-bit MAC address into a EUI-64 IPv6 address suffix. + + # Example + + ```nix + mkEUI64Suffix "66:75:63:6B:20:75" + => "6475:63ff:fe6b:2075" + ``` + + # Type + + ``` + mkEUI64Suffix :: String -> String + ``` + + # Argumemts + + mac + : The MAC address (may contain these delimiters: `:`, `-` or `.` but it's not necessary) + */ + mkEUI64Suffix = + mac: + pipe mac [ + # match mac address + (match "^([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})$") + + # check if there are matches + (matches: if matches == null then throw ''"${mac}" doesn't meet MAC address criteria'' else matches) + + # transform to result hextets + (mac: [ + (toHexString (bitXor 512 (fromHexString ((elemAt mac 0) + (elemAt mac 1))))) + "${elemAt mac 2}ff" + "fe${elemAt mac 3}" + ((elemAt mac 4) + (elemAt mac 5)) + ]) + + # concat to result suffix + (concatStringsSep ":") + + toLower + ]; }; } From 7abe9e95ece8e6dfbdf8d5b6b951991813af5b06 Mon Sep 17 00:00:00 2001 From: nukdokplex Date: Tue, 9 Sep 2025 12:12:59 +0500 Subject: [PATCH 2/4] lib.network: add lib.mkEUI64Suffix tests to network.sh --- lib/tests/network.sh | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/tests/network.sh b/lib/tests/network.sh index 54ca476d2deb..b0c917b8b222 100755 --- a/lib/tests/network.sh +++ b/lib/tests/network.sh @@ -114,4 +114,42 @@ expectFailure '(internal._ipv6.split "/::/").prefixLength' "is not a valid IPv expectSuccess 'lib.network.ipv6.fromString "2001:DB8::ffff/64"' '{"address":"2001:db8:0:0:0:0:0:ffff","prefixLength":64}' expectSuccess 'lib.network.ipv6.fromString "1234:5678:90ab:cdef:fedc:ba09:8765:4321/44"' '{"address":"1234:5678:90ab:cdef:fedc:ba09:8765:4321","prefixLength":44}' +expectSuccess 'mkEUI64Suffix "00:11:22:AA:BB:CC"' '"211:22ff:feaa:bbcc"' +expectSuccess 'mkEUI64Suffix "00-11-22-AA-BB-CC"' '"211:22ff:feaa:bbcc"' +expectSuccess 'mkEUI64Suffix "00.11.22.AA.BB.CC"' '"211:22ff:feaa:bbcc"' +expectSuccess 'mkEUI64Suffix "00:11:22:aa:bb:cc"' '"211:22ff:feaa:bbcc"' +expectSuccess 'mkEUI64Suffix "00-11-22-aa-bb-cc"' '"211:22ff:feaa:bbcc"' +expectSuccess 'mkEUI64Suffix "00.11.22.aa.bb.cc"' '"211:22ff:feaa:bbcc"' + +expectSuccess 'mkEUI64Suffix "12:34:56:78:9A:bc"' '"1034:56ff:fe78:9abc"' +expectSuccess 'mkEUI64Suffix "123456789ABC"' '"1034:56ff:fe78:9abc"' + +expectSuccess 'mkEUI64Suffix "001122AABBCC"' '"211:22ff:feaa:bbcc"' +expectSuccess 'mkEUI64Suffix "001122aabbcc"' '"211:22ff:feaa:bbcc"' + +expectSuccess 'mkEUI64Suffix "ff-ff-ff-ff-ff-ff"' '"fdff:ffff:feff:ffff"' +expectSuccess 'mkEUI64Suffix "ffffffffffff"' '"fdff:ffff:feff:ffff"' +expectSuccess 'mkEUI64Suffix "00.00.00.00.00.00"' '"200:00ff:fe00:0000"' +expectSuccess 'mkEUI64Suffix "000000000000"' '"200:00ff:fe00:0000"' + +expectFailure 'mkEUI64Suffix "123456789AB"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "123456789A"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "123456789"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "12345678"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "1234567"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "123456"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "12345"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "1234"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "123"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "12"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "1"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix ""' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "------------"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "............"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "::::::::::::"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "1:2:3:4:5:6"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "0.0.0.0.0.0"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "00:11:-2:AA:BB:CC"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "00:-11:22:AA:BB:CC"' "doesn't meet MAC address criteria" + echo >&2 tests ok From 68253aae9bd742cff45706ab66e470ab7502b728 Mon Sep 17 00:00:00 2001 From: nukdokplex Date: Wed, 10 Sep 2025 13:31:23 +0500 Subject: [PATCH 3/4] lib.mkEUI64Suffix: bring @hsjobeki suggestions renamed `mac` to `octets` in hextets combining step for better var naming; rephrased error message to provide a hint of expected format; replaced `Arguments` with `Inputs` in docstring; added more test cases for invalid hex digits; added comments in hextets combining step; --- lib/network/default.nix | 25 ++++++++++++++++------- lib/tests/network.sh | 44 +++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 26 deletions(-) diff --git a/lib/network/default.nix b/lib/network/default.nix index 14d801244966..54934b138db0 100644 --- a/lib/network/default.nix +++ b/lib/network/default.nix @@ -70,7 +70,7 @@ in mkEUI64Suffix :: String -> String ``` - # Argumemts + # Inputs mac : The MAC address (may contain these delimiters: `:`, `-` or `.` but it's not necessary) @@ -82,14 +82,25 @@ in (match "^([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})[-:.]?([0-9A-Fa-f]{2})$") # check if there are matches - (matches: if matches == null then throw ''"${mac}" doesn't meet MAC address criteria'' else matches) + ( + matches: + if matches == null then + throw ''"${mac}" is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)'' + else + matches + ) # transform to result hextets - (mac: [ - (toHexString (bitXor 512 (fromHexString ((elemAt mac 0) + (elemAt mac 1))))) - "${elemAt mac 2}ff" - "fe${elemAt mac 3}" - ((elemAt mac 4) + (elemAt mac 5)) + (octets: [ + # combine 1st and 2nd octets into first hextet, flip U/L bit, 512 = 0x200 + (toHexString (bitXor 512 (fromHexString ((elemAt octets 0) + (elemAt octets 1))))) + + # combine 3rd and 4th octets, combine them, insert fffe pattern in between to get next two hextets + "${elemAt octets 2}ff" + "fe${elemAt octets 3}" + + # combine 5th and 6th octets into the last hextet + ((elemAt octets 4) + (elemAt octets 5)) ]) # concat to result suffix diff --git a/lib/tests/network.sh b/lib/tests/network.sh index b0c917b8b222..e873ac851fe8 100755 --- a/lib/tests/network.sh +++ b/lib/tests/network.sh @@ -132,24 +132,30 @@ expectSuccess 'mkEUI64Suffix "ffffffffffff"' '"fdff:ffff:feff:ffff"' expectSuccess 'mkEUI64Suffix "00.00.00.00.00.00"' '"200:00ff:fe00:0000"' expectSuccess 'mkEUI64Suffix "000000000000"' '"200:00ff:fe00:0000"' -expectFailure 'mkEUI64Suffix "123456789AB"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "123456789A"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "123456789"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "12345678"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "1234567"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "123456"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "12345"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "1234"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "123"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "12"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "1"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix ""' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "------------"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "............"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "::::::::::::"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "1:2:3:4:5:6"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "0.0.0.0.0.0"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "00:11:-2:AA:BB:CC"' "doesn't meet MAC address criteria" -expectFailure 'mkEUI64Suffix "00:-11:22:AA:BB:CC"' "doesn't meet MAC address criteria" +expectFailure 'mkEUI64Suffix "123456789AB"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "123456789A"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "123456789"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "12345678"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "1234567"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "123456"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "12345"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "1234"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "123"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "12"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "1"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix ""' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "------------"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "............"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "::::::::::::"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "1:2:3:4:5:6"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "0.0.0.0.0.0"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "00:11:-2:AA:BB:CC"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "00:-11:22:AA:BB:CC"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "ab:cd:ef:g0:12:34' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "AB:CD:EF:G0:12:34' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "ab:cd:ef:gh:jk:lm' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "AB:CD:EF:GH:JK:LM' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "01:23:3a:bc:de:fg"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "01:23:3A:BC:DE:FG"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" echo >&2 tests ok From d24f103572bc7dd16f4ffa844cc6b315be603656 Mon Sep 17 00:00:00 2001 From: nukdokplex Date: Thu, 11 Sep 2025 00:01:53 +0500 Subject: [PATCH 4/4] lib.mkEUI64Suffix: fix syntax errors and tests --- lib/network/default.nix | 2 +- lib/tests/network.sh | 50 ++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/network/default.nix b/lib/network/default.nix index 54934b138db0..822abc9abf53 100644 --- a/lib/network/default.nix +++ b/lib/network/default.nix @@ -85,7 +85,7 @@ in ( matches: if matches == null then - throw ''"${mac}" is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)'' + throw ''"${mac}" is not a valid MAC address (expected 6 octets of hex digits)'' else matches ) diff --git a/lib/tests/network.sh b/lib/tests/network.sh index e873ac851fe8..543a75c0f565 100755 --- a/lib/tests/network.sh +++ b/lib/tests/network.sh @@ -132,30 +132,30 @@ expectSuccess 'mkEUI64Suffix "ffffffffffff"' '"fdff:ffff:feff:ffff"' expectSuccess 'mkEUI64Suffix "00.00.00.00.00.00"' '"200:00ff:fe00:0000"' expectSuccess 'mkEUI64Suffix "000000000000"' '"200:00ff:fe00:0000"' -expectFailure 'mkEUI64Suffix "123456789AB"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "123456789A"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "123456789"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "12345678"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "1234567"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "123456"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "12345"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "1234"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "123"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "12"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "1"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix ""' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "------------"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "............"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "::::::::::::"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "1:2:3:4:5:6"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "0.0.0.0.0.0"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "00:11:-2:AA:BB:CC"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "00:-11:22:AA:BB:CC"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "ab:cd:ef:g0:12:34' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "AB:CD:EF:G0:12:34' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "ab:cd:ef:gh:jk:lm' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "AB:CD:EF:GH:JK:LM' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "01:23:3a:bc:de:fg"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" -expectFailure 'mkEUI64Suffix "01:23:3A:BC:DE:FG"' "is not a valid MAC address (expected 6 octets of hex digits with optional delimiters)" +expectFailure 'mkEUI64Suffix "123456789AB"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "123456789A"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "123456789"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "12345678"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "1234567"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "123456"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "12345"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "1234"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "123"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "12"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "1"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix ""' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "------------"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "............"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "::::::::::::"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "1:2:3:4:5:6"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "0.0.0.0.0.0"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "00:11:-2:AA:BB:CC"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "00:-11:22:AA:BB:CC"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "ab:cd:ef:g0:12:34"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "AB:CD:EF:G0:12:34"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "ab:cd:ef:gh:jk:lm"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "AB:CD:EF:GH:JK:LM"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "01:23:3a:bc:de:fg"' "is not a valid MAC address \(expected 6 octets of hex digits\)" +expectFailure 'mkEUI64Suffix "01:23:3A:BC:DE:FG"' "is not a valid MAC address \(expected 6 octets of hex digits\)" echo >&2 tests ok