Skip to content

Instantly share code, notes, and snippets.

@markwragg
Last active April 5, 2024 14:32
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save markwragg/80faa959610731149a080946e22c4abb to your computer and use it in GitHub Desktop.
Save markwragg/80faa959610731149a080946e22c4abb to your computer and use it in GitHub Desktop.
PowerShell cmdlet to return the IP details and range of a network and subnet mask
function Get-Subnet {
param (
[parameter(ValueFromPipeline)]
[String]
$IP,
[ValidateRange(0, 32)]
[int]
$MaskBits,
[switch]
$SkipHosts
)
Begin {
function Convert-IPtoINT64 ($ip) {
$octets = $ip.split(".")
[int64]([int64]$octets[0] * 16777216 + [int64]$octets[1] * 65536 + [int64]$octets[2] * 256 + [int64]$octets[3])
}
function Convert-INT64toIP ([int64]$int) {
(([math]::truncate($int / 16777216)).tostring() + "." + ([math]::truncate(($int % 16777216) / 65536)).tostring() + "." + ([math]::truncate(($int % 65536) / 256)).tostring() + "." + ([math]::truncate($int % 256)).tostring() )
}
If (-not $IP -and -not $MaskBits) {
$LocalIP = (Get-NetIPAddress | Where-Object {$_.AddressFamily -eq 'IPv4' -and $_.PrefixOrigin -ne 'WellKnown'})
$IP = $LocalIP.IPAddress
$MaskBits = $LocalIP.PrefixLength
}
}
Process {
If ($IP -match '/\d') {
$IPandMask = $IP -Split '/'
$IP = $IPandMask[0]
$MaskBits = $IPandMask[1]
}
$IPAddr = [Net.IPAddress]::Parse($IP)
$Class = Switch ($IP.Split('.')[0]) {
{$_ -in 0..127} { 'A' }
{$_ -in 128..191} { 'B' }
{$_ -in 192..223} { 'C' }
{$_ -in 224..239} { 'D' }
{$_ -in 240..255} { 'E' }
}
If (-not $MaskBits) {
$MaskBits = Switch ($Class) {
'A' { 8 }
'B' { 16 }
'C' { 24 }
default { Throw 'Subnet mask size was not specified and could not be inferred.' }
}
Write-Warning "Subnet mask size was not specified. Using default subnet size for a Class $Class network of /$MaskBits."
}
If ($MaskBits -lt 16 -and -not $SkipHosts) {
Write-Warning "It may take some time to calculate all host addresses for a /$MaskBits subnet. Use -SkipHosts to skip."
}
$MaskAddr = [Net.IPAddress]::Parse((Convert-INT64toIP -int ([convert]::ToInt64(("1" * $MaskBits + "0" * (32 - $MaskBits)), 2))))
$NetworkAddr = New-Object net.ipaddress ($MaskAddr.address -band $IPAddr.address)
$BroadcastAddr = New-Object net.ipaddress (([system.net.ipaddress]::parse("255.255.255.255").address -bxor $MaskAddr.address -bor $NetworkAddr.address))
$HostStartAddr = (Convert-IPtoINT64 -ip $NetworkAddr.ipaddresstostring) + 1
$HostEndAddr = (Convert-IPtoINT64 -ip $broadcastaddr.ipaddresstostring) - 1
If (-not $SkipHosts) {
$HostAddresses = for ($i = $HostStartAddr; $i -le $HostEndAddr; $i++) {
Convert-INT64toIP -int $i
}
}
[pscustomobject]@{
IPAddress = $IPAddr
MaskBits = $MaskBits
NetworkAddress = $NetworkAddr
BroadcastAddress = $broadcastaddr
SubnetMask = $MaskAddr
NetworkClass = $Class
Range = "$networkaddr ~ $broadcastaddr"
HostAddresses = $HostAddresses
}
}
End {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment