Function Get-IPRange {
param([string]$ipaddress="",[switch]$AsString,[switch]$AsDecimal,[switch]$AsIPAddress)
begin {
# support functions
function ToDecimal {
# Convert a string IP ("192.168.1.1") to it's Decimal Equivalent
# Convert a Binary IP ("11011011111101011101110001111111") to it's Decimal Equivalent
param([string]$paddress)
if ($paddress.length -gt 15) {
# Possibly Binary as it's too long for Dot-Decimal
return [system.Convert]::ToInt64($paddress.replace(".",""),2)
} else {
# Possibly Dot-Decimal.
# Converting an IP address to decimal involves shifting bits
# for each octect. Powershell doesn't have any bit shifting operators
# so we'll use some math (YUCK!)
[byte[]]$b = ([system.Net.IPAddress]::Parse($paddress)).GetAddressBytes()
$longip = 0
for ($i = 0; $i -lt 4; $i++) {
$num = $b[$i]
$longip += (($num % 256) * ([math]::pow(256,3-$i)))
}
return [int64]$longip
}
}
function ToIP {
param ($paddress)
if ($paddress.Length -gt 15) {
# Possibly Binary as it's too long for Decimal
# If it's not a string, it'll also fail this test
return [system.Net.IPAddress]::Parse( (ToDecimal $paddress) )
} else {
# Most likely Decimal which the Parse method understands on its own.
return [system.Net.IPAddress]::Parse($paddress)
}
}
function ToBinary {
param($paddress)
if ($paddress.GetType().Name -eq "string") {
#Dot-Decimal
return ([system.Convert]::ToString((ToDecimal $paddress),2)).padleft(32,[char]"0")
} else {
#Decimal
return ([system.Convert]::ToString($paddress,2)).padleft(32,[char]"0")
}
}
function SplitAddress {
param([string]$paddress)
$address = ($paddress.split("/")[0])
$cidr = ([int]($paddress.split("/")[1]))
if (($cidr -lt 0) -or ($cidr -gt 32)) {
#invalid CIDR.
throw "$_ is not a valid CIDR notation for a range of IP addresses."
} else {
write-Output $address
write-Output $cidr
}
}
}
process {
################################################
# Support both pipeline and argument input.
if ($_) {
# Pipeline Input
$address,$cidr = SplitAddress $_
} else {
# Argument Input
if (!$ipaddress) { Throw "You must specify an IP Range in CIDR notation (I.e. `"192.168.1.0/24`")" }
$address,$cidr = SplitAddress $ipaddress
}
$binaddress = ToBinary ( ToDecimal $address )
$binmask = ("1" * $cidr).padright(32,[char]"0")
$binnetwork = ""
$binbroadcast = ""
for ($i = 0; $i -lt 32; $i++) {
# faking a bitwise comparison since powershell's -BAND only handles Int32.
# Determine the Network Address (first in range) by doing a bitwise AND
# between the address and mask specified.
$binnetwork += [string]( $binmask.Substring($i,1) -band $binaddress.substring($i,1) )
# Determine the Broadcast Address by flipping only the HOST bits to 1
if ($i -lt $cidr) {
$binbroadcast += [string]( $binaddress.Substring($i,1) )
} else {
$binbroadcast += [string]"1"
}
}
# Convert the binary results back to Decimal
$longnetwork = ToDecimal $binnetwork
$longbroadcast = ToDecimal $binbroadcast
#Pipe each IP object up the pipeline:
# I'm skipping the network address and the Broadcast address
for ($i = $longnetwork+1; $i -lt $longbroadcast; $i++) {
if ($AsString) {
write-Output (ToIP $i).IPAddressToString
} elseif ($AsDecimal) {
write-Output $i
} else {
#AsIPAddress
write-Output (ToIP $i)
}
}
}
}