Created
January 28, 2023 04:01
-
-
Save iyre/aa9e3d09306a88477c19aee448cf5a6e to your computer and use it in GitHub Desktop.
powershell ip math
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function IpToInt ([ipaddress]$IPAddress) { | |
$IpBytes = $IPAddress.GetAddressBytes() | |
if ([BitConverter]::IsLittleEndian) { | |
[Array]::Reverse($IpBytes) | |
} | |
return [BitConverter]::ToUInt32($IpBytes, 0) | |
} | |
function IntToIp ([uint32]$IPInteger) { | |
$IpBytes = [BitConverter]::GetBytes($IPInteger) | |
if ([BitConverter]::IsLittleEndian) { | |
[Array]::Reverse($IpBytes) | |
} | |
return [ipaddress]$IpBytes | |
} | |
function CidrMaskToInt([int]$NetMask) { | |
return (([math]::pow(2, 32)) - 1) - (([math]::pow(2, 32 - $NetMask)) - 1) | |
} | |
# ip addresses are big endian | |
# c# converts these to little endian integers | |
# this results in the byte order being reversed, making some basic "ip math" either impossible or convoluted | |
# there are 32 bits in an ipv4 address, which means 2^32 possible addresses | |
# 2^32 = 4294967296, equivalent to FFFFFFFF in hex | |
# so, any decimal number from 0 to 4294967295 represents a valid IP address | |
# 192.168.0.1 # dotted decimal | |
# 0xc0a80001 # in hex | |
# 11000000101010000000000000000001 # binary | |
# this is the 32-bit unsigned integer with the "correct" byte order | |
# 3232235521 | |
# the c# ipaddress class has an "address" property that flips the byte order of the ip address to LITTLE ENDIAN (least significant first) | |
# ([ipaddress]'192.168.0.1').address | |
# 16820416 | |
# 0x0100a8c0 | |
# 00000001000000001010100011000000 | |
# this integer does not align with the 2^32 range of decimal numbers | |
([ipaddress]'192.168.0.1').address | |
# 16820416 | |
iptoint '192.168.0.1' | |
# 3232235521 | |
inttoip 3232235521 | |
# 192.168.0.1 | |
# much simpler to offset by a number of networks this way | |
# given network mask (m), number of networks (n) to offset by | |
# (2 ^ (32 - m )) * n ) = address offset | |
# (2 ^ (32 - 24)) * 12) = 3072 | |
(inttoip ((iptoint '192.168.0.1') + 3072)).ipaddresstostring | |
# 192.168.12.1 | |
# c# alternative is not that bad, just always required to build an actual ip address and convert between the reversed int | |
([ipaddress](([ipaddress]'192.168.0.1').address + ([ipaddress]'0.0.12.0').address)).ipaddresstostring | |
# calculating the gateway for a given ip is overly complicated, since we need to convert everything to the weird reversed order and back | |
([ipaddress]((([ipaddress]'192.168.18.220').address -band ([ipaddress]'255.255.255.0').address) + ([ipaddress]'0.0.0.1').address)).ipaddresstostring | |
# i realize this looks way more complicated, but it makes sense logically and keeps the byte order consistent | |
(inttoip (((iptoint '192.168.18.220') -band (([math]::pow(2, 32)) - 1) - (([math]::pow(2, 32-24)) - 1)) + 1)).ipaddresstostring | |
(inttoip (((iptoint '192.168.18.220') -band (cidrmasktoint 24)) + 1)).ipaddresstostring | |
# just the network id | |
(inttoip ((iptoint '192.168.18.220') -band (cidrmasktoint 24))).ipaddresstostring | |
(inttoip ((iptoint '192.168.18.220') -band (iptoint '255.255.255.0'))).ipaddresstostring | |
# this doesnt produce the desired result with the c# class - due to the little endian byte order | |
([ipaddress](([ipaddress]'10.0.240.0').address + ([ipaddress]'0.0.16.0').address)).ipaddresstostring | |
# this produces 10.0.0.1 | |
# logically, we expect 10.1.0.0 | |
# since the bytes are reversed, the "carry" is moved in the wrong direction | |
# any operation that needs to span a byte isn't gonna work | |
# no such issue when we keep the matching byte order. correct octet is incremented | |
(inttoip ((iptoint '10.0.240.0') + (iptoint '0.0.16.0'))).ipaddresstostring | |
# 10.1.0.0 | |
# it's also much simpler (and more sensical) to perform ip math with the correctly ordered integers) | |
# offset by 8 addresses | |
(inttoip ((iptoint '192.168.0.1') + 8)).ipaddresstostring | |
# 192.168.0.9 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment