DavinciPS.psm1
Function Get-SubnetAddresses { Param ([IPAddress]$IP,[ValidateRange(0, 32)][int]$maskbits) # Convert the mask to type [IPAddress] #IP address is built backwards $mask = ([Math]::Pow(2, $MaskBits) - 1) * [Math]::Pow(2, (32 - $MaskBits)) $maskbytes = [BitConverter]::GetBytes([UInt32] $mask) $DottedMask = [IPAddress]((3..0 | ForEach-Object { [String] $maskbytes[$_] }) -join '.') # bitwise AND them together to get the subnet ID $lower = [IPAddress] ( $ip.Address -band $DottedMask.Address ) # Similar operation for the broadcast address # subnet mask bytes need to be inverted and reversed before adding $LowerBytes = [BitConverter]::GetBytes([UInt32] $lower.Address) [IPAddress]$upper = (0..3 | %{$LowerBytes[$_] + ($maskbytes[(3-$_)] -bxor 255)}) -join '.' # Make an object for use elsewhere Return [pscustomobject][ordered]@{ Lower=$lower Upper=$upper } } Function Get-IPRange { param ( [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName)][IPAddress]$lower, [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName)][IPAddress]$upper ) $IPList = [Collections.ArrayList]::new() $null = $IPList.Add($lower) $i = $lower # increment ip until reaching $upper in range while ( $i -ne $upper ) { # IP octet values are built back-to-front, so reverse the octet order $iBytes = [BitConverter]::GetBytes([UInt32] $i.Address) [Array]::Reverse($iBytes) #+1 the int value and reverse again $nextBytes = [BitConverter]::GetBytes([UInt32]([bitconverter]::ToUInt32($iBytes,0) +1)) [Array]::Reverse($nextBytes) # Convert to IP and add to list $i = [IPAddress]$nextBytes $null = $IPList.Add($i) } return $IPList } function Get-AvailableIPs { param ( $networkAddress, $CIDR, $DNSZone, $serverName ) #Get a list of IP addresses $referenceList = Get-SubnetAddresses $networkAddress $CIDR | Get-IPRange | Select-Object -ExpandProperty IPAddressToString #Query DNS to get a list of entries $result = Get-DnsServerResourceRecord -ZoneName $DNSZone -ComputerName $serverName | Where-Object {$_.RecordData.ipv4address -like "1*"} | Select-Object -Property @{Name = "IP Address"; Expression={$_.RecordData.IPv4Address}} #Compare the two lists $compare = Compare-Object -ReferenceObject $referenceList -DifferenceObject $result."IP Address" -IncludeEqual #Format the list to show a friendly label $compare | ForEach-Object{ if($_.sideIndicator -eq '<='){ $_.sideIndicator = " Avalible" } if($_.sideIndicator -eq '=>'){ $_.sideIndicator = " In use " } if($_.sideIndicator -eq '=='){ $_.sideIndicator = " In use " } } #Display the results of the comparison to the user $compare | Select-Object @{Name="IP Address";Expression={$_.InputObject}}, @{Name="Status";Expression={$_.sideIndicator}} } Export-ModuleMember -Function Get-AvailableIPs |