-
Notifications
You must be signed in to change notification settings - Fork 0
/
1_Parameter_Get-FreeIpAddresses.ps1
117 lines (96 loc) · 4.11 KB
/
1_Parameter_Get-FreeIpAddresses.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
param (
[String]$NetworkName,
[String]$ResourceGroupName,
[String]$SubnetName
)
# Usage: .\1_Parameter_Get-FreeIpAddresses.ps1 -NetworkName GlobalAzureBootcamp2019-vnet -ResourceGroupName GlobalAzureBootcamp2019
function Get-SubnetAddress {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string]
$Subnet
)
# Website: https://powershell.org/forums/topic/ip-address-math/
# Copyright: (c) 2014 Dave Wyatt
$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 '^(?<address>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/(?<mask>\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
}
}
function Get-IPAddressFromUInt32 {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[UInt32]
$UInt32
)
# Website: https://powershell.org/forums/topic/ip-address-math/
# Copyright: (c) 2014 Dave Wyatt
$bytes = [BitConverter]::GetBytes($UInt32)
if ([BitConverter]::IsLittleEndian) {
[Array]::Reverse($bytes)
}
return New-Object ipaddress(, $bytes)
}
function Get-UInt32FromIPAddress {
[OutputType('System.UInt32')]
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[ipaddress]
$IPAddress
)
# Website: https://powershell.org/forums/topic/ip-address-math/
# Copyright: (c) 2014 Dave Wyatt
$bytes = $IPAddress.GetAddressBytes()
if ([BitConverter]::IsLittleEndian) {
[Array]::Reverse($bytes)
}
return [BitConverter]::ToUInt32($bytes, 0)
}
if ($SubnetName) {
$SubnetConfiguration = Get-AzureRmVirtualNetwork -ExpandResource "subnets/ipConfigurations" -Name $NetworkName -ResourceGroupName $ResourceGroupName | Select-Object -ExpandProperty Subnets | Where-Object { $_.Name -eq $SubnetName}
}
else {
$SubnetConfiguration = Get-AzureRmVirtualNetwork -ExpandResource "subnets/ipConfigurations" -Name $NetworkName -ResourceGroupName $ResourceGroupName | Select-Object -ExpandProperty Subnets
}
foreach ($Subnet in $SubnetConfiguration) {
$PossibleIpAddresses = Get-SubnetAddress -Subnet "$($Subnet.AddressPrefix)" | Select-Object -ExpandProperty IPAddressToString
$UsedIpAddresses = $Subnet.ipConfigurations.privateIPAddress
if ([string]::IsNullOrEmpty($UsedIpAddresses)) {
$FreeIPAddresses = $PossibleIpAddresses
}
else {
$FreeIPAddresses = Compare-Object -ReferenceObject $PossibleIpAddresses -DifferenceObject $UsedIpAddresses | Where-Object { $_.SideIndicator -eq "<="} | Select-Object -ExpandProperty InputObject
}
foreach ($IPAddress in $FreeIPAddresses) {
# First three address are reserved addresses in each subnet according to MSFT
# https://docs.microsoft.com/en-us/azure/virtual-network/virtual-networks-faq#are-there-any-restrictions-on-using-ip-addresses-within-these-subnets
if ($IPAddress -notin ( $PossibleIpAddresses | Select-Object -First 3 ) ) {
New-Object psobject -Property @{
"IPAddress" = $IPAddress
"Subnet" = $Subnet.Name
"VirtualNetworkName" = $NetworkName
"ResourceGroupName" = $ResourceGroupName
}
}
}
}