lib.krebs.genipv6: init
This commit is contained in:
parent
8ce6ab8401
commit
24c9ea126b
92
lib/krebs/genipv6.nix
Normal file
92
lib/krebs/genipv6.nix
Normal file
@ -0,0 +1,92 @@
|
||||
lib:
|
||||
with lib;
|
||||
let {
|
||||
body = netname: subnetname: suffix: rec {
|
||||
address = let
|
||||
suffix' =
|
||||
if hasEmptyGroup (parseAddress suffix)
|
||||
then suffix
|
||||
else joinAddress "::" suffix;
|
||||
in
|
||||
checkAddress addressLength (joinAddress subnetPrefix suffix');
|
||||
addressCIDR = "${address}/${toString addressLength}";
|
||||
addressLength = 128;
|
||||
|
||||
inherit netname;
|
||||
netCIDR = "${netAddress}/${toString netPrefixLength}";
|
||||
netAddress = joinAddress netPrefix "::";
|
||||
netHash = toString {
|
||||
retiolum = 0;
|
||||
wirelum = 1;
|
||||
}.${netname};
|
||||
netPrefix = "42:${netHash}";
|
||||
netPrefixLength = {
|
||||
retiolum = 32;
|
||||
wirelum = 32;
|
||||
}.${netname};
|
||||
|
||||
inherit subnetname;
|
||||
subnetCIDR = "${subnetAddress}/${toString subnetPrefixLength}";
|
||||
subnetAddress = joinAddress subnetPrefix "::";
|
||||
subnetHash = hash subnetname;
|
||||
subnetPrefix = joinAddress netPrefix subnetHash;
|
||||
subnetPrefixLength = netPrefixLength + 16;
|
||||
|
||||
inherit suffix;
|
||||
suffixLength = addressLength - subnetPrefixLength;
|
||||
};
|
||||
|
||||
hash = s: head (match "0*(.*)" (substring 0 4 (hashString "sha256" s)));
|
||||
|
||||
dropLast = n: xs: reverseList (drop n (reverseList xs));
|
||||
takeLast = n: xs: reverseList (take n (reverseList xs));
|
||||
|
||||
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];
|
||||
|
||||
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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user