liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

default.nix (2670B)


      1 {
      2   nftables,
      3   writeScript,
      4   lib,
      5 }:
      6 name: ruleset:
      7 let
      8   inherit (lib.strings)
      9     concatStringsSep
     10     splitString
     11     hasInfix
     12     substring
     13     optionalString
     14     ;
     15   inherit (lib.lists) groupBy;
     16   inherit (lib.attrsets) attrsToList mapAttrsToList;
     17   inherit (builtins) elemAt map head tail toString;
     18 
     19   indentLines =
     20     offset: lines:
     21     if lines == [ ] then
     22       ""
     23     else
     24       let
     25         line = head lines;
     26         isOpen = hasInfix "{" line;
     27         isClose = hasInfix "}" line;
     28         offset' = offset + (if isOpen then 4 else 0) + (if isClose then -4 else 0);
     29         padding = offset: substring 0 offset "                           ";
     30       in
     31       if (isClose && !isOpen) then
     32         (padding offset') + line + "\n" + indentLines offset' (tail lines)
     33       else
     34         (padding offset) + line + "\n" + indentLines offset' (tail lines);
     35 
     36   indent = text: indentLines 0 (splitString "\n" text);
     37 
     38   dochain =
     39     {
     40       name,
     41       type,
     42       family,
     43       rules,
     44       policy ? null,
     45       priority ? "filter",
     46       hook ? null,
     47     }:
     48     ''
     49       chain ${name} {
     50       ${if hook != null then "type ${type} hook ${hook} priority ${priority}; policy ${policy};" else ""}
     51       ${concatStringsSep "\n" rules}
     52       }
     53     '';
     54 
     55   doset =
     56     {
     57       name,
     58       type,
     59       elements ? [ ],
     60       extraText ? null,
     61       ...
     62     }:
     63     ''
     64       set ${name}  {
     65         type ${type}
     66         ${if elements != [ ] then "elements = { ${concatStringsSep ", " (builtins.trace elements elements)} }" else ""}
     67         ${optionalString (extraText != null) extraText}
     68       }
     69     '';
     70 
     71   domap =
     72     {
     73       name,
     74       type,
     75       elements ? [ ],
     76       extraText ? null,
     77       ...
     78     }:
     79       let
     80         colonize = v:
     81           let  ty = elemAt (attrsToList v) 0; in "${ty.name}: ${ty.value}";
     82       in ''
     83         map ${name}  {
     84           type ${colonize type}
     85           ${if elements != [ ] then "elements = { ${concatStringsSep ", " (mapAttrsToList (k: v : "${k}: ${toString v}") elements)} }" else ""}
     86           ${optionalString (extraText != null) extraText}
     87         }
     88       '';
     89 
     90   dochainorset =
     91     {
     92       kind ? "chain",
     93       ...
     94     }@params:
     95     {
     96       chain = dochain;
     97       set = doset;
     98       map = domap;
     99     }
    100     .${kind}
    101       params;
    102 
    103   dotable = family: chains: ''
    104     table ${family} table-${family} {
    105     ${concatStringsSep "\n" (map dochainorset chains)}
    106     }
    107   '';
    108   categorise =
    109     chains: groupBy ({ family, ... }: family) (mapAttrsToList (n: v: { name = n; } // v) chains);
    110 in
    111 writeScript name ''
    112   #!${nftables}/sbin/nft -f
    113 
    114   flush ruleset
    115 
    116   ${indent (concatStringsSep "\n" (mapAttrsToList dotable (categorise ruleset)))}
    117 ''