IP Address Math

Tagged: ,

This topic contains 3 replies, has 3 voices, and was last updated by Profile photo of Dave Wyatt Dave Wyatt 2 years, 7 months ago.

  • Author
    Posts
  • #14968
    Profile photo of techguytj
    techguytj
    Member

    Is there a native way in PowerShell to do IP math? Take for example I want to use the network 10.0.0.0/22 and find all pingable devices on the network. It's a simple example but I should be able to loop through all the address by giving it the CIDR notation or a network with subnet. How should I go about accomplishing this?

  • #15040
    Profile photo of Peter Jurgens
    Peter Jurgens
    Participant

    Sorry to go off topic a bit, but I like the way that you use

    and in your regex pattern to name the keys in the $matches hash table. Is there any documentation on this feature? I've never seen it done before...
  • #14969
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    As luck would have it, this was part of the practice event in the scripting games (given CIDR notation of a subnet, identify computers on the subnet, collect inventory data, etc.) Here's how I accomplished it:

    function Get-UInt32FromIPAddress
    {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory)]
            [ipaddress]
            $IPAddress
        )
    
        $bytes = $IPAddress.GetAddressBytes()
    
        if ([BitConverter]::IsLittleEndian)
        {
            [Array]::Reverse($bytes)
        }
    
        return [BitConverter]::ToUInt32($bytes, 0)
    }
    
    function Get-IPAddressFromUInt32
    {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory)]
            [UInt32]
            $UInt32
        )
    
        $bytes = [BitConverter]::GetBytes($UInt32)
                
        if ([BitConverter]::IsLittleEndian)
        {
            [Array]::Reverse($bytes)
        }
    
        return New-Object ipaddress(,$bytes)
    }
    
    function Get-SubnetAddresses
    {
        # Converts an IPv4 subnet address in CIDR notation (ie, 192.168.0.0/24) into a collection of [ipaddress] objects.
    
        [CmdletBinding()]
        param (
            [Parameter(Mandatory)]
            [string]
            $Subnet
        )
    
        $ipaddress = $null
    
        # Validating the string format here instead of in a ValidateScript block allows us to use the
        # $ipaddress and $matches variables without having to perform the parsing twice.
    
        if ($Subnet -notmatch '^(?
    \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/(?\d{1,2})$') { throw "Subnet address '$Subnet' does not match the expected CIDR format (example: 192.168.0.0/24)" } if (-not [ipaddress]::TryParse($matches['Address'], [ref]$ipaddress)) { throw "Subnet address '$Subnet' contains an invalid IPv4 address." } $maskDecimal = [int]$matches['Mask'] if ($maskDecimal -gt 30) { throw "Subnet address '$Subnet' contains an invalid subnet mask (must be less than or equal to 30)." } $hostBitCount = 32 - $maskDecimal $netMask = [UInt32]0xFFFFFFFFL -shl $hostBitCount $hostMask = -bnot $netMask $networkAddress = (Get-UInt32FromIPAddress -IPAddress $ipaddress) -band $netMask $broadcastAddress = $networkAddress -bor $hostMask for ($address = $networkAddress + 1; $address -lt $broadcastAddress; $address++) { Get-IPAddressFromUInt32 -UInt32 $address } }

    I could then call the Get-SubnetAddresses function and either pipe it to something, or just save the results as an array to be enumerated with a foreach loop.

    Edit: Looking over this code again, I should probably note that it requires PowerShell 3.0 or later (for the -shl operator). It can be modified to work with PowerShell 2.0, but the code would be a little bit harder to read. "$netMask = [UInt32]0xFFFFFFFFL -shl $hostBitCount" would become something like "$netMask = ([UInt32]((0xFFFFFFFL * [math]::Pow(2, $hostBitCount)) -band 0xFFFFFFFFL))"

  • #15044
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Those are called "named groups". You can find all of the official documentation on .NET regular expressions on MSDN, and http://www.regular-expressions.info/ is also quite a good reference (covering more than just the .NET implementation, plus a lot of good tutorials in general.)

You must be logged in to reply to this topic.