Public/Get-Subnet.ps1

function Get-Subnet {
    <#
        .SYNOPSIS
            Returns subnet details for the local IP address, or a given network address and mask.

        .DESCRIPTION
            Use to get subnet details for a given network address and mask, including network address, broadcast address, network class,
            address range, host addresses and host address count.

        .PARAMETER IP
            A metric object (generated by one of the Get-*Metric cmdlets from this module) which can be provided as pipeline input.

        .PARAMETER MaskBits
            The name of the measure to be updated or created.

        .PARAMETER Force
            Use to force the return of all host IP addresses regardless of the subnet size (skipped by default for subnets larger than /16).

        .EXAMPLE
            Get-Subnet 10.1.2.3/24

            Description
            -----------
            Returns the subnet details for the specified network and mask, specified as a single string to the -IP parameter.

        .EXAMPLE
            Get-Subnet 192.168.0.1 -MaskBits 23

            Description
            -----------
            Returns the subnet details for the specified network and mask.

        .EXAMPLE
            Get-Subnet

            Description
            -----------
            Returns the subnet details for the current local IP.

        .EXAMPLE
            '10.1.2.3/24','10.1.2.4/24' | Get-Subnet

            Description
            -----------
            Returns the subnet details for two specified networks.
    #>

    Param ( 
        [parameter(ValueFromPipeline)]
        [string]
        $IP,

        [ValidateRange(0, 32)]
        [int]
        $MaskBits,

        [switch]
        $Force
    )
    Process {
        
        If ($PSBoundParameters.ContainsKey('MaskBits')) { 
            $Mask = $MaskBits 
        }

        If (-not $IP) { 
            $LocalIP = (Get-NetIPAddress | Where-Object { $_.AddressFamily -eq 'IPv4' -and $_.PrefixOrigin -ne 'WellKnown' })

            $IP = $LocalIP.IPAddress
            If ($Mask -notin 0..32) { $Mask = $LocalIP.PrefixLength }
        }

        If ($IP -match '/\d') { 
            $IPandMask = $IP -Split '/' 
            $IP = $IPandMask[0]
            $Mask = $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 ($Mask -notin 0..32) {
            $Mask = Switch ($Class) {
                'A' { 8 }
                'B' { 16 }
                'C' { 24 }
                default { Throw "Subnet mask size was not specified and could not be inferred because the address is Class $Class." }
            }

            Write-Warning "Subnet mask size was not specified. Using default subnet size for a Class $Class network of /$Mask."
        }

        $MaskAddr = [IPAddress]::Parse((Convert-Int64toIP -int ([convert]::ToInt64(("1" * $Mask + "0" * (32 - $Mask)), 2))))        
        $NetworkAddr = [IPAddress]($MaskAddr.address -band $IPAddr.address) 
        $BroadcastAddr = [IPAddress](([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

        $HostAddressCount = ($HostEndAddr - $HostStartAddr) + 1
        
        If ($Mask -ge 16 -or $Force) {
            
            Write-Progress "Calcualting host addresses for $NetworkAddr/$Mask.."

            $HostAddresses = for ($i = $HostStartAddr; $i -le $HostEndAddr; $i++) {
                Convert-Int64toIP -int $i
            }
        }
        Else {
            Write-Warning "Host address calculation was not performed because it would take some time for a /$Mask subnet. `nUse -Force if you want it to occur."
        }

        [pscustomobject]@{
            IPAddress        = $IPAddr
            MaskBits         = $Mask
            NetworkAddress   = $NetworkAddr
            BroadcastAddress = $broadcastaddr
            SubnetMask       = $MaskAddr
            NetworkClass     = $Class
            Range            = "$networkaddr ~ $broadcastaddr"
            HostAddresses    = $HostAddresses
            HostAddressCount = $HostAddressCount
        }
    }
}