Created
January 7, 2020 18:08
-
-
Save davidjenni/7eb707e60316cdd97549b37ca95fbe93 to your computer and use it in GitHub Desktop.
CIDR to IP range conversion using PowerShell
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
# calculate IP address range from CIDR notation | |
# https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing | |
function cidrToIpRange { | |
param ( | |
[string] $cidrNotation | |
) | |
$addr, $maskLength = $cidrNotation -split '/' | |
[int]$maskLen = 0 | |
if (-not [int32]::TryParse($maskLength, [ref] $maskLen)) { | |
throw "Cannot parse CIDR mask length string: '$maskLen'" | |
} | |
if (0 -gt $maskLen -or $maskLen -gt 32) { | |
throw "CIDR mask length must be between 0 and 32" | |
} | |
$ipAddr = [Net.IPAddress]::Parse($addr) | |
if ($ipAddr -eq $null) { | |
throw "Cannot parse IP address: $addr" | |
} | |
if ($ipAddr.AddressFamily -ne [Net.Sockets.AddressFamily]::InterNetwork) { | |
throw "Can only process CIDR for IPv4" | |
} | |
$shiftCnt = 32 - $maskLen | |
$mask = -bnot ((1 -shl $shiftCnt) - 1) | |
$ipNum = [Net.IPAddress]::NetworkToHostOrder([BitConverter]::ToInt32($ipAddr.GetAddressBytes(), 0)) | |
$ipStart = ($ipNum -band $mask) + 1 | |
$ipEnd = ($ipNum -bor (-bnot $mask)) - 1 | |
# return as tuple of strings: | |
([BitConverter]::GetBytes([Net.IPAddress]::HostToNetworkOrder($ipStart)) | ForEach-Object { $_ } ) -join '.' | |
([BitConverter]::GetBytes([Net.IPAddress]::HostToNetworkOrder($ipEnd)) | ForEach-Object { $_ } ) -join '.' | |
} | |
$start, $end = cidrToIpRange "192.168.100.14/24" | |
Write-Host "Start: $start, end: $end" | |
$start, $end = cidrToIpRange "10.77.1.1/18" | |
Write-Host "Start: $start, end: $end" |
Thanks, Just what I needed ;-)
The script is really good but does not work well when the mask is 31 or 32.
For an input 13.105.220.108/31 it will produce a result like:
Start Host: 13.105.220.109
End Host: 13.105.220.108
To fix that just replace lines 28 and 29
$ipStart = ($ipNum -band $mask) + 1 $ipEnd = ($ipNum -bor (-bnot $mask)) - 1
By this
` $ipStart = $ipNum -band $mask
$ipEnd = $ipNum -bor (-bnot $mask)
if ($maskLength -lt 31) {
$ipStart += 1
$ipEnd -= 1
}`
I've tested this with more than 4000 cidr
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think the +1/-1 should be removed altogether. That's what I did in my fork after verifying.