Skip to content
Snippets Groups Projects
ip-util.nix 3.93 KiB
Newer Older
  • Learn to ignore specific revisions
  • # Thank you: https://gist.github.com/petabyteboy/558ffddb9aeb24e1eab2d5d6d021b5d7
    
    with import <nixpkgs/lib>;
    
    rec {
      # FIXME: add case for negative numbers
      pow = base: exponent: if exponent == 0 then 1 else fold (
        x: y: y * base
      ) base (
        range 2 exponent
      );
    
      fromHexString = hex: foldl (
        x: y: 16 * x + (
          (
            listToAttrs (
              map (
                x: nameValuePair (
                  toString x
                ) x
              ) (
                range 0 9
              )
            ) // {
              "a" = 10;
              "b" = 11;
              "c" = 12;
              "d" = 13;
              "e" = 14;
              "f" = 15;
            }
          ).${y}
        )
      ) 0 (
        stringToCharacters (
          removePrefix "0x" (
            hex
          )
        )
      );
    
      ipv4 = rec {
    
        decode = address: foldl (
          x: y: 256 * x + y
        ) 0 (
          map toInt (
            splitString "." address
          )
        );
    
        encode = num: concatStringsSep "." (
          map (
            x: toString (mod (num / x) 256)
          ) (
            reverseList (
              genList (
                x: pow 2 (x * 8)
              ) 4
            )
          )
        );
    
        netmask = prefixLength: (
          foldl (
            x: y: 2 * x + 1
          ) 0 (
            range 1 prefixLength
          )
        ) * (
          pow 2 (
            32 - prefixLength
          )
        );
    
        reverseZone = net: (
          concatStringsSep "." (
            reverseList (
              splitString "." net
            )
          )
        ) + ".in-addr.arpa";
    
        eachAddress = net: prefixLength: genList (
          x: decode (
            x + (
              decode net
            )
          )
        ) (
          pow 2 (
            32 - prefixLength
          )
        );
    
        networkOf = address: prefixLength: encode (
          bitAnd (
            decode address
          ) (
            netmask prefixLength
          )
        );
    
        isInNetwork = net: address: networkOf address == net;
    
        /* nixos-specific stuff */
    
        findOwnAddress = config: net: head (
          filter (
            isInNetwork net
          ) (
            configuredAddresses config
          )
        );
    
        configuredAddresses = config: concatLists (
          mapAttrsToList (
            name: iface: iface.ipv4.addresses
          ) config.networking.interfaces
        );
    
      };
    
      ipv6 = rec {
    
        expand = address: (
          replaceStrings ["::"] [(
            concatStringsSep "0" (
              genList (x: ":") (
                9 - (count (x: x == ":") (stringToCharacters address))
              )
            )
          )] address
        ) + (
          if hasSuffix "::" address then
            "0"
          else
            ""
        );
    
        decode = address: map fromHexString (
          splitString ":" (
            expand address
          )
        );
    
        encode = address: toLower (
          concatStringsSep ":" (
            map toHexString address
          )
        );
    
        netmask = prefixLength: map (
          x: if prefixLength > x + 16 then
            (pow 2 16) - 1
          else if prefixLength < x then
            0
          else
            (
              foldl (
                x: y: 2 * x + 1
              ) 0 (
                range 1 (prefixLength - x)
              )
            ) * (
              pow 2 (
                16 - (prefixLength - x)
              )
            )
        ) (
          genList (
            x: x * 16
          ) 8
        );
    
        reverseZone = net: (
          concatStringsSep "." (
            concatLists (
              reverseList (
                map (
                  x: stringToCharacters (fixedWidthString 4 "0" x)
                ) (
                  splitString ":" (
                    expand net
                  )
                )
              )
            )
          )
        ) + ".ip6.arpa";
    
        networkOf = address: prefixLength: encode (
          zipListsWith bitAnd (
            decode address
          ) (
            netmask prefixLength
          )
        );
    
        isInNetwork = net: address: networkOf address == (expand net);
    
        /* nixos-specific stuff */
    
        findOwnAddress = config: net: head (
          filter (
            isInNetwork net
          ) (
            configuredAddresses config
          )
        );
    
        configuredAddresses = config: concatLists (
          mapAttrsToList (
            name: iface: iface.ipv6.addresses
          ) config.networking.interfaces
        );
    
      };
    }