01 / ADDRESSING AND INVENTORY · LESSON 03

Test IPv4 subnet membership

Compare addresses by prefix, including default, point-to-point, and host prefixes.

15 min · learn at your pace

A prefix identifies an address block

A CIDR such as 192.0.2.0/24 has 24 network bits and 8 remaining bits. Its block size is 2^(32 - prefix length). Two IPv4 numbers are in the same block when dividing by that size and rounding down produces the same quotient.

Dot-source AddressMath.ps1 to use the strict converter from the previous lesson. Parse the slash and validate a canonical decimal prefix from 0 to 32. This exercise accepts host bits in the prefix address: 192.0.2.99/24 identifies the same block as 192.0.2.0/24.

[math]::Pow(2, 32 - 24)

Membership is not host assignability

The first and last address are both members of a prefix. Do not subtract network or broadcast addresses from a membership test. A /0 contains every IPv4 address, a /32 contains one, and a /31 contains two. On appropriately configured point-to-point links, both /31 addresses can be used as endpoints.

Use a wide value for the block size: /0 requires 4,294,967,296. A shift on a 32-bit integer by 32 does not provide a reliable /0 shortcut. Avoid enumerating all addresses; a membership decision needs only arithmetic.

The function returns one boolean and throws on malformed addresses or prefixes. It performs no packet transmission or connectivity test.

Go deeper

Read the official reference.

Try an example.ps1
. '/home/user/AddressMath.ps1'
ConvertTo-IPv4Number '192.0.2.10'
YOUR TURN

Put it into practice.

Dot-source AddressMath.ps1 and define Test-IPv4Subnet -Address -Cidr. Return a boolean for membership, including the first and last address. Accept prefix lengths 0–32 with no leading zeros, and normalise host bits by comparing blocks. Throw for malformed addresses/CIDRs. Do not enumerate addresses.

See an explained solution
One way to solve it.ps1
. '/home/user/AddressMath.ps1'
function Test-IPv4Subnet {
    param([string]$Address,[string]$Cidr)
    $parts = $Cidr.Split('/')
    if ($parts.Count -ne 2 -or $parts[1] -cnotmatch '\A(?:0|[1-9][0-9]?)\z' -or [int]$parts[1] -gt 32) { throw 'Invalid IPv4 prefix length.' }
    $addressValue = ConvertTo-IPv4Number $Address
    $prefixValue = ConvertTo-IPv4Number $parts[0]
    [uint64]$blockSize = [math]::Pow(2, 32 - [int]$parts[1])
    return [bool]([math]::Floor($addressValue / $blockSize) -eq [math]::Floor($prefixValue / $blockSize))
}

Block arithmetic handles /0, /31, and /32 without special host-count assumptions. The converter rejects malformed address text before a numeric comparison.