Get-PowerIP2CIDR.ps1
<#
.SYNOPSIS Converts provided range to CIDR or splits provided CIDR to subnet blocks. .DESCRIPTION Function utilized by Test-PowerPing to convert range to CIDR. .NOTES Author: Hunter Hirsch #> ## Tables to assist with increment calculations $zfact = 2,4,8,16,32,64,128 $rincr = @{ '32' = 1 '0,8,16,24' = 255 '1,9,17,25' = 128 '2,10,18,26' = 64 '3,11,19,27' = 32 '4,12,20,28' = 16 '5,13,21,29' = 8 '6,14,22,30' = 4 '7,15,23,31' = 2 } $rbases = @{ '0,1,2,3,4,5,6,7' = 0 '8,9,10,11,12,13,14,15' = 1 '16,17,18,19,20,21,22,23' = 2 '24,25,26,27,28,29,30,31' = 3 } ## Function to determine increment increase between blocks when increasing block size (small to large) function Get-ppblkup { Param( [Parameter (Mandatory)] [byte] $bfact, [Parameter (Mandatory)] [uint32] $last ) $cfact = $null if ($bfact-ne 0){ for (($i = $bfact),($k = 2); ($i/$k).GetType().name -ne 'Double' -and $k -le 128; $k = $k*2){ $cfact = $k } } Else{ $last++ if ($last -lt 256){ for ($i = 0; $last -ge $zfact[$i] -and $i -le 6; $i++){ $cfact = $zfact[$i] } } Else{ $cfact = 255 } } return $cfact } ## Function to determine increment difference when decreasing block size (large to small) function Get-ppblkdwn { Param( [Parameter (Mandatory)] [byte] $s, [Parameter (Mandatory)] [byte] $e, [Parameter (Mandatory)] [uint32] $dif ) $fact = get-ppblkup -bfact $s -last $e if ($s -eq 0){ $dif++ } while ($fact -gt $dif){ $fact = $zfact[(($zfact.IndexOf($fact)) -1)] } return $fact } ## Function to convert range to CIDR with fewest possible blocks function Get-PPCIDRMin{ Param( [Parameter (Mandatory)] [byte[]] $Start, [Parameter (Mandatory)] [byte[]] $End, [Parameter (Mandatory)] [int32] $base ) Begin{ if ($Start[3]%2 -ne 0){ $odd = $true } if ($base -eq 3){ [uint32]$3dif = $End[3] - $Start[3] } Else{ $tblk = $base+1 $TB = $true if ($End[$base]%2 -ne 0){ while ($tblk -lt 4){ if ($End[$tblk] -ne 255){ $TB = $false } $tblk++ } } Else{ $TB = $false } } if ($odd -and $base -lt 3){ $cidque.Enqueue([string][ipaddress] $Start + '/32') $odd = $null if ($Start[3] -lt 255){ $Start[3]++ } Else{ if ($Start[2] -lt 255){ $Start[2]++ } Else{ $Start[2] = 0 if ($Start[1] -lt 255){ $Start[1]++ } Else{ $Start[1] = 0 if ($Start[0] -lt 255){ $Start[0]++ } } } $Start[3] = 0 } } if ($base -lt 3 -and $Start[3] -ne 0){ while ($Start[3] -ne 0){ $plus = get-ppblkup -bfact $Start[3] -last 255 $afact = ($rincr.Keys.Where({$rincr.$_ -eq $plus})).split(',')[3] $cidque.Enqueue([string][ipaddress] $Start + "/$afact") if (($Start[3] + $plus) -lt 255){ $Start[3] = $Start[3] + $plus } Else{ $Start[3] = 0 if ($Start[2] -lt 255){ $Start[2]++ } Else{ $Start[2] = 0 if ($Start[1] -lt 255){ $Start[1]++ } Else{ $Start[1] = 0 if ($Start[0] -lt 255){ $Start[0]++ } } } } } } } Process{ if ($base -lt 3){ for ($i = 2;!$stop; $i--){ if ($Start[$i] -ne 0 -and $base -lt $i){ while ($start[$i] -ne 0){ if ($Start[$i]%2 -ne 0){ $afact = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($i+1)] $cidque.Enqueue([string][ipaddress] $Start + "/$afact") if ($Start[$i] -lt 255){ $Start[$i]++ } Else{ $Start[$i] = 0 if ($i -gt 0){ if ($Start[($i-1)] -lt 255){ $Start[($i-1)]++ } Else{ $Start[($i-1)] = 0 if ($i -gt 1){ if ($Start[($i-2)] -lt 255){ $Start[($i-2)]++ } } } } } } if ($start[$i] -ne 0){ $plus = get-ppblkup -bfact $Start[$i] -last 255 $afact = ($rincr.Keys.Where({$rincr.$_ -eq $plus})).split(',')[$i] $cidque.Enqueue([string][ipaddress] $Start + "/$afact") if (($Start[$i] + $plus) -lt 255){ $Start[$i] = $Start[$i] + $plus } Else{ $Start[$i] = 0 if ($i -gt 0){ if ($Start[($i-1)] -lt 255){ $Start[($i-1)]++ } Else{ $Start[($i-1)] = 0 if ($i -gt 1){ if ($Start[($i-2)] -lt 255){ $Start[($i-2)]++ } } } } } } } } Elseif ($base -eq $i){ $bdif = $End[$i] - $Start[$i] if ($Start[$i]%2 -ne 0 -and $bdif -gt 0){ $afact = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($i+1)] $cidque.Enqueue([string][ipaddress] $Start + "/$afact") if ($Start[$i] -lt 255){ $Start[$i]++ } Else{ $Start[$i] = 0 if ($i -gt 0){ if ($Start[($i-1)] -lt 255){ $Start[($i-1)]++ } Else{ $Start[($i-1)] = 0 if ($i -gt 1){ if ($Start[($i-2)] -lt 255){ $Start[($i-2)]++ } } } } } $bdif = $End[$i] - $Start[$i] } if ($End[$i]%2 -ne 0 -and $TB){ $bdif = ($End[$i] +1) - $Start[$i] } while ($bdif -gt 0){ if ($bdif -gt 1 -and $TB){ $plus = get-ppblkdwn -s $Start[$i] -e $End[$i] -dif $bdif $afact = ($rincr.Keys.Where({$rincr.$_ -eq $plus})).split(',')[$i] $cidque.Enqueue([string][ipaddress] $Start + "/$afact") if (($Start[$i] + $plus) -lt 255){ $Start[$i] = $Start[$i] + $plus } Else{ $Start[$i] = 255 } if ($End[$i]%2 -ne 0){ $bdif = ($End[$i] +1) - $Start[$i] if ($bdif -eq 1){ $bdif = 0 } } Else{ $bdif = $End[$i] - $Start[$i] } } if ($bdif -gt 1 -and !$TB){ if ($End[$i] -eq 255){ [byte]$iEnd = 254 } Else{ $iEnd = $End[$i] } if ($Start[$i] -eq 0){ $iEnd-- } $plus = get-ppblkdwn -s $Start[$i] -e $iEnd -dif $bdif $afact = ($rincr.Keys.Where({$rincr.$_ -eq $plus})).split(',')[$i] $cidque.Enqueue([string][ipaddress] $Start + "/$afact") $Start[$i] = $Start[$i] + $plus $bdif = $End[$i] - $Start[$i] } if ($bdif -eq 1){ if ($Start[$i]%2 -ne 0){ $ifact = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($i+1)] $cidque.Enqueue([string][ipaddress] $Start + "/$ifact") if ($Start[$i] -lt 255){ $Start[$i]++ } if ($TB){ $stop = $true } } Else{ if ($TB){ $ifact = ($rincr.Keys.Where({$rincr.$_ -eq 2})).split(',')[$i] $cidque.Enqueue([string][ipaddress] $Start + "/$ifact") $Start[$i] = $Start[$i]+2 $stop = $true } Else{ $ifact = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($i+1)] $cidque.Enqueue([string][ipaddress] $Start + "/$ifact") $Start[$i]++ } } $bdif = 0 } } if ($TB -and $bdif -eq 0){ $stop = $true } } if (!$TB -and $base -eq $i){ if ($base -eq 0 -and $end[3] -eq 255){ $jcheck = $true } for ($j = $base+1; $j -lt 3; $j++){ $jdif = $End[$j] - $Start[$j] while ($Start[$j] -ne $End[$j]){ if ($jdif -gt 1){ if ($End[($j+1)] -ne 255){ $jEnd = $End[$j] -1 if ($Start[$j] -eq 0 -and $End[$j]%2 -ne 0){ $jEnd-- } } Else{ if ($jcheck -or $j -eq 2){ $jEnd = $End[$j] if ($jEnd%2 -ne 0){ $jdif++ } } Else{ $jEnd = $End[$j] -1 if ($Start[$j] -eq 0 -and $End[$j]%2 -ne 0){ $jEnd-- } } } $plus = get-ppblkdwn -s $Start[$j] -e $jEnd -dif $jdif $afact = ($rincr.Keys.Where({$rincr.$_ -eq $plus})).split(',')[$j] $cidque.Enqueue([string][ipaddress] $Start + "/$afact") $Start[$j] = $Start[$j] + $plus $jdif = $End[$j] - $Start[$j] } if ($jdif -eq 1){ if ($End[$j]%2 -ne 0){ if ($End[($j+1)] -eq 255){ if ($jcheck -or $j -eq 2){ $ifact = ($rincr.Keys.Where({$rincr.$_ -eq 2})).split(',')[($j)] } else{ $ifact = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($j+1)] } } Else{ $ifact = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($j+1)] } $cidque.Enqueue([string][ipaddress] $Start + "/$ifact") $Start[$j] = $End[$j] if ($j -eq 2 -or ($End[($j+1)] -eq 255 -and $End[3] -eq 255)){ $j = 4 } } Else{ $ifact = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($j+1)] $cidque.Enqueue([string][ipaddress] $Start + "/$ifact") $Start[$j]++ } } if ($jdif -le 0){ if ($End[$j]%2 -eq 0 -and ($End[($j+1)] -eq 255 -and $End[3] -eq 255) -and $j -lt 2){ $Start[$j] = $End[$j] $ifact = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($j+1)] $cidque.Enqueue([string][ipaddress] $Start + "/$ifact") } if ($j -eq 2 -or ($End[($j+1)] -eq 255 -and $End[3] -eq 255)){ $j = 4 } } } } If ($End[3] -ne 255){ $3dif = $End[3] } else{ $test = $Start.Clone() $test[3] = 255 if ([string][ipaddress] $test -eq [string][ipaddress] $End -and $End[2]%2 -eq 0){ $cidque.Enqueue([string][ipaddress] $Start + '/24') } $test = $null } $stop = $true } } } if ($3dif){ if ($3dif -eq 1){ if ($odd){ $cidque.Enqueue([string][ipaddress] $Start + '/32') $cidque.Enqueue([string][ipaddress] $End + '/32') } Else{ $cidque.Enqueue([string][ipaddress] $Start + '/31') } } Else{ if ($odd -and $base -eq 3){ $cidque.Enqueue([string][ipaddress] $Start + '/32') $Start[3]++ $3dif-- } if ($3dif -eq 1){ $cidque.Enqueue([string][ipaddress] $Start + '/31') } Else{ while ($3dif -gt 0){ if ($3dif -gt 1){ if ($zfact -contains ($3dif+1)){ $3dif++ if ($end[3] -lt 255){ $end[3]++ } $3end = $true } $plus = get-ppblkdwn -s $Start[3] -e $End[3] -dif $3dif $afact = ($rincr.Keys.Where({$rincr.$_ -eq $plus})).split(',')[3] $cidque.Enqueue([string][ipaddress] $Start + "/$afact") if (($Start[3] + $plus) -lt 255){ $Start[3] = $Start[3] + $plus } Else{ $Start[3] = 255 } if ($End[3] -eq 255){ $3dif = 256 - $Start[3] if ($3dif -eq 1){ $3dif = 256 } } Else{ $3dif = $End[3] - $Start[3] } } if ($3dif -eq 1){ if (($Start[3]/2).GetType().Name -eq 'Double'){ $cidque.Enqueue([string][ipaddress] $Start + '/32') $cidque.Enqueue([string][ipaddress] $End + '/32') } Else{ $cidque.Enqueue([string][ipaddress] $Start + '/31') } $3dif = 0 } Elseif (!$3end -and $3dif -eq 0){ $cidque.Enqueue([string][ipaddress] $Start + '/32') } Elseif ($3dif -eq 256){ $3dif = 0 } } } } } Elseif ($3dif -eq 0 -and $End[3] -eq 0){ $cidque.Enqueue([string][ipaddress] $Start + '/32') } } End{ } } ## Function to split range/CIDR into sub blocks function Get-PowerIP2CIDR{ [CmdletBinding()] [OutputType([system.collections.arraylist])] Param( [Parameter(Mandatory)] [string] $Begin, [Parameter(Mandatory)] [string] $Finish, [Parameter(Mandatory)] [string] $factor, [Parameter()] [switch] $full ) Begin{ $cidque = [System.Collections.Queue]::new() $cidlist = [System.Collections.ArrayList]::new() [byte[]]$starr = $Begin.Split('.') [byte[]]$edarr = $Finish.split('.') [string]$adbal = ($edarr[0] - $starr[0]),($edarr[1] - $starr[1]),($edarr[2] - $starr[2]),($edarr[3] - $starr[3]) $adbal = $adbal.Replace(" ",'') if ($adbal[0] -eq '-' -or $adbal -match "^[0]{1,3}-"){ [byte[]]$starr = $Finish.split('.') [byte[]]$edarr = $Begin.Split('.') } $rbase = 0 for (($i=0); $starr[$i] -eq $edarr[$i]; $i++){ $rbase++ } if (1..31 -contains $factor){ $basediff = ($edarr[$rbase] - $starr[$rbase]) +1 $plustable = $rincr.Values | Sort-Object $fplus = $rincr.Keys.Where({$_.split(',') -contains $factor}) | ForEach-Object {$rincr.$_} for ($i = 0; $basediff -ge $plustable[$i] -and $i -le 8; $i++){ if ($basediff -gt 1){ $fmax = ($rincr.Keys.Where({$rincr.$_ -eq $plustable[$i]})).split(',')[$rbase] } Else{ $fmax = ($rincr.Keys.Where({$rincr.$_ -eq 255})).split(',')[($rbase+1)] } } if ([int32]$factor -eq $fmax){ if ($starr[$rbase]%2 -ne 0 -and $plustable -contains $basediff){ $invalidfactor = $true } Else{ if ($basediff -eq $fplus){ for ($i = $rbase +1; $i -le 3; $i++){ if ($starr[$i] -ne 0 -or $edarr[$i] -ne 255){ $invalidfactor = $true } } } if ($basediff -gt $fplus){ $fmaxbase = $starr.Clone() while ($fmaxbase[$rbase]%$fplus -ne 0){ $fmaxbase[$rbase]++ if ($fmaxbase[$rbase] -eq 255){ $invalidfactor = $true $fmaxbase[$rbase] = $fplus } } if (!$invalidfactor){ if ($edarr[$rbase] -eq 255 -and $rbase -lt 3){ for ($i = $rbase + 1; $i -le 3; $i++){ if ($edarr[$i] -ne 255){ $invalidfactor = $true } } } Else{ if (($fmaxbase[$rbase] + $fplus) -gt $edarr[$rbase]){ $invalidfactor = $true } if (($fmaxbase[$rbase] + $fplus) -eq $edarr[$rbase] -and $rbase -lt 3){ for ($i = $rbase +1; $i -le 3; $i++){ if ($starr[$i] -ne 0){ $invalidfactor = $true } } } } } } } } if ([int32]$factor -lt $fmax -or !$fmax -or $invalidfactor){ Throw Write-Output "Divider block size: $factor greater than provided Start/End range. Update parameters and try again." } for ($i = $rbase; $i -le 3; $i++){ if (($rbases.Keys.Where({$rbases.$_ -eq $i})).split(',') -contains $factor){ $fbase = $i } } if ($starr[3]%2 -ne 0){ $cidque.Enqueue([string][ipaddress] $starr + '/32') if ($starr[3] -lt 255){ $starr[3]++ } Else{ $starr[3] = 0 if ($starr[2] -lt 255){ $starr[2]++ } Else{ $starr[2] = 0 if ($starr[1] -lt 255){ $starr[1] ++ } Else{ $starr[1] = 0 if ($starr[0] -lt 255){ $starr[0]++ } } } } } if ($starr[$fbase]%$fplus -eq 0){ if ($starr[$fbase] -ne 255){ $validstart = $true for ($i = $fbase + 1; $i -le 3; $i++){ if ($starr[$i] -ne 0){ $validstart = $false } } } } if (!$validstart){ $bstarr = $starr.Clone() for ($i = 3;$i -ge $fbase; $i--){ if ($i -ne $fbase){ $bstarr[$i] = 255 } Else{ if ($bstarr[$i] -ne 0){ if ($bstarr[$i]%$fplus -ne 0){ while ($bstarr[$i]%$fplus -ne 0 -and !$cap){ if ($bstarr[$i] -lt 255){ $bstarr[$i]++ } Else{ $bstarr[$i] = 255 $cap = $true } } } Else{ if (($bstarr[$i] + $fplus) -lt 255){ $bstarr[$i] = $bstarr[$i] + $fplus } Else{ $bstarr[$i] = 255 } } } Else{ if ($fplus -ne 255){ $bstarr[$i] = $bstarr[$i] + $fplus -1 } Else{ $bstarr[$i] = 255 } } } } if ($bstarr[$fbase]%2 -eq 0 -and $bstarr[$fbase] -ne $starr[$fbase]){ $bstarr[$fbase]-- } $fstart = $bstarr } $validend = $true for ($i = $fbase; $i -le 3; $i++){ if ($i -eq $fbase){ if ($edarr[$i]%2 -eq 0){ $validend = $false } Elseif ($edarr[$i] -ne 255){ if ($fplus -eq 255){ $validend = $false } Else{ $tplus = $fplus $tpt = $false while ($tplus -lt 255){ if ($edarr[$i] -eq ($tplus-1)){ $tpt = $true } $tplus = $tplus + $fplus } if (!$tpt){ $validend = $false } } } } Else{ if ($edarr[$i] -ne 255){ $validend = $false } } } if ($validend){ $bedarr = $edarr.Clone() if ($bedarr[$fbase] -lt 255){ $bedarr[$fbase]++ } Else{ $bedarr[$fbase] = 0 if ($bedarr[($fbase-1)] -lt 255){ $bedarr[($fbase-1)]++ } Else{ $bedarr[($fbase-1)]=0 if ($bedarr[($fbase-2)] -lt 255){ $bedarr[($fbase-2)]++ } Else{ $bedarr[($fbase-2)]=0 if ($bedarr[($fbase-3)] -lt 255){ $bedarr[($fbase-3)]++ } Else{ $bedarr[($fbase-3)] = 0 } } } } for ($i = $fbase+1; $i -le 3; $i++){ $bedarr[$i] = 0 } if ($bedarr[0] -eq 0 -and $edarr[0] -eq 255){ $bedarr[0] = 255 $endcatch = $true for ($i = $fbase; $i -gt 0; $i--){ if (('8,16,24').split(',') -contains $factor -and $edarr[($i-1)] -eq 255){ $bedarr[($i -1)] = 255 } elseif ($edarr[$i] -eq 255){ $bedarr[$i] = 255 } } } $fend = [ipaddress] $bedarr } if (!$validend){ $bedarr = $edarr.Clone() for ($i =3; $i -ge $fbase; $i--){ if ($i -ne $fbase){ $bedarr[$i] = 0 } Else{ if ($edarr[$i] -eq 255 -and $bedarr[$i] -eq 255){ if ($fplus -ne 255){ $bedarr[$i] = 256 - $fplus } Else{ $bedarr[$i] = 0 } } Elseif ($bedarr[$i] -ne 255){ if ($bedarr[$i] -le $fplus){ $bedarr[$i] = 0 } Elseif ($fplus -eq 2){ if ($bedarr[$i] -eq $edarr[$i]){ if (($bedarr[$i] - 2) -gt 0){ if ($bedarr[$i]%2 -ne 0){ $bedarr[$i]-- } Else{ $bedarr[$i] = $bedarr[$i] - 2 } } Else{ $bedarr[$i] = 0 } } } Elseif ($bedarr[$i] -gt $fplus){ $tplus = $fplus while (($tplus-1) -lt $bedarr[$i]){ $lastb = $tplus $tplus = $tplus + $fplus } $bedarr[$i] = $lastb } } } } $fend = [ipaddress] $bedarr } } Else{ $Minblock = $true } } Process{ if ($Minblock){ Get-PPCIDRMin -Start $starr -End $edarr -base $rbase } Else{ if (!$validstart){ Get-PPCIDRMin -Start $starr -End $fstart -base $fbase $starr = $fstart for ($i = 3; $i -ge $fbase; $i--){ if ($i -ne $fbase){ $starr[$i] = 0 } Else{ if ($starr[$i] -lt 255){ $starr[$i]++ } Else{ $starr[$i] = 0 if ($starr[($i-1)] -lt 255){ $starr[($i-1)]++ } Else{ $starr[($i-1)] = 0 if ($starr[($i-2)] -lt 255){ $starr[($i-2)]++ } Else{ $starr[($i-2)]=0 if ($starr[($i-3)] -lt 255){ $starr[($i-3)]++ } } } } } } if ($starr[$fbase]%2 -ne 0){ $starr[$fbase]-- } } while ([ipaddress] $starr -ne $fend){ $cidque.Enqueue([string][ipaddress] $starr + "/$factor") if ($fplus -ne 255){ if (($starr[$fbase] + $fplus) -lt 255){ $starr[$fbase] = $starr[$fbase] + $fplus } Elseif ($edarr[0] -eq 255 -and $fbase -eq 0){ $starr[0] = 255 } Elseif ($starr[0] -eq 255 -and $fbase -gt 0){ if ($starr[($fbase -1)] -lt 255){ $starr[($fbase -1)]++ $starr[($fbase)] = 0 } Else{ if ($fbase -eq 3){ if ($starr[1] -lt 255){ $starr[1]++ $starr[2] = 0 $starr[3] = 0 } Else{ $starr[3] = 255 } } Else{ $starr[$fbase] = 255 } } } Else{ $starr[$fbase] = 0 if ($starr[($fbase-1)] -lt 255){ $starr[($fbase-1)]++ } Else{ $starr[($fbase-1)] = 0 if ($starr[($fbase-2)] -lt 255){ $starr[($fbase-2)]++ } Else{ $starr[($fbase-2)] = 0 if ($starr[($fbase-3)] -lt 255){ $starr[($fbase-3)]++ } } } } } Else{ $starr[$fbase] = 0 if ($starr[($fbase-1)] -lt 255){ $starr[($fbase-1)]++ } Else{ $starr[($fbase-1)] = 0 if ($starr[($fbase-2)] -lt 255){ $starr[($fbase-2)]++ } Else{ $starr[($fbase-2)] = 0 if ($starr[($fbase-3)] -lt 255){ $starr[($fbase-3)]++ } } } } } if (!$validend){ $estart = $fend.GetAddressBytes() Get-PPCIDRMin -Start $estart -End $edarr -base $fbase } elseif ($endcatch){ if (('8,16,24').split(',') -contains $factor){ $cidque.Enqueue([string][ipaddress] $fend + "/$factor") } } } } End{ if ($cidque.Count -gt 1){ $null = $cidlist.AddRange($cidque) } Else{ $null = $cidlist.Add($cidque.Dequeue()) } if (!$full -and !$Minblock){ $cidlist.Where({$_ -match ("/$factor")}) } Else{ $cidlist } $cidque.Clear() $cidlist = $null; $cidque = $null [System.GC]::Collect() } } |