I’ve been extended and upgrading my library of network functions for some time now, I thought I’d post the functions that work directly with my original collection.
The functions described here have been updated since posting this article. The updated functions are available as part of the script Indented.Net.IP. The module may be installed from the PS gallery:
Install-Module Indented.Net.IP
ConvertTo-HexIP
Sometimes being able to convert to a hexadecimal format is useful, this little function does exactly that. The body is very simple; it uses the built in formatters.
filter ConvertTo-HexIP {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[IPAddress]$IPAddress
)
($IPAddress.GetAddressBytes() | ForEach-Object {
'{0:X2}' -f $_
}) -join ''
}
ConvertFrom-HexIP
And back again, using System.Convert.ToUInt32 with a base-16 value to get to UInt32, then a call to ConvertTo-DottedDecimalIP (from the original set).
filter ConvertFrom-HexIP {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
[ValidatePattern('^[0-9a-f]{8}$')]
[String]$IPAddress
)
ConvertTo-DottedDecimalIP ([Convert]::ToUInt32($IPAddress, 16))
}
Get-NetworkSummary
Get-NetworkSummary gets a bit of an improvement.
filter Get-NetworkSummary {
[CmdletBinding(DefaultParameterSetName = "IPAndMask")]
param (
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = "IPAndMask", ValueFromPipeline = $true)]
[Net.IPAddress]$IPAddress,
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "IPAndMask")]
[Alias("Mask")]
[IPAddress]$SubnetMask,
[Parameter(Mandatory = $true, ParameterSetName = "CIDRNotation", ValueFromPipeline = $true)]
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}[\\/]\d{1,2}$')]
[String]$Network
)
if ($pscmdlet.ParameterSetName -eq 'CIDRNotation') {
$Temp = $Network.Split("/")
$IPAddress = $Temp[0]
$SubnetMask = ConvertTo-Mask $Temp[1]
}
$DecimalIP = ConvertTo-DecimalIP $IPAddress
$DecimalMask = ConvertTo-DecimalIP $SubnetMask
$DecimalNetwork = $DecimalIP -band $DecimalMask
$DecimalBroadcast = $DecimalIP -bor ((-bnot $DecimalMask) -band [UInt32]::MaxValue)
$NetworkSummary = [PSCustomObject]@{
NetworkAddress = (ConvertTo-DottedDecimalIP $DecimalNetwork)
NetworkDecimal = $DecimalNetwork
BroadcastAddress = (ConvertTo-DottedDecimalIP $DecimalBroadcast)
BroadcastDecimal = $DecimalBroadcast
Mask = $SubnetMask
MaskLength = (ConvertTo-MaskLength $SubnetMask)
MaskHexadecimal = (ConvertTo-HexIP $SubnetMask)
HostRange = ''
NumberOfHosts = ($DecimalBroadcast - $DecimalNetwork - 1)
Class = ''
IsPrivate = $false
}
if ($NetworkSummary.MaskLength -lt 31) {
$NetworkSummary.HostRange = "{0} - {1}" -f
(ConvertTo-DottedDecimalIP ($DecimalNetwork + 1)),
(ConvertTo-DottedDecimalIP ($DecimalBroadcast - 1))
}
$NetworkSummary.Class = switch -regex ($(ConvertTo-BinaryIP $IPAddress)) {
"^1111" { "E"; break }
"^1110" { "D"; break }
"^11000000.10101000" { $NetworkSummary.IsPrivate = $true }
"^110" { "C"; break }
"^10101100.0001" { $NetworkSummary.IsPrivate = $true }
"^10" { "B"; break }
"^00001010" { $NetworkSummary.IsPrivate = $true }
"^0" { "A"; break }
}
$NetworkSummary
}
Get-NetworkRange
And so does Get-NetworkRange.
filter Get-NetworkRange {
[CmdletBinding(DefaultParameterSetName = "IPAndMask")]
param (
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = "IPAndMask", ValueFromPipeline = $true)]
[IPAddress]$IPAddress,
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "IPAndMask")]
[Alias("Mask")]
[IPAddress]$SubnetMask,
[Parameter(Mandatory = $true, ParameterSetName = "CIDRNotation", ValueFromPipeline = $true)]
# [ValidatePattern('^(\d{1,3}\.){3}\d{1,3}[\\/]\d{1,2}$')]
[String]$Network
)
if ($pscmdlet.ParameterSetName -eq 'CIDRNotation') {
$Temp = $Network.Split("/")
$IPAddress = $Temp[0]
$SubnetMask = ConvertTo-Mask $Temp[1]
}
$DecimalIP = ConvertTo-DecimalIP $IPAddress
$DecimalMask = ConvertTo-DecimalIP $SubnetMask
$DecimalNetwork = $DecimalIP -band $DecimalMask
$DecimalBroadcast = $DecimalIP -bor ((-bnot $DecimalMask) -band [UInt32]::MaxValue)
for ($i = $DecimalNetwork + 1; $i -lt $DecimalBroadcast; $i++) {
ConvertTo-DottedDecimalIP $i
}
}
Get-Subnets
I ran into a need to calculate a list of subnets of a specific length within a super-net, this function does just that.
filter Get-Subnets {
[CmdletBinding(DefaultParameterSetName = "IPAndMask")]
param (
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = "IPAndMask", ValueFromPipeline = $true)]
[IPAddress]$IPAddress,
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "IPAndMask")]
[Alias("Mask")]
[IPAddress]$SubnetMask,
[Parameter(Mandatory = $true, ParameterSetName = "CIDRNotation", ValueFromPipeline = $true)]
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}[\\/]\d{1,2}$')]
[String]$Network,
[ValidateRange(1, 32)]
[UInt32]$SupernetLength
)
if ($pscmdlet.ParameterSetName -eq 'CIDRNotation') {
$Temp = $Network.Split("/")
$IPAddress = $Temp[0]
$SubnetMask = ConvertTo-Mask $Temp[1]
} else {
$SubnetLength = ConvertTo-MaskLength $SubnetMask
}
if (!$SupernetLength) {
$SupernetLength = switch -regex ($(ConvertTo-BinaryIP $IPAddress)) {
"^110" { 24 }
"^10" { 16 }
"^0" { 8 }
default { 24 }
}
}
if ($SupernetLength -gt $SubnetLength) {
throw "Subnet is larger than supernet."
}
$SupernetMask = ConvertTo-Mask $SupernetLength
$NumberOfNets = [Math]::Pow(2, ($SubnetLength - $SupernetLength))
$NumberOfAddresses = [Math]::Pow(2, (32 - $SubnetLength))
$SupernetAddress = Get-NetworkAddress $IPAddress $SupernetMask
$DecimalAddress = ConvertTo-DecimalIP $SupernetAddress
for ($i = 0; $i -lt $NumberOfNets; $i++) {
$NetworkAddress = ConvertTo-DottedDecimalIP $DecimalAddress
[PSCustomObject]@{
NetworkAddress = $NetworkAddress
BroadcastAddress = Get-BroadcastAddress $NetworkAddress $SubnetMask
SubnetMask = $SubnetMask
HostAddresses = $(
$NumberOfHosts = $NumberOfAddresses - 2
if ($NumberOfHosts -lt 0) { 0 } else { $NumberOfHosts }
)
}
$DecimalAddress += $NumberOfAddresses
}
}