diff options
author | makefu <github@syntax-fehler.de> | 2018-12-12 17:53:38 +0100 |
---|---|---|
committer | makefu <github@syntax-fehler.de> | 2018-12-12 17:53:38 +0100 |
commit | 97aaf34c3311291ac47967ac1313e2d955b8228a (patch) | |
tree | d119d7ae674863f645e840e14bde0fbfe6f6a16c /lib/krebs/genipv6.nix | |
parent | 2e18ee84f02c0d7abcf936b1d39c42ab8e75825c (diff) | |
parent | 25cf61f6a74b69656d15f52021f25a6c2e4068e6 (diff) |
Merge remote-tracking branch 'lass/master' into HEAD
Diffstat (limited to 'lib/krebs/genipv6.nix')
-rw-r--r-- | lib/krebs/genipv6.nix | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/krebs/genipv6.nix b/lib/krebs/genipv6.nix new file mode 100644 index 000000000..af1df6d0e --- /dev/null +++ b/lib/krebs/genipv6.nix @@ -0,0 +1,107 @@ +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 = appendZeros netPrefixLength netPrefix; + netHash = toString { + retiolum = 0; + wirelum = 1; + }.${netname}; + netPrefix = "42:${netHash}"; + netPrefixLength = { + retiolum = 32; + wirelum = 32; + }.${netname}; + + inherit subnetname; + subnetCIDR = "${subnetAddress}/${toString subnetPrefixLength}"; + subnetAddress = appendZeros subnetPrefixLength subnetPrefix; + subnetHash = hashToLength 4 subnetname; + subnetPrefix = joinAddress netPrefix subnetHash; + subnetPrefixLength = netPrefixLength + 16; + + suffix = getAttr (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]; + + 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); +} |