Search CIDR subnet ranges with powershell

I'd like to be able to search for an IP's within CIDR ranges/list, and output the information around that IP's CIDR file.
Very similar to this EE question https://www.experts-exchange.com/questions/29127048/Excel-CIDR-IP-Address-Overlap-Formula-Check-for-CIDR-IP-Address-Overlap.html

This is what I envision...
CIDR.csv
CIDR, Subnet_Name
10.0.0.0/24, Guest Network
10.10.0.0/23, Production
10.8.0.0/22, Telco
10.69.69.0/24, BoomChickaWowWow

Open in new window


.\findip.ps1 10.0.0.22
    Found: 10.0.0.22 - Guest Network 10.0.0.0/24

.\findip.ps1 10.8.0.123, 10.69.69.68, 10.1.2.3
   Found: 10.8.0.123 - Telco 10.8.0.0/22
   Found: 10.69.69.68 - BoomChickaWowWow
   Not Found: 10.1.2.3

FindIp would look inside the cidr.csv and then expand the CIDR's and seqrch for matches within.
LVL 38
Rich RumbleSecurity SamuraiAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

LearnctxEngineerCommented:
Rather than re-invent the wheel, try this script. Just find a method to that suites you for iterating through the subnets.

function IPInRange {
    [cmdletbinding()]
    [outputtype([System.Boolean])]
    param(
        # IP Address to find.
        [parameter(Mandatory,
                   Position=0)]
        [validatescript({
            ([System.Net.IPAddress]$_).AddressFamily -eq 'InterNetwork'
        })]
        [string]
        $IPAddress,

        # Range in which to search using CIDR notation. (ippaddr/bits)
        [parameter(Mandatory,
                   Position=1)]
        [validatescript({
            $IP   = ($_ -split '/')[0]
            $Bits = ($_ -split '/')[1]

            (([System.Net.IPAddress]($IP)).AddressFamily -eq 'InterNetwork')

            if (-not($Bits)) {
                throw 'Missing CIDR notiation.'
            } elseif (-not(0..32 -contains [int]$Bits)) {
                throw 'Invalid CIDR notation. The valid bit range is 0 to 32.'
            }
        })]
        [alias('CIDR')]
        [string]
        $Range
    )

    # Split range into the address and the CIDR notation
    [String]$CIDRAddress = $Range.Split('/')[0]
    [int]$CIDRBits       = $Range.Split('/')[1]

    # Address from range and the search address are converted to Int32 and the full mask is calculated from the CIDR notation.
    [int]$BaseAddress    = [System.BitConverter]::ToInt32((([System.Net.IPAddress]::Parse($CIDRAddress)).GetAddressBytes()), 0)
    [int]$Address        = [System.BitConverter]::ToInt32(([System.Net.IPAddress]::Parse($IPAddress).GetAddressBytes()), 0)
    [int]$Mask           = [System.Net.IPAddress]::HostToNetworkOrder(-1 -shl ( 32 - $CIDRBits))

    # Determine whether the address is in the range.
    if (($BaseAddress -band $Mask) -eq ($Address -band $Mask)) {
        $true
    } else {
        $false
    }
}

Open in new window


Source/Credit
oBdACommented:
Returns proper objects, entries not found in a range are written to the Warning stream by default; can be suppressed using -WarningAction SilentlyContinue, or you can use -IncludeNotFound, which will create an object as for the ones found, but obviously with the Subnet and CIDR columns empty.
Accepts pipeline input as well.
[CmdletBinding()]
Param(
	[Parameter(Position=0, ValueFromPipeline=$true)]
	[IPAddress[]]$IPAddress,
	[Switch]$IncludeNotFound
)
Begin {
	Function ConvertTo-DecimalAddress([IPAddress]$IPAddress) {
		$bytes = $IPAddress.GetAddressBytes()
		[array]::Reverse($bytes)
		[BitConverter]::ToUInt32($bytes, 0)
	}
	$data = Import-Csv -Path '.\CIDR.csv' | ForEach-Object {
		$firstAddress = ConvertTo-DecimalAddress -IPAddress $_.CIDR.Split('/')[0]
		$hosts = [math]::Pow(2, (32 - $_.CIDR.Split('/')[1])) - 1
		$_ | Select-Object -Property *, @{n='FirstAddress'; e={$firstAddress}}, @{n='LastAddress'; e={$firstAddress + $hosts}}
	}
}
Process {
	$IPAddress | ForEach-Object {
		$address = ConvertTo-DecimalAddress -IPAddress $_
		If ($row = $data | Where-Object {($_.FirstAddress -le $address) -and ($address -le $_.LastAddress)}) {
			$_ | Select-Object -Property @{n='IPAddress'; e={$_.ToString()}}, @{n='CIDR'; e={$row.CIDR}}, @{n='Subnet_Name'; e={$row.Subnet_Name}}
		} Else {
			If ($IncludeNotFound) {
				$_ | Select-Object -Property @{n='IPAddress'; e={$_.ToString()}}, CIDR, Subnet_Name
			} Else {
				Write-Warning "IP address $($_.ToString()) not found"
			}
		}
	}
}

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Rich RumbleSecurity SamuraiAuthor Commented:
Wow, you guys make this look easy! oBdA is getting the majority of the points, the solution worked great! I've got a /8 with 6k different CIDR subnets/names and this searches through all of it in few seconds! I will have some follow up questions soon, keep an eye out :)
-rich
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.