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.
These functions are also included in my NetShell module, I need to post an update to that very soon as well.
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.
Function ConvertTo-HexIP {
<#
.Synopsis
Converts a dotted decimal IP address into a hexadecimal string.
.Description
ConvertTo-HexIP takes a dotted decimal IP and returns a single hexadecimal string value.
.Parameter IPAddress
An IP Address to convert.
#>
[CmdLetBinding()]
Param(
[Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)]
[Net.IPAddress]$IPAddress
)
Process {
"$($IPAddress.GetAddressBytes() | ForEach-Object { '{0:x2}' -f $_ })" -Replace '\s'
}
}
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).
Function ConvertFrom-HexIP {
<#
.Synopsis
Converts a hexadecimal IP address into a dotted decimal string.
.Description
ConvertFrom-HexIP takes a hexadecimal string and returns a dotted decimal IP address.
.Parameter IPAddress
An IP Address to convert.
#>
[CmdLetBinding()]
Param(
[Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)]
[ValidatePattern('^[0-9a-f]{8}$')]
[String]$IPAddress
)
Process {
ConvertTo-DottedDecimalIP ([Convert]::ToUInt32($IPAddress, 16))
}
}
Get-NetworkSummary
Get-NetworkSummary gets a bit of an improvement.
Function Get-NetworkSummary {
<#
.Synopsis
Generates a summary of a network range
.Description
Get-NetworkSummary uses most of the IP conversion CmdLets to provide a summary of a network
range from any IP address in the range and a subnet mask.
.Parameter IPAddress
Any IP address within the network range.
.Parameter Network
A network description in the format 1.2.3.4/24
.Parameter SubnetMask
The subnet mask for the network.
#>
[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")]
[Net.IPAddress]$SubnetMask,
[Parameter(Mandatory = $True, ParameterSetName = "CIDRNotation", ValueFromPipeline = $True)]
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}[\\/]\d{1,2}$')]
[String]$Network
)
Process {
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 = New-Object PSObject -Property @{
"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 = [String]::Format("{0} - {1}",
(ConvertTo-DottedDecimalIP ($DecimalNetwork + 1)),
(ConvertTo-DottedDecimalIP ($DecimalBroadcast - 1)))
}
Switch -RegEx ($(ConvertTo-BinaryIP $IPAddress)) {
"^1111" { $NetworkSummary.Class = "E" }
"^1110" { $NetworkSummary.Class = "D" }
"^11000000.10101000" { $NetworkSummary.Class = "C"; $NetworkSummary.IsPrivate = $True }
"^110" { $NetworkSummary.Class = "C" }
"^10101100.0001" { $NetworkSummary.Class = "B"; $NetworkSummary.IsPrivate = $True }
"^10" { $NetworkSummary.Class = "B" }
"^00001010" { $NetworkSummary.Class = "A"; $NetworkSummary.IsPrivate = $True }
"^0" { $NetworkSummary.Class = "A" }
}
Return $NetworkSummary
}
}
Get-NetworkRange
And so does Get-NetworkRange.
Function Get-NetworkRange {
<#
.Synopsis
Generates IP addresses within the specified network.
.Description
Get-NetworkRange finds the network and broadcast address as decimal values then starts a
counter between the two, returning Net.IPAddress for each.
.Parameter IPAddress
Any IP address within the network range.
.Parameter Network
A network description in the format 1.2.3.4/24
.Parameter SubnetMask
The subnet mask for the network.
#>
[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")]
[Net.IPAddress]$SubnetMask,
[Parameter(Mandatory = $True, ParameterSetName = "CIDRNotation", ValueFromPipeline = $True)]
[ValidatePattern('^(\d{1,3}\.){3}\d{1,3}[\\/]\d{1,2}$')]
[String]$Network
)
Process {
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.
Function Get-Subnets {
<#
.Synopsis
Generates a list of subnets for a given network range
.Description
Generates a list of subnets for a given network range using either the address class or a
user-specified value.
.Parameter NetworkAddress
Any address in the supernet range.
.Parameter SubnetMask
The desired mask, determines the size of the resulting subnet. Must be a valid subnet mask.
.Parameter SupernetLength
By default Get-Subnets uses the address class to determine the size of the supernet. Where the
supernet describes the range of addresses being split.
#>
[CmdLetBinding(DefaultParameterSetName = "PS1")]
Param(
[Parameter(Mandatory = $True, Position = 0, ParameterSetName = "IPAndMask", ValueFromPipeline = $True)]
[Net.IPAddress]$IPAddress,
[Parameter(Mandatory = $True, Position = 1, ParameterSetName = "IPAndMask")]
[Alias("Mask")]
[Net.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
)
Process {
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) {
Write-Error "Subnet is larger than supernet. Aborting"
}
$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
"" | Select-Object @{n='NetworkAddress';e={ $NetworkAddress }},
@{n='BroadcastAddress';e={ Get-BroadcastAddress $NetworkAddress $SubnetMask }},
@{n='SubnetMask';e={ $SubnetMask }},
@{n='HostAddresses';e={
$NumberOfHosts = $NumberOfAddresses - 2
If ($NumberOfHosts -lt 0) { 0 } Else { $NumberOfHosts } }}
$DecimalAddress += $NumberOfAddresses
}
}
}

I really like your sub-net math functions – the original collection and the additions. Much appreciated.
In order to use them on one of the projects that I am working on a clear licence statement would be very helpful. You did mention on the VbScript version post in the comments that all code is intended to be public domain. In contrast to that your footer on every page clearly states “All rights reserved.”
I also downloaded your NetShell module, and the copyright attribute doesn’t help to clarify either.
Just trying to stay our of trouble ;-)
Thanks again!
Andy