set default ipv6 address
This commit is contained in:
parent
277af5c2f9
commit
1b4efdb72f
@ -6,6 +6,7 @@ let
|
|||||||
netname = "retiolum";
|
netname = "retiolum";
|
||||||
cfg = config.networking.retiolum;
|
cfg = config.networking.retiolum;
|
||||||
hosts = ../../hosts;
|
hosts = ../../hosts;
|
||||||
|
genipv6 = import ./genipv6.nix { inherit lib; };
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
networking.retiolum.ipv4 = mkOption {
|
networking.retiolum.ipv4 = mkOption {
|
||||||
@ -17,6 +18,9 @@ in {
|
|||||||
};
|
};
|
||||||
networking.retiolum.ipv6 = mkOption {
|
networking.retiolum.ipv6 = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
default = (genipv6 "retiolum" "external" {
|
||||||
|
inherit (config.networking) hostName;
|
||||||
|
}).address;
|
||||||
description = ''
|
description = ''
|
||||||
own ipv6 address
|
own ipv6 address
|
||||||
'';
|
'';
|
||||||
|
198
modules/retiolum/genipv6.nix
Normal file
198
modules/retiolum/genipv6.nix
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
# stolen from krebs/stockholm
|
||||||
|
{ lib ? (import <nixpkgs> {}).lib }:
|
||||||
|
with lib;
|
||||||
|
let {
|
||||||
|
body = netname: subnetname: suffixSpec: rec {
|
||||||
|
address = let
|
||||||
|
suffix' = prependZeros suffixLength suffix;
|
||||||
|
in
|
||||||
|
normalize-ip6-addr
|
||||||
|
(checkAddress addressLength (joinAddress subnetPrefix suffix'));
|
||||||
|
addressCIDR = "${address}/${toString addressLength}";
|
||||||
|
addressLength = 128;
|
||||||
|
|
||||||
|
inherit netname;
|
||||||
|
netCIDR = "${netAddress}/${toString netPrefixLength}";
|
||||||
|
netAddress =
|
||||||
|
normalize-ip6-addr (appendZeros addressLength netPrefix);
|
||||||
|
netHash = toString {
|
||||||
|
retiolum = 0;
|
||||||
|
wiregrill = 1;
|
||||||
|
}.${netname};
|
||||||
|
netPrefix = "42:${netHash}";
|
||||||
|
netPrefixLength = {
|
||||||
|
retiolum = 32;
|
||||||
|
wiregrill = 32;
|
||||||
|
}.${netname};
|
||||||
|
|
||||||
|
inherit subnetname;
|
||||||
|
subnetCIDR = "${subnetAddress}/${toString subnetPrefixLength}";
|
||||||
|
subnetAddress =
|
||||||
|
normalize-ip6-addr (appendZeros addressLength subnetPrefix);
|
||||||
|
subnetHash = hashToLength 4 subnetname;
|
||||||
|
subnetPrefix = joinAddress netPrefix subnetHash;
|
||||||
|
subnetPrefixLength = netPrefixLength + 16;
|
||||||
|
|
||||||
|
suffix = getAttr (builtins.typeOf suffixSpec) {
|
||||||
|
set =
|
||||||
|
concatStringsSep
|
||||||
|
":"
|
||||||
|
(stringToGroupsOf
|
||||||
|
4
|
||||||
|
(hashToLength (suffixLength / 4) suffixSpec.hostName));
|
||||||
|
string = suffixSpec;
|
||||||
|
};
|
||||||
|
suffixLength = addressLength - subnetPrefixLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
appendZeros = n: s: let
|
||||||
|
n' = n / 16;
|
||||||
|
zeroCount = n' - length parsedaddr;
|
||||||
|
parsedaddr = parseAddress s;
|
||||||
|
in
|
||||||
|
formatAddress (parsedaddr ++ map (const "0") (range 1 zeroCount));
|
||||||
|
|
||||||
|
prependZeros = n: s: let
|
||||||
|
n' = n / 16;
|
||||||
|
zeroCount = n' - length parsedaddr;
|
||||||
|
parsedaddr = parseAddress s;
|
||||||
|
in
|
||||||
|
formatAddress (map (const "0") (range 1 zeroCount) ++ parsedaddr);
|
||||||
|
|
||||||
|
hasEmptyPrefix = xs: take 2 xs == ["" ""];
|
||||||
|
hasEmptySuffix = xs: takeLast 2 xs == ["" ""];
|
||||||
|
hasEmptyInfix = xs: any (x: x == "") (trimEmpty 2 xs);
|
||||||
|
|
||||||
|
hasEmptyGroup = xs:
|
||||||
|
any (p: p xs) [hasEmptyPrefix hasEmptyInfix hasEmptySuffix];
|
||||||
|
|
||||||
|
hashToLength = n: s: substring 0 n (builtins.hashString "sha256" s);
|
||||||
|
|
||||||
|
ltrimEmpty = n: xs: if hasEmptyPrefix xs then drop n xs else xs;
|
||||||
|
rtrimEmpty = n: xs: if hasEmptySuffix xs then dropLast n xs else xs;
|
||||||
|
trimEmpty = n: xs: rtrimEmpty n (ltrimEmpty n xs);
|
||||||
|
|
||||||
|
parseAddress = splitString ":";
|
||||||
|
formatAddress = concatStringsSep ":";
|
||||||
|
|
||||||
|
check = s: c: if !c then throw "${s}" else true;
|
||||||
|
|
||||||
|
checkAddress = maxaddrlen: addr: let
|
||||||
|
parsedaddr = parseAddress addr;
|
||||||
|
normalizedaddr = trimEmpty 1 parsedaddr;
|
||||||
|
in
|
||||||
|
assert (check "address malformed; lone leading colon: ${addr}" (
|
||||||
|
head parsedaddr == "" -> tail (take 2 parsedaddr) == ""
|
||||||
|
));
|
||||||
|
assert (check "address malformed; lone trailing colon ${addr}" (
|
||||||
|
last parsedaddr == "" -> head (takeLast 2 parsedaddr) == ""
|
||||||
|
));
|
||||||
|
assert (check "address malformed; too many successive colons: ${addr}" (
|
||||||
|
length (filter (x: x == "") normalizedaddr) > 1 -> addr == [""]
|
||||||
|
));
|
||||||
|
assert (check "address malformed: ${addr}" (
|
||||||
|
all (test "[0-9a-f]{0,4}") parsedaddr
|
||||||
|
));
|
||||||
|
assert (check "address is too long: ${addr}" (
|
||||||
|
length normalizedaddr * 16 <= maxaddrlen
|
||||||
|
));
|
||||||
|
addr;
|
||||||
|
|
||||||
|
joinAddress = prefix: suffix: let
|
||||||
|
parsedPrefix = parseAddress prefix;
|
||||||
|
parsedSuffix = parseAddress suffix;
|
||||||
|
normalizePrefix = rtrimEmpty 2 parsedPrefix;
|
||||||
|
normalizeSuffix = ltrimEmpty 2 parsedSuffix;
|
||||||
|
delimiter =
|
||||||
|
optional (length (normalizePrefix ++ normalizeSuffix) < 8 &&
|
||||||
|
(hasEmptySuffix parsedPrefix || hasEmptyPrefix parsedSuffix))
|
||||||
|
"";
|
||||||
|
in
|
||||||
|
formatAddress (normalizePrefix ++ delimiter ++ normalizeSuffix);
|
||||||
|
|
||||||
|
# https://tools.ietf.org/html/rfc5952
|
||||||
|
normalize-ip6-addr =
|
||||||
|
let
|
||||||
|
max-run-0 =
|
||||||
|
let
|
||||||
|
both = v: { off = v; pos = v; };
|
||||||
|
gt = a: b: a.pos - a.off > b.pos - b.off;
|
||||||
|
|
||||||
|
chkmax = ctx: {
|
||||||
|
cur = both (ctx.cur.pos + 1);
|
||||||
|
max = if gt ctx.cur ctx.max then ctx.cur else ctx.max;
|
||||||
|
};
|
||||||
|
|
||||||
|
incpos = ctx: recursiveUpdate ctx {
|
||||||
|
cur.pos = ctx.cur.pos + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
f = ctx: blk: (if blk == "0" then incpos else chkmax) ctx;
|
||||||
|
z = { cur = both 0; max = both 0; };
|
||||||
|
in
|
||||||
|
blks: (chkmax (foldl' f z blks)).max;
|
||||||
|
|
||||||
|
group-zeros = a:
|
||||||
|
let
|
||||||
|
blks = splitString ":" a;
|
||||||
|
max = max-run-0 blks;
|
||||||
|
lhs = take max.off blks;
|
||||||
|
rhs = drop max.pos blks;
|
||||||
|
in
|
||||||
|
if max.pos == 0
|
||||||
|
then a
|
||||||
|
else let
|
||||||
|
sep =
|
||||||
|
if 8 - (length lhs + length rhs) == 1
|
||||||
|
then ":0:"
|
||||||
|
else "::";
|
||||||
|
in
|
||||||
|
"${concatStringsSep ":" lhs}${sep}${concatStringsSep ":" rhs}";
|
||||||
|
|
||||||
|
drop-leading-zeros =
|
||||||
|
let
|
||||||
|
f = block:
|
||||||
|
let
|
||||||
|
res = builtins.match "0*(.+)" block;
|
||||||
|
in
|
||||||
|
if res == null
|
||||||
|
then block # empty block
|
||||||
|
else elemAt res 0;
|
||||||
|
in
|
||||||
|
a: concatStringsSep ":" (map f (splitString ":" a));
|
||||||
|
in
|
||||||
|
a:
|
||||||
|
toLower
|
||||||
|
(if test ".*::.*" a
|
||||||
|
then a
|
||||||
|
else group-zeros (drop-leading-zeros a));
|
||||||
|
|
||||||
|
# Split string into list of chunks where each chunk is at most n chars long.
|
||||||
|
# The leftmost chunk might shorter.
|
||||||
|
# Example: stringToGroupsOf "123456" -> ["12" "3456"]
|
||||||
|
stringToGroupsOf = n: s: let
|
||||||
|
acc =
|
||||||
|
foldl'
|
||||||
|
(acc: c: if stringLength acc.chunk < n then {
|
||||||
|
chunk = acc.chunk + c;
|
||||||
|
chunks = acc.chunks;
|
||||||
|
} else {
|
||||||
|
chunk = c;
|
||||||
|
chunks = acc.chunks ++ [acc.chunk];
|
||||||
|
})
|
||||||
|
{
|
||||||
|
chunk = "";
|
||||||
|
chunks = [];
|
||||||
|
}
|
||||||
|
(stringToCharacters s);
|
||||||
|
in
|
||||||
|
filter (x: x != []) ([acc.chunk] ++ acc.chunks);
|
||||||
|
|
||||||
|
|
||||||
|
takeLast = n: xs: reverseList (take n (reverseList xs));
|
||||||
|
|
||||||
|
test = re: x: isString x && testString re x;
|
||||||
|
|
||||||
|
testString = re: x: builtins.match re x != null;
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user