summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/default.nix44
-rw-r--r--lib/krebs/default.nix3
-rw-r--r--lib/krebs/genipv6.nix109
-rw-r--r--lib/types.nix26
4 files changed, 177 insertions, 5 deletions
diff --git a/lib/default.nix b/lib/default.nix
index 348d47e8..347830e8 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -5,6 +5,7 @@ let
evalSource = import ./eval-source.nix;
git = import ./git.nix { inherit lib; };
+ krebs = import ./krebs lib;
krops = import ../submodules/krops/lib;
shell = import ./shell.nix { inherit lib; };
types = nixpkgs-lib.types // import ./types.nix { inherit lib; };
@@ -28,8 +29,6 @@ let
listToAttrs (map (name: nameValuePair name set.${name})
(filter (flip hasAttr set) names));
- setAttr = name: value: set: set // { ${name} = value; };
-
test = re: x: isString x && testString re x;
testString = re: x: match re x != null;
@@ -94,7 +93,13 @@ let
in
if max.pos == 0
then a
- else "${concatStringsSep ":" lhs}::${concatStringsSep ":" rhs}";
+ else let
+ sep =
+ if 8 - (length lhs + length rhs) == 1
+ then ":0:"
+ else "::";
+ in
+ "${concatStringsSep ":" lhs}${sep}${concatStringsSep ":" rhs}";
drop-leading-zeros =
let
@@ -108,7 +113,38 @@ let
in
a: concatStringsSep ":" (map f (splitString ":" a));
in
- a: toLower (group-zeros (drop-leading-zeros a));
+ a:
+ toLower
+ (if test ".*::.*" a
+ then a
+ else group-zeros (drop-leading-zeros a));
+
+ hashToLength = n: s: substring 0 n (hashString "sha256" s);
+
+ dropLast = n: xs: reverseList (drop n (reverseList xs));
+ takeLast = n: xs: reverseList (take n (reverseList xs));
+
+ # 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);
+
};
in
diff --git a/lib/krebs/default.nix b/lib/krebs/default.nix
new file mode 100644
index 00000000..c9d9bef6
--- /dev/null
+++ b/lib/krebs/default.nix
@@ -0,0 +1,3 @@
+lib:
+with lib;
+mapNixDir (flip import lib) ./.
diff --git a/lib/krebs/genipv6.nix b/lib/krebs/genipv6.nix
new file mode 100644
index 00000000..22a23fce
--- /dev/null
+++ b/lib/krebs/genipv6.nix
@@ -0,0 +1,109 @@
+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 (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);
+}
diff --git a/lib/types.nix b/lib/types.nix
index 01685330..17c1688f 100644
--- a/lib/types.nix
+++ b/lib/types.nix
@@ -19,7 +19,7 @@ rec {
default = config._module.args.name;
};
cores = mkOption {
- type = positive;
+ type = uint;
};
nets = mkOption {
type = attrsOf net;
@@ -192,6 +192,28 @@ rec {
}));
default = null;
};
+ wireguard = mkOption {
+ type = nullOr (submodule ({ config, ... }: {
+ options = {
+ port = mkOption {
+ type = int;
+ description = "tinc port to use to connect to host";
+ default = 51820;
+ };
+ pubkey = mkOption {
+ type = wireguard-pubkey;
+ };
+ subnets = mkOption {
+ type = listOf cidr;
+ description = ''
+ wireguard subnets,
+ this defines how routing behaves for hosts that can't reach each other.
+ '';
+ default = [];
+ };
+ };
+ }));
+ };
};
});
@@ -548,4 +570,6 @@ rec {
check = filename.check;
merge = mergeOneOption;
};
+
+ wireguard-pubkey = str;
}