AutomatedLabWorkerInternals.psm1
#region Internals #region IP function Function Get-NetworkAddress { <# .Synopsis Takes an IP address and subnet mask then calculates the network address for the range. .Description Get-NetworkAddress returns the network address for a subnet by performing a bitwise AND operation against the decimal forms of the IP address and subnet mask. Get-NetworkAddress expects both the IP address and subnet mask in dotted decimal format. .Parameter IPAddress Any IP address within the network range. .Parameter SubnetMask The subnet mask for the network. #> [CmdLetBinding()] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [Net.IPAddress]$IPAddress, [Parameter(Mandatory = $True, Position = 1)] [Alias('Mask')] [Net.IPAddress]$SubnetMask ) Process { Return ConvertTo-DottedDecimalIP ((ConvertTo-DecimalIP $IPAddress) -BAnd (ConvertTo-DecimalIP $SubnetMask)) } } Function ConvertTo-Mask { <# .Synopsis Returns a dotted decimal subnet mask from a mask length. .Description ConvertTo-Mask returns a subnet mask in dotted decimal format from an integer value ranging between 0 and 32. ConvertTo-Mask first creates a binary string from the length, converts that to an unsigned 32-bit integer then calls ConvertTo-DottedDecimalIP to complete the operation. .Parameter MaskLength The number of bits which must be masked. #> [CmdLetBinding()] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [Alias('Length')] [ValidateRange(0, 32)] $MaskLength ) Process { Return ConvertTo-DottedDecimalIP ([Convert]::ToUInt32($(('1' * $MaskLength).PadRight(32, '0')), 2)) } } Function ConvertTo-MaskLength { <# .Synopsis Returns the length of a subnet mask. .Description ConvertTo-MaskLength accepts any IPv4 address as input, however the output value only makes sense when using a subnet mask. .Parameter SubnetMask A subnet mask to convert into length #> [CmdLetBinding()] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [Alias('Mask')] [Net.IPAddress]$SubnetMask ) Process { $Bits = "$( $SubnetMask.GetAddressBytes() | ForEach-Object -Process { [Convert]::ToString($_, 2) } )" $Bitsx = $Bits -Replace '[\s0]' Return $Bitsx.Length } } Function ConvertTo-DottedDecimalIP { <# .Synopsis Returns a dotted decimal IP address from either an unsigned 32-bit integer or a dotted binary string. .Description ConvertTo-DottedDecimalIP uses a regular expression match on the input string to convert to an IP address. .Parameter IPAddress A string representation of an IP address from either UInt32 or dotted binary. #> [CmdLetBinding()] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [String]$IPAddress ) process { switch -RegEx ($IPAddress) { '([01]{8}\.){3}[01]{8}' { return [String]::Join('.', $($IPAddress.Split('.') | ForEach-Object -Process { [Convert]::ToUInt32($_, 2) } )) } '\d' { $IPAddress = [UInt32]$IPAddress $dottedIP = $(For ($i = 3; $i -gt -1; $i--) { $remainder = $IPAddress % [Math]::Pow(256, $i) ($IPAddress - $remainder) / [Math]::Pow(256, $i) $IPAddress = $remainder } ) return [String]::Join('.', $dottedIP) } default { Write-Error 'Cannot convert this format' } } } } Function ConvertTo-DecimalIP { <# .Synopsis Converts a Decimal IP address into a 32-bit unsigned integer. .Description ConvertTo-DecimalIP takes a decimal IP, uses a shift-like operation on each octet and returns a single UInt32 value. .Parameter IPAddress An IP Address to convert. #> [CmdLetBinding()] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [Net.IPAddress]$IPAddress ) Process { $i = 3 $decimalIP = 0 $IPAddress.GetAddressBytes() | ForEach-Object -Process { $decimalIP += $_ * [Math]::Pow(256, $i) $i-- } Return [UInt32]$decimalIP } } Function ConvertTo-BinaryIP { <# .Synopsis Converts a Decimal IP address into a binary format. .Description ConvertTo-BinaryIP uses System.Convert to switch between decimal and binary format. The output from this function is dotted binary. .Parameter IPAddress An IP Address to convert. #> [CmdLetBinding()] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [Net.IPAddress]$IPAddress ) Process { Return [String]::Join('.', $($IPAddress.GetAddressBytes() | ForEach-Object -Process { [Convert]::ToString($_, 2).PadLeft(8, '0') } )) } } Function Get-BroadcastAddress { <# .Synopsis Takes an IP address and subnet mask then calculates the broadcast address for the range. .Description Get-BroadcastAddress returns the broadcast address for a subnet by performing a bitwise AND operation against the decimal forms of the IP address and inverted subnet mask. Get-BroadcastAddress expects both the IP address and subnet mask in dotted decimal format. .Parameter IPAddress Any IP address within the network range. .Parameter SubnetMask The subnet mask for the network. #> [CmdLetBinding()] Param ( [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] [Net.IPAddress]$IPAddress, [Parameter(Mandatory = $True, Position = 1)] [Alias('Mask')] [Net.IPAddress]$SubnetMask ) process { return ConvertTo-DottedDecimalIP $((ConvertTo-DecimalIP $IPAddress) -BOr ` ((-bnot (ConvertTo-DecimalIP $SubnetMask)) -band [UInt32]::MaxValue)) } } function Get-NetworkSummary { param ( [Parameter(Mandatory)] [String]$IPAddress, [Parameter(Mandatory)] [String]$SubnetMask ) If ($IPAddress.Contains('/')) { $temp = $IP.Split('/') $IPAddress = $temp[0] $SubnetMask = $temp[1] } If (!$SubnetMask.Contains('.')) { $SubnetMask = ConvertTo-Mask $SubnetMask } $decimalIP = ConvertTo-DecimalIP $IPAddress $decimalMask = ConvertTo-DecimalIP $SubnetMask $network = $decimalIP -BAnd $decimalMask $broadcast = $decimalIP -BOr ((-BNot $decimalMask) -BAnd [UInt32]::MaxValue) $networkAddress = ConvertTo-DottedDecimalIP $network $rangeStart = ConvertTo-DottedDecimalIP ($network + 1) $rangeEnd = ConvertTo-DottedDecimalIP ($broadcast - 1) $broadcastAddress = ConvertTo-DottedDecimalIP $broadcast $MaskLength = ConvertTo-MaskLength $SubnetMask $binaryIP = ConvertTo-BinaryIP $IPAddress $private = $false switch -RegEx ($binaryIP) { '^1111' { $class = 'E' $subnetBitMap = '1111' } '^1110' { $class = 'D' $subnetBitMap = '1110' } '^110' { $class = 'C' If ($binaryIP -Match '^11000000.10101000') { $private = $True } } '^10' { $class = 'B' If ($binaryIP -Match '^10101100.0001') { $private = $True } } '^0' { $class = 'A' If ($binaryIP -Match '^00001010') { $private = $True } } } $netInfo = New-Object -TypeName Object Add-Member -MemberType NoteProperty -Name 'Network' -InputObject $netInfo -Value $networkAddress Add-Member -MemberType NoteProperty -Name 'Broadcast' -InputObject $netInfo -Value $broadcastAddress Add-Member -MemberType NoteProperty -Name 'Range' -InputObject $netInfo ` -Value "$rangeStart - $rangeEnd" Add-Member -MemberType NoteProperty -Name 'Mask' -InputObject $netInfo -Value $SubnetMask Add-Member -MemberType NoteProperty -Name 'MaskLength' -InputObject $netInfo -Value $MaskLength Add-Member -MemberType NoteProperty -Name 'Hosts' -InputObject $netInfo ` -Value $($broadcast - $network - 1) Add-Member -MemberType NoteProperty -Name 'Class' -InputObject $netInfo -Value $class Add-Member -MemberType NoteProperty -Name 'IsPrivate' -InputObject $netInfo -Value $private return $netInfo } <#Work in progress function Test-SubnetInSubnet { param ( [Parameter(Mandatory)] $SubNets, [Parameter(Mandatory)] [String]$IPAddress, [Parameter(Mandatory)] [String]$SubnetMask ) If ($IPAddress.Contains('/')) { $temp = $IP.Split('/') $IPAddress = $temp[0] $SubnetMask = $temp[1] } If (!$SubnetMask.Contains('.')) { $SubnetMask = ConvertTo-Mask $SubnetMask } $decimalIP = ConvertTo-DecimalIP $IPAddress $decimalMask = ConvertTo-DecimalIP $SubnetMask $network = $decimalIP -BAnd $decimalMask $broadcast = $decimalIP -BOr ((-BNot $decimalMask) -BAnd [UInt32]::MaxValue) $networkAddress = ConvertTo-DottedDecimalIP $network $rangeStart = ConvertTo-DottedDecimalIP ($network + 1) $rangeEnd = ConvertTo-DottedDecimalIP ($broadcast - 1) $broadcastAddress = ConvertTo-DottedDecimalIP $broadcast $MaskLength = ConvertTo-MaskLength $SubnetMask $binaryIP = ConvertTo-BinaryIP $IPAddress $private = $false switch -RegEx ($binaryIP) { '^1111' { $class = 'E' $subnetBitMap = '1111' } '^1110' { $class = 'D' $subnetBitMap = '1110' } '^110' { $class = 'C' If ($binaryIP -Match '^11000000.10101000') { $private = $True } } '^10' { $class = 'B' If ($binaryIP -Match '^10101100.0001') { $private = $True } } '^0' { $class = 'A' If ($binaryIP -Match '^00001010') { $private = $True } } } $netInfo = New-Object -TypeName Object Add-Member -MemberType NoteProperty -Name 'Network' -InputObject $netInfo -Value $networkAddress Add-Member -MemberType NoteProperty -Name 'Broadcast' -InputObject $netInfo -Value $broadcastAddress Add-Member -MemberType NoteProperty -Name 'Range' -InputObject $netInfo ` -Value "$rangeStart - $rangeEnd" Add-Member -MemberType NoteProperty -Name 'Mask' -InputObject $netInfo -Value $SubnetMask Add-Member -MemberType NoteProperty -Name 'MaskLength' -InputObject $netInfo -Value $MaskLength Add-Member -MemberType NoteProperty -Name 'Hosts' -InputObject $netInfo ` -Value $($broadcast - $network - 1) Add-Member -MemberType NoteProperty -Name 'Class' -InputObject $netInfo -Value $class Add-Member -MemberType NoteProperty -Name 'IsPrivate' -InputObject $netInfo -Value $private $startIP = ($rangeStart.split('.')[0] * 256*256*256) + ($rangeStart.split('.')[1] * 256*256) + ($rangeStart.split('.')[2] * 256) + ($rangeStart.split('.')[3]) $endIP = ($rangeEnd.split('.')[0] * 256*256*256) + ($rangeEnd.split('.')[1] * 256*256) + ($rangeEnd.split('.')[2] * 256) + ($rangeEnd.split('.')[3]) if (([ipaddress]$IpAddress).Address -ge ([ipaddress]$rangeStart).Address -and ([ipaddress]$IpAddress).Address -le ([ipaddress]$rangeEnd).Address) { $true } else { $false } } #> function Get-NetworkRange { param ( [string]$IPAddress, [string]$SubnetMask ) if ($IPAddress.Contains('/')) { $temp = $IPAddress.Split('/') $IPAddress = $temp[0] $SubnetMask = $temp[1] } If (-not $SubnetMask.Contains('.')) { $SubnetMask = ConvertTo-Mask -MaskLength $SubnetMask } $decimalIP = ConvertTo-DecimalIP -IPAddress $IPAddress $decimalMask = ConvertTo-DecimalIP -IPAddress $SubnetMask $network = $decimalIP -band $decimalMask $broadcast = $decimalIP -bor ((-bnot $decimalMask) -band [UInt32]::MaxValue) for ($i = $($network + 1); $i -lt $broadcast; $i++) { ConvertTo-DottedDecimalIP -IPAddress $i } } #region Function Test-IpInSameSameNetwork Function Test-IpInSameSameNetwork { param ( [AutomatedLab.IPNetwork]$Ip1, [AutomatedLab.IPNetwork]$Ip2 ) $ip1Decimal = $Ip1.SerializationNetworkAddress $ip2Decimal = $Ip2.SerializationNetworkAddress $ip1Total = $Ip1.Total $ip2Total = $Ip2.Total if (($ip1Decimal -ge $ip2Decimal) -and ($ip1Decimal -lt ([long]$ip2Decimal+[long]$ip2Total))) { return $true } if (($ip2Decimal -ge $ip1Decimal) -and ($ip2Decimal -lt ([long]$ip1Decimal+[long]$ip1Total))) { return $true } return $false } #endregion Test-IpInSameSameNetwork #endregion IP functions #region Get-Type (helper function for creating generic types) function Get-Type { param ( [Parameter(Position = 0, Mandatory = $True)] [string] $GenericType, [Parameter(Position = 1, Mandatory = $True)] [string[]] $T ) $T = $T -as [type[]] try { $generic = [type]($GenericType + '`' + $T.Count) $generic.MakeGenericType($T) } catch [Exception] { throw New-Object -TypeName System.Exception -ArgumentList ('Cannot create generic type', $_.Exception) } } #endregion #region Invoke-Ternary function Invoke-Ternary ([scriptblock]$decider, [scriptblock]$ifTrue, [scriptblock]$ifFalse) { if (&$decider) { &$ifTrue } else { &$ifFalse } } Set-Alias -Name ?? -Value Invoke-Ternary -Option AllScope -Description "Ternary Operator like '?' in C#" #endregion #endregion Internals |