Personal Nix setup
at main 7.6 kB view raw
1/* See: https://github.com/djacu/nixpkgs/blob/adb22cf/lib/network.nix */ 2{ lib, ... }: 3 4let 5 /* 6 Converts an IP address from a list of ints to a string. 7 8 Type: prettyIp :: [ Int ] -> String 9 10 Examples: 11 prettyIp [ 192 168 70 9 ] 12 => "192.168.70.9" 13 */ 14 prettyIp = addr: 15 lib.concatStringsSep "." (builtins.map builtins.toString addr); 16 17 /* 18 Given a bit mask, return the associated subnet mask. 19 20 Type: bitMaskToSubnetMask :: Int -> [ Int ] 21 22 Examples: 23 bitMaskToSubnetMask 15 24 => [ 255 254 0 0 ] 25 bitMaskToSubnetMask 24 26 => [ 255 255 255 0 ] 27 */ 28 bitMaskToSubnetMask = bitMask: let 29 numOctets = 4; 30 octetBits = 8; 31 octetMin = 0; 32 octetMax = 255; 33 # How many initial parts of the mask are full (=255) 34 fullParts = bitMask / octetBits; 35 in 36 lib.genList ( 37 idx: 38 # Fill up initial full parts 39 if idx < fullParts 40 then octetMax 41 # If we're above the first non-full part, fill with 0 42 else if fullParts < idx 43 then octetMin 44 # First non-full part generation 45 else _genPartialMask (lib.mod bitMask octetBits) 46 ) 47 numOctets; 48 49 /* 50 Generate a the partial portion of a subnet mask. 51 52 Type: _genPartialMask :: Int -> Int 53 54 Examples: 55 _genPartialMask 0 56 => 0 57 _genPartialMask 1 58 => 128 59 _genPartialMask 2 60 => 192 61 _genPartialMask 3 62 => 224 63 _genPartialMask 4 64 => 240 65 _genPartialMask 5 66 => 248 67 _genPartialMask 6 68 => 252 69 _genPartialMask 7 70 => 254 71 */ 72 _genPartialMask = n: 73 if n == 0 74 then 0 75 else _genPartialMask (n - 1) / 2 + 128; 76 77 /* 78 Given a subnet mask, return the associated bit mask. 79 80 Type: subnetMaskToBitMask :: [ Int ] -> Int 81 82 Examples: 83 subnetMaskToBitMask [ 255 254 0 0 ] 84 => 15 85 subnetMaskToBitMask [ 255 255 255 0 ] 86 => 24 87 */ 88 subnetMaskToBitMask = subnetMask: let 89 partialBits = octet: 90 if octet == 0 91 then 0 92 else (lib.mod octet 2) + partialBits (octet / 2); 93 in 94 builtins.foldl' 95 (x: y: x + y) 96 0 97 (builtins.map partialBits subnetMask); 98 99 /* 100 Given a CIDR, return the IP Address. 101 102 Type: cidrToIpAddress :: String -> [ Int ] 103 104 Examples: 105 cidrToIpAddress "192.168.70.9/15" 106 => [ 192 168 70 9 ] 107 */ 108 cidrToIpAddress = cidr: let 109 splitParts = lib.splitString "/" cidr; 110 addr = lib.elemAt splitParts 0; 111 parsed = 112 builtins.map 113 lib.toInt 114 (builtins.match "([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)" addr); 115 checkBounds = octet: 116 (octet >= 0) && (octet <= 255); 117 in 118 if (builtins.all checkBounds parsed) 119 then parsed 120 else builtins.throw "IP ${prettyIp addr} has out of bounds octet(s)"; 121 122 /* 123 Given a CIDR, return the bitmask. 124 125 Type: cidrToBitMask :: String -> Int 126 127 Examples: 128 cidrToBitMask "192.168.70.9/15" 129 => 15 130 */ 131 cidrToBitMask = cidr: let 132 splitParts = lib.splitString "/" cidr; 133 mask = lib.toInt (lib.elemAt splitParts 1); 134 checkBounds = mask: 135 (mask >= 0) && (mask <= 32); 136 in 137 if (checkBounds mask) 138 then mask 139 else builtins.throw "Bitmask ${builtins.toString mask} is invalid."; 140 141 /* 142 Given a CIDR, return the associated subnet mask. 143 144 Type: cidrToSubnetMask :: String -> [ Int ] 145 146 Examples: 147 cidrToSubnetMask "192.168.70.9/15" 148 => [ 255 254 0 0 ] 149 */ 150 cidrToSubnetMask = cidr: 151 bitMaskToSubnetMask (cidrToBitMask cidr); 152 153 /* 154 Given a CIDR, return the associated network ID. 155 156 Type: cidrToNetworkId :: String -> [ Int ] 157 158 Examples: 159 cidrToNetworkId "192.168.70.9/15" 160 => [ 192 168 0 0 ] 161 */ 162 cidrToNetworkId = cidr: let 163 ip = cidrToIpAddress cidr; 164 subnetMask = cidrToSubnetMask cidr; 165 in 166 lib.zipListsWith lib.bitAnd ip subnetMask; 167 168 /* 169 Given a CIDR, return the associated first usable IP address. 170 171 Type: cidrToFirstUsableIp :: String -> [ Int ] 172 173 Examples: 174 cidrToFirstUsableIp "192.168.70.9/15" 175 => [ 192 168 0 1 ] 176 */ 177 cidrToFirstUsableIp = cidr: let 178 networkId = cidrToNetworkId cidr; 179 in 180 incrementIp networkId 1; 181 182 /* 183 Given a CIDR, return the associated broadcast address. 184 185 Type: cidrToBroadcastAddress :: String -> [ Int ] 186 187 Examples: 188 cidrToBroadcastAddress "192.168.70.9/15" 189 => [ 192 169 255 255 ] 190 */ 191 cidrToBroadcastAddress = cidr: let 192 subnetMask = cidrToSubnetMask cidr; 193 networkId = cidrToNetworkId cidr; 194 in 195 getBroadcastAddress networkId subnetMask; 196 197 /* 198 Given a network ID and subnet mask, return the associated broadcast address. 199 200 Type: getBroadcastAddress :: [ Int ] -> [ Int ] -> [ Int ] 201 202 Examples: 203 getBroadcastAddress [ 192 168 0 0 ] [ 255 254 0 0 ] 204 => [ 192 169 255 255 ] 205 */ 206 getBroadcastAddress = networkId: subnetMask: 207 lib.zipListsWith (nid: mask: 255 - mask + nid) networkId subnetMask; 208 209 /* 210 Given a CIDR, return the associated last usable IP address. 211 212 Type: cidrToLastUsableIp :: String -> [ Int ] 213 214 Examples: 215 cidrToLastUsableIp "192.168.70.9/15" 216 => [ 192 169 255 254 ] 217 */ 218 cidrToLastUsableIp = cidr: let 219 broadcast = cidrToBroadcastAddress cidr; 220 in 221 incrementIp broadcast (-1); 222 223 /* 224 Increment the last octet of a given IP address. 225 226 Type: incrementIp :: [ Int ] -> Int -> [ Int ] 227 228 Examples: 229 incrementIp [ 192 168 70 9 ] 3 230 => [ 192 168 70 12 ] 231 incrementIp [ 192 168 70 9 ] (-2) 232 => [ 192 168 70 7 ] 233 */ 234 incrementIp = addr: offset: let 235 lastOctet = lib.last addr; 236 firstThree = lib.init addr; 237 in 238 firstThree ++ [(lastOctet + offset)]; 239 240 /* 241 Given an IP address and bit mask, return the associated CIDR. 242 243 Type: ipAndBitMaskToCidr :: [ Int ] -> Int -> String 244 245 Examples: 246 ipAndBitMaskToCidr [ 192 168 70 9 ] 15 247 => "192.168.70.9/15" 248 */ 249 ipAndBitMaskToCidr = addr: bitMask: 250 lib.concatStringsSep "/" 251 [ 252 (prettyIp addr) 253 (builtins.toString bitMask) 254 ]; 255 256 /* 257 Given an IP address and subnet mask, return the associated CIDR. 258 259 Type: ipAndSubnetMaskToCidr :: [ Int ] -> Int -> String 260 261 Examples: 262 ipAndSubnetMaskToCidr [ 192 168 70 9 ] [ 255 254 0 0 ] 263 => "192.168.70.9/15" 264 */ 265 ipAndSubnetMaskToCidr = addr: subnetMask: 266 ipAndBitMaskToCidr addr (subnetMaskToBitMask subnetMask); 267 268 /* 269 Given a CIDR, return an attribute set of: 270 the IP Address, 271 the bit mask, 272 the first usable IP address, 273 the last usable IP address, 274 the network ID, 275 the subnet mask, 276 the broadcast address. 277 278 Type: getNetworkProperties :: str -> attrset 279 280 Examples: 281 getNetworkProperties "192.168.70.9/15" 282 => { 283 bitMask = 15; 284 broadcast = "192.169.255.255"; 285 firstUsableIp = "192.168.0.1"; 286 ipAddress = "192.168.70.9"; 287 lastUsableIp = "192.169.255.254"; 288 networkId = "192.168.0.0"; 289 subnetMask = "255.254.0.0"; 290 } 291 */ 292 getNetworkProperties = cidr: let 293 ipAddress = prettyIp (cidrToIpAddress cidr); 294 bitMask = cidrToBitMask cidr; 295 firstUsableIp = prettyIp (cidrToFirstUsableIp cidr); 296 lastUsableIp = prettyIp (cidrToLastUsableIp cidr); 297 networkId = prettyIp (cidrToNetworkId cidr); 298 subnetMask = prettyIp (cidrToSubnetMask cidr); 299 broadcast = prettyIp (cidrToBroadcastAddress cidr); 300 in {inherit ipAddress bitMask firstUsableIp lastUsableIp networkId subnetMask broadcast;}; 301in { 302 ipv4 = { 303 inherit 304 prettyIp 305 incrementIp 306 bitMaskToSubnetMask 307 subnetMaskToBitMask 308 ipAndBitMaskToCidr 309 ipAndSubnetMaskToCidr 310 cidrToIpAddress 311 cidrToBitMask 312 cidrToFirstUsableIp 313 cidrToLastUsableIp 314 cidrToNetworkId 315 cidrToSubnetMask 316 cidrToBroadcastAddress 317 getNetworkProperties 318 ; 319 }; 320}