Private/IPAX-IPv4Math.ps1

function Convert-V4DottedToInt {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidatePattern('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}')]
        [string]$InputString
    )
    $power = 3
    $value = 0
    $InputString.Split('.').ForEach({ $value += ([int]$_ * [math]::Pow(256,$power)); $power = $power - 1})
    $value
}

function Convert-IntToV4Dotted {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateRange(0,4294967295)]
        [int64]$InputValue
    )
    $binval = ([convert]::ToString($InputValue,2)).PadLeft(32,'0')
    $valbytes = @()
    (0..3).ForEach({$valbytes += ([convert]::ToByte($binval.Substring($_ * 8,8),2)).ToString()})
    $valbytes -join '.'
}

function Get-IPAX4SubnetMask {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateRange(1,32)]
        [int]$SubnetMaskLength
    )
    $binmask = '1' * $SubnetMaskLength + '0' * (32 - $SubnetMaskLength)
    $maskbytes = @()
    (0..3).ForEach({$maskbytes += ([convert]::ToByte($binmask.Substring($_ * 8,8),2)).ToString()})
    $maskbytes -join '.'
}

function Get-IPAX4SubnetMaskLength {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidatePattern('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}')]
        [string]$SubnetMask
    )
    if (Test-IPAX4SubnetMask -SubnetMask $SubnetMask) {
        $mask = Convert-V4DottedToInt -InputString $SubnetMask
        $binmask = [convert]::ToString($mask,2)
        $binmask.Trim('0').Length
    } else {
        0
    }
}

function Test-IPAX4SubnetMask {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidatePattern('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}')]
        [string]$SubnetMask
    )
    $mask = Convert-V4DottedToInt -InputString $SubnetMask
    $binmask = [convert]::ToString($mask,2)
    if ($binmask -match '^1+0*$') {
        $true
    } else {
        $false
    }
}

function Get-IPAX4Classification {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidatePattern('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}')]
        [string]$IPAddress
    )
    $addressValue = Convert-V4DottedToInt $IPAddress
    $addressClassification = 'Public'
    # initial list from https://ipinfo.io/bogon
    if ($addressValue -eq 4294967295) {
        # 255.255.255.255
        $addressClassification = 'Limited Broadcast'
    } elseif ($addressValue -ge 4026531840) {
        # 240.0.0.0/4
        $addressClassification = 'Reserved for future use'
    } elseif ($addressValue -ge 3758096384) {
        # 224.0.0.0/4
        $addressClassification = 'Multicast'
    } elseif (($addressValue -ge 3405803776) -and ($addressValue -le 3405804030)) {
        # 203.0.113.0/24
        $addressClassification = 'TEST-NET-3'
    } elseif (($addressValue -ge 3325256704) -and ($addressValue -le 3325256958)) {
        # 192.51.100.0/24
        $addressClassification = 'TEST-NET-2'
    } elseif (($addressValue -ge 3323068416) -and ($addressValue -le 3323199487)) {
        # 192.18.0.0/15
        $addressClassification = 'Network interconnect device benchmark testing'
    } elseif (($addressValue -ge 3232235520) -and ($addressValue -le 3232301055)) {
        # 192.168.0.0/16
        $addressClassification = 'Private'
    } elseif (($addressValue -ge 3221225984) -and ($addressValue -le 3221226239)) {
        # 192.0.2.0/24
        $addressClassification = 'TEST-NET-1'
    } elseif (($addressValue -ge 3221225472) -and ($addressValue -le 3221225727)) {
        # 192.0.0.0/24
        $addressClassification = 'IETF protocol assignments'
    } elseif (($addressValue -ge 2886729728) -and ($addressValue -le 2886795263)) {
        # 172.16.0.0/12
        $addressClassification = 'Private'
    } elseif (($addressValue -ge 2851995648) -and ($addressValue -le 2852061183)) {
        # 169.254.0.0/16
        $addressClassification = 'Link-Local'
    } elseif ($addressValue -eq 2130720053) {
        # 127.0.53.53
        $addressClassification = 'Name collision occurrence'
    } elseif (($addressValue -ge 2130706432) -and ($addressValue -le 2147483647)) {
        # 127.0.0.0/8
        $addressClassification = 'Loopback'
    } elseif (($addressValue -ge 171966464) -and ($addressValue -le 176160767)) {
        # 100.64.0.0/10
        $addressClassification = 'Carrier-grade NAT'
    } elseif (($addressValue -ge 167772160) -and ($addressValue -le 184549375)) {
        # 10.0.0.0/8
        $addressClassification = 'Private'
    } elseif ($addressValue -le 16777215) {
        # 0.0.0.0/8
        $addressClassification = 'This network'
    } 
    return $addressClassification
}