internal/Test-IpAddressInSubnet.ps1
<# .SYNOPSIS Determine if an IP address exists in the specified subnet. .EXAMPLE PS C:\>Test-IpAddressInSubnet 192.168.1.10 -Subnet '192.168.1.1/32','192.168.1.0/24' Determine if the IPv4 address exists in the specified subnet. .EXAMPLE PS C:\>Test-IpAddressInSubnet 2001:db8:1234::1 -Subnet '2001:db8:a::123/64','2001:db8:1234::/48' Determine if the IPv6 address exists in the specified subnet. .INPUTS System.Net.IPAddress .LINK https://github.com/jasoth/Utility.PS #> function Test-IpAddressInSubnet { [CmdletBinding()] [OutputType([bool], [string[]])] param ( # IP Address to test against provided subnets. [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 1)] [ipaddress[]] $IpAddresses, # List of subnets in CIDR notation. For example, "192.168.1.0/24" or "2001:db8:1234::/48". [Parameter(Mandatory = $true)] [string[]] $Subnets, # Return list of matching subnets rather than a boolean result. [Parameter(Mandatory = $false)] [switch] $ReturnMatchingSubnets ) begin { function ConvertBitArrayToByteArray([System.Collections.BitArray] $BitArray) { [byte[]] $ByteArray = New-Object byte[] ([System.Math]::Ceiling($BitArray.Length / 8)) $BitArray.CopyTo($ByteArray, 0) return $ByteArray } function ConvertBitArrayToBigInt([System.Collections.BitArray] $BitArray) { return [bigint][byte[]](ConvertBitArrayToByteArray $BitArray) } } process { foreach ($IpAddress in $IpAddresses) { if ($IpAddress.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork) { [int32] $bitIpAddress = [BitConverter]::ToInt32($IpAddress.GetAddressBytes(), 0) } else { [System.Collections.BitArray] $bitIpAddress = $IpAddress.GetAddressBytes() } [System.Collections.Generic.List[string]] $listSubnets = New-Object System.Collections.Generic.List[string] [bool] $Result = $false foreach ($Subnet in $Subnets) { [string[]] $SubnetComponents = $Subnet.Split('/') [ipaddress] $SubnetAddress = $SubnetComponents[0] [int] $SubnetMaskLength = $SubnetComponents[1] if ($IpAddress.AddressFamily -eq $SubnetAddress.AddressFamily) { if ($IpAddress.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork) { ## Supports IPv4 (32 bit) only but more performant than BitArray? #[int32] $bitIpAddress = [BitConverter]::ToInt32($IpAddress.GetAddressBytes(), 0) [int32] $bitSubnetAddress = [BitConverter]::ToInt32($SubnetAddress.GetAddressBytes(), 0) [int32] $bitSubnetMaskHostOrder = 0 if ($SubnetMaskLength -gt 0) { $bitSubnetMaskHostOrder = -1 -shl (32 - $SubnetMaskLength) } [int32] $bitSubnetMask = [ipaddress]::HostToNetworkOrder($bitSubnetMaskHostOrder) ## Check IP if (($bitIpAddress -band $bitSubnetMask) -eq ($bitSubnetAddress -band $bitSubnetMask)) { if ($ReturnMatchingSubnets) { $listSubnets.Add($Subnet) } else { $Result = $true continue } } } else { ## BitArray supports IPv4 (32 bits) and IPv6 (128 bits). Would Int128 type in .NET 7 improve performance? #[System.Collections.BitArray] $bitIpAddress = $IpAddress.GetAddressBytes() [System.Collections.BitArray] $bitSubnetAddress = $SubnetAddress.GetAddressBytes() [System.Collections.BitArray] $bitSubnetMask = New-Object System.Collections.BitArray -ArgumentList ($bitSubnetAddress.Length - $SubnetMaskLength), $true $bitSubnetMask.Length = $bitSubnetAddress.Length [void]$bitSubnetMask.Not() [byte[]] $ByteArray = ConvertBitArrayToByteArray $bitSubnetMask [array]::Reverse($ByteArray) # Convert to Network byte order [System.Collections.BitArray] $bitSubnetMask = $ByteArray ## Check IP if ((ConvertBitArrayToBigInt $bitIpAddress.And($bitSubnetMask)) -eq (ConvertBitArrayToBigInt $bitSubnetAddress.And($bitSubnetMask))) { if ($ReturnMatchingSubnets) { $listSubnets.Add($Subnet) } else { $Result = $true continue } } } } } ## Return list of matches or boolean result if ($ReturnMatchingSubnets) { if ($listSubnets.Count -gt 1) { Write-Output $listSubnets.ToArray() -NoEnumerate } elseif ($listSubnets.Count -eq 1) { Write-Output $listSubnets.ToArray() } else { $Exception = New-Object ArgumentException -ArgumentList ('The IP address {0} does not belong to any of the provided subnets.' -f $IpAddress) Write-Error -Exception $Exception -Category ([System.Management.Automation.ErrorCategory]::ObjectNotFound) -CategoryActivity $MyInvocation.MyCommand -ErrorId 'TestIpAddressInSubnetNoMatch' -TargetObject $IpAddress } } else { Write-Output $Result } } } } # SIG # Begin signature block # MIInqQYJKoZIhvcNAQcCoIInmjCCJ5YCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD1I7e+FLnEuNT1 # MbQ068brmFcnJWmAcIxwTVDKBkDR2KCCDYEwggX/MIID56ADAgECAhMzAAACzI61 # lqa90clOAAAAAALMMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAxWhcNMjMwNTExMjA0NjAxWjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQCiTbHs68bADvNud97NzcdP0zh0mRr4VpDv68KobjQFybVAuVgiINf9aG2zQtWK # No6+2X2Ix65KGcBXuZyEi0oBUAAGnIe5O5q/Y0Ij0WwDyMWaVad2Te4r1Eic3HWH # UfiiNjF0ETHKg3qa7DCyUqwsR9q5SaXuHlYCwM+m59Nl3jKnYnKLLfzhl13wImV9 # DF8N76ANkRyK6BYoc9I6hHF2MCTQYWbQ4fXgzKhgzj4zeabWgfu+ZJCiFLkogvc0 # RVb0x3DtyxMbl/3e45Eu+sn/x6EVwbJZVvtQYcmdGF1yAYht+JnNmWwAxL8MgHMz # xEcoY1Q1JtstiY3+u3ulGMvhAgMBAAGjggF+MIIBejAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUiLhHjTKWzIqVIp+sM2rOHH11rfQw # UAYDVR0RBEkwR6RFMEMxKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 # ZXJ0byBSaWNvMRYwFAYDVQQFEw0yMzAwMTIrNDcwNTI5MB8GA1UdIwQYMBaAFEhu # ZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6Ly93d3cu # bWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0NvZFNpZ1BDQTIwMTFfMjAxMS0w # Ny0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsGAQUFBzAChkVodHRwOi8vd3d3 # Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY0NvZFNpZ1BDQTIwMTFfMjAx # MS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAgEAeA8D # sOAHS53MTIHYu8bbXrO6yQtRD6JfyMWeXaLu3Nc8PDnFc1efYq/F3MGx/aiwNbcs # J2MU7BKNWTP5JQVBA2GNIeR3mScXqnOsv1XqXPvZeISDVWLaBQzceItdIwgo6B13 # vxlkkSYMvB0Dr3Yw7/W9U4Wk5K/RDOnIGvmKqKi3AwyxlV1mpefy729FKaWT7edB # d3I4+hldMY8sdfDPjWRtJzjMjXZs41OUOwtHccPazjjC7KndzvZHx/0VWL8n0NT/ # 404vftnXKifMZkS4p2sB3oK+6kCcsyWsgS/3eYGw1Fe4MOnin1RhgrW1rHPODJTG # AUOmW4wc3Q6KKr2zve7sMDZe9tfylonPwhk971rX8qGw6LkrGFv31IJeJSe/aUbG # dUDPkbrABbVvPElgoj5eP3REqx5jdfkQw7tOdWkhn0jDUh2uQen9Atj3RkJyHuR0 # GUsJVMWFJdkIO/gFwzoOGlHNsmxvpANV86/1qgb1oZXdrURpzJp53MsDaBY/pxOc # J0Cvg6uWs3kQWgKk5aBzvsX95BzdItHTpVMtVPW4q41XEvbFmUP1n6oL5rdNdrTM # j/HXMRk1KCksax1Vxo3qv+13cCsZAaQNaIAvt5LvkshZkDZIP//0Hnq7NnWeYR3z # 4oFiw9N2n3bb9baQWuWPswG0Dq9YT9kb+Cs4qIIwggd6MIIFYqADAgECAgphDpDS # AAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMK # V2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0 # IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0 # ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5MDlaFw0yNjA3MDgyMTA5MDla # MH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMT # H01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTEwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQTTS68rZYIZ9CGypr6VpQqrgG # OBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULTiQ15ZId+lGAkbK+eSZzpaF7S # 35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYSL+erCFDPs0S3XdjELgN1q2jz # y23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494HDdVceaVJKecNvqATd76UPe/7 # 4ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZPrGMXeiJT4Qa8qEvWeSQOy2u # M1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5bmR/U7qcD60ZI4TL9LoDho33 # X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGSrhwjp6lm7GEfauEoSZ1fiOIl # XdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADhvKwCgl/bwBWzvRvUVUvnOaEP # 6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON7E1JMKerjt/sW5+v/N2wZuLB # l4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xcv3coKPHtbcMojyyPQDdPweGF # RInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqwiBfenk70lrC8RqBsmNLg1oiM # CwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFEhuZOVQ # BdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1Ud # DwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFHItOgIxkEO5FAVO # 4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwubWljcm9zb2Z0 # LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUFBzAChkJodHRwOi8vd3d3Lm1p # Y3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dDIwMTFfMjAxMV8wM18y # Mi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGCNy4DMIGDMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2RvY3MvcHJpbWFyeWNw # cy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AcABvAGwAaQBjAHkA # XwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIBAGfyhqWY # 4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4sPvjDctFtg/6+P+gKyju/R6mj # 82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKLUtCw/WvjPgcuKZvmPRul1LUd # d5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7pKkFDJvtaPpoLpWgKj8qa1hJ # Yx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft0N3zDq+ZKJeYTQ49C/IIidYf # wzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4MnEnGn+x9Cf43iw6IGmYslmJ # aG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxvFX1Fp3blQCplo8NdUmKGwx1j # NpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG0QaxdR8UvmFhtfDcxhsEvt9B # xw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf0AApxbGbpT9Fdx41xtKiop96 # eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkYS//WsyNodeav+vyL6wuA6mk7 # r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrvQQqxP/uozKRdwaGIm1dxVk5I # RcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIZfjCCGXoCAQEwgZUwfjELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9z # b2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAAAsyOtZamvdHJTgAAAAACzDAN # BglghkgBZQMEAgEFAKCBrjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgor # BgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgtddtfUS+ # kUzSkVdnSX+OjuaJNwq+JG0lIpdyfXiY5mUwQgYKKwYBBAGCNwIBDDE0MDKgFIAS # AE0AaQBjAHIAbwBzAG8AZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTAN # BgkqhkiG9w0BAQEFAASCAQA9cJmKyFR3G1ARUQ6lq2eaH4lKPRFevUSGcUwyr9LJ # Ri0R2ECZsrJ/nTewWGYEZOMf5Z9Jenlltq6CBG3au7y3r3axVYwmEV1HL1+VU6W/ # RswhuD16+ypQ7OPK81lmq+mSA3H0qkOLi9vWQgVlAZmXYQiktx8m4C90p1FZkTGU # KH7kOPy/fB2CoTBQg+2GmX3SX5Fjn3O1MDf3/yWowO34PWN/Wp5UH3ZUPwo55+tc # zbWsZsbzLS++XABL8qGpwqeEDOIIAVB3REpLnluSli9Yr0i2pHYBtYHyfUzTEkub # 59DNAabAza+C03lnk/HCQf+rhX6zagxkdsxCDRr8MOj4oYIXCDCCFwQGCisGAQQB # gjcDAwExghb0MIIW8AYJKoZIhvcNAQcCoIIW4TCCFt0CAQMxDzANBglghkgBZQME # AgEFADCCAVQGCyqGSIb3DQEJEAEEoIIBQwSCAT8wggE7AgEBBgorBgEEAYRZCgMB # MDEwDQYJYIZIAWUDBAIBBQAEIC8bzIw+AWmELCqqX5EuT3Sfb/q3F+wxuCH43q6t # dZoJAgZjxortyxwYEjIwMjMwMTI4MDIyNjU0LjMyWjAEgAIB9KCB1KSB0TCBzjEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWlj # cm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBU # U1MgRVNOOkY3N0YtRTM1Ni01QkFFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1T # dGFtcCBTZXJ2aWNloIIRXDCCBxAwggT4oAMCAQICEzMAAAGqpTGbC8uyCA4AAQAA # AaowDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw # HhcNMjIwMzAyMTg1MTI2WhcNMjMwNTExMTg1MTI2WjCBzjELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWljcm9zb2Z0IE9wZXJh # dGlvbnMgUHVlcnRvIFJpY28xJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkY3N0Yt # RTM1Ni01QkFFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoE/scrnVtYd/4UNKH07t # jKtC2Q0y90fMeJrO850j084aPIkhiuzVY4yZIKnej+a+y4+cVI/lzR0J4G5Srq7o # nfQzzVlo04/9ptmtPBitg343mdK2s4Z0K1EG6bvqHLtOvcBkNQCsvC+GwaVeEuUN # TXCKhrEz4FXAI0jsuZNpgqqObnyESCxi0ogeTn0vM6cjhp6ds8sE/9VhiMjprgoh # y6fQRkSsC6S3k8L+YpRo6mFQwZibQ/F+lj0GQbmw99zMXIh8DXcstFLiwaFtStwz # ngS8TYWVYFBomjt+spbsJWMhMsRfgTaXHBAb8y5n7XANiD044StPmH7rN5yPrt56 # fDF5Sho4Rsq2JTFolRifJArEJZOQ11ZFdMpKYjHHS1uw/mKtaOpe9Pq3/N4krDTk # 1jyE9Pnq9bbSrQNgrY2144IMPRQPpk0AUtXzsY6SXR4GpdxOgVV14nDA5MTpoDhG # pig2vZBQ8EhTokSJQYGz1zioLmYEdNjjpVpH+h1oUMtzFAjg4+SflqX8g+x3z+to # OYx8qKTrrFw2Hao3jLK1gze6IN6dfmp4V3Hel2LjelgAU39LX/dVE2T78ZFVRRhZ # gGMNlKrGyWJ0TyGzELsryot+Y2hpDZoCy7XeHV9pMxJkgRXGizPVv3Ih5ea0zo2W # uNXd63BLsldjAaEcx1VgQvUCAwEAAaOCATYwggEyMB0GA1UdDgQWBBQ/mhS8U4cu # 2F93RbPeEa2dBUaknjAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBf # BgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmww # bAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29m # dC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0El # MjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMI # MA0GCSqGSIb3DQEBCwUAA4ICAQDfDIBNkEUQGiCtzAezjMjupfbLSNsoIjpmJ4YA # hH3pGIyuNm9Ybf1g8D8Uva+EZIK07t5reIGXCGFPIkQ97Eu6BPiMHhbSuV04s/ls # RzTPDGz021MVLxSXbNsnuPPlbFKeFIex9pUVSntLoHZrVuMqZYij9K93dbVXeZwh # jOFukshRWU/cJtMkQT5wLeFf4mCCdJhERPKj6YjsfP8oxYVpFYFRgjiDQGvCJXaV # iorJ6SM2nquPtvyXo6FuBf8k/RvM3G/qKjRjiI2UjPP890iH8TamPelc+JAk9GUS # QySxF5wTxWcXKqFHh9v8XpznLBjj6YSmyEgCDZhRezAWqpsr0W/5TxhhyVg++Er/ # BFmz7/lq4rgUz5BOPLCPQLmuavwzOKqZQaAC7BlBjIdEKimdV2Vo7/HFJkJ9plHv # DsHc4ESXyP5Wih+zUp+r0CaZABZk6O3gOc2Tk2fFOE++NBW45T/L4dMSvCoP/ApE # KXQAndQ9Mnw89in6NsReQqagWFTgkZ6vl5qPbadfX2m6M1kqqpqu3jIuM1Q6SpaN # WTgoel1hEZwkxVeQqRACKWNSf1wdHA24/P9O7tiZ+BFdY3ge8JxPabVAAOKc5k+w # 7m/mP9sTHDRaYWtbYK0MQCmcKWaIApyEWvTFIoTkRP4DK5stql6MQ2v2+3tBc2rp # o/VdZzCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcN # AQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAw # BgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEw # MB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUt # U3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk # 4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9c # T8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWG # UNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6Gnsz # rYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2 # LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLV # wIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTd # EonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0 # gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFph # AXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJ # YfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXb # GjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJ # KwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnP # EP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMw # UQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9z # b2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggr # BgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYw # DwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoY # xDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtp # L2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYB # BQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20v # cGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0B # AQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U5 # 18JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgAD # sAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo # 32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZ # iefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZK # PmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RI # LLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgk # ujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9 # af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzba # ukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/ # OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggLPMIIC # OAIBATCB/KGB1KSB0TCBzjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0 # b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEpMCcGA1UECxMgTWljcm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28x # JjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkY3N0YtRTM1Ni01QkFFMSUwIwYDVQQD # ExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDg # bSbQnh4CWWNw/+O86/3+mb/rxqCBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1w # IFBDQSAyMDEwMA0GCSqGSIb3DQEBBQUAAgUA537g9DAiGA8yMDIzMDEyODAzNDcw # MFoYDzIwMjMwMTI5MDM0NzAwWjB0MDoGCisGAQQBhFkKBAExLDAqMAoCBQDnfuD0 # AgEAMAcCAQACAgS/MAcCAQACAhF4MAoCBQDngDJ0AgEAMDYGCisGAQQBhFkKBAIx # KDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZI # hvcNAQEFBQADgYEAEwpOD5Z1zMelhO6aTcAXN+xUQCZFNVtL5DXRlqBAqo5u+DtY # uKLLxERiScvVqWCYQrR9YLZvvVWuLxmmqmoJVntFq1IzPY4kN/fcoicTXYIl9uRU # o5P0SLEOqCnMaASF8c2U/26pLDe4/ensXCB7X442hmLWXB1HSfQdLyCl+qMxggQN # MIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQ # MA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u # MSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAaql # MZsLy7IIDgABAAABqjANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkDMQ0G # CyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCBYXE/nUxgKsbqdAmRq8xUPyztL # dtZ4LVL+7GJMdAFJ8zCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIFa1AkMc # WrwR4HPdNe6AKpGFIj8kJlsBNgQjBMbxsx7AMIGYMIGApH4wfDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRp # bWUtU3RhbXAgUENBIDIwMTACEzMAAAGqpTGbC8uyCA4AAQAAAaowIgQgUCdn37pS # b7i+Ghd1GJ6fD/Y26FRweiOPzDv33HZqRgEwDQYJKoZIhvcNAQELBQAEggIAQFJE # ASSx6m3PesdCrKiuu7lcteFxVi9ibtpfSHlzxp/4rziMAQ9hk10xMeUFuK1sYof0 # D5D0cURSk/XjBHo0eqDFaanobZ6630oqqYI3CHgiD4AqmUFNIXa+/p3egiuC7FHw # F5M9NfoJaYS95DAo1eXPN/vQPXYU2wVQpa7Vk5+9iozcTrnwgehDSho8QXuSYcmx # j7oW2Wy6c6EuPTe96vDHKhsHGJwnqYhiNGAFJ6/c+mUa9GDrnQbslCj/8kKQufho # kYkUEV3b3f4AnYu1TFWnnxla5F6bsfVGPezVyepx1hr8Gy+fll29K0NrWFFppGgM # hI4vDhzzw7Aftwbuw23IwC5U/ANRbWqWZlhzEWeQrtTZ9zIR4UhiXNDUUihshOLr # KqQvRCOX6EOU6osOXO1L4ch6fikNFc/xDb+Jsq6EVcjF9HCUZigTkQNmXBABWkec # cunJB4OfIOBHOlnrTGeOkYDubNJZSGcdVxUFBcjm8FIz4w6juoDMesmaz13ohEWO # yiXriO9KDzMN2dLupcr0QqX//euDRTbZeLZYYDOxfMFQZ2cc/xOwkGXQuoXGS0Ej # 1tQKSMe8dHPSkxWPvIkbJIrH/OJdQy3WUnrMscZ4UECy+XXsqhlC0PLmTNwR8tMB # YAJiz+u0hDMJHuar5lGTdgpvBsStRpwitMJjIyw= # SIG # End signature block |