Last active
May 29, 2021 14:34
-
-
Save thedavecarroll/0024d27e05e95800656b080d7c84f96d to your computer and use it in GitHub Desktop.
Get IANA Port Number Registry
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-IanaPortNumberRegistry { | |
[CmdLetBinding()] | |
param( | |
[ValidateSet('TCP','UDP','SCTP','DCCP')] | |
[string[]]$Protocol, | |
[ValidateRange(0,65535)] | |
[int[]]$PortNumber, | |
[string]$ServiceName, | |
[switch]$RefreshCache, | |
[string]$AlternatePath | |
) | |
function Invoke-DownloadIanaPortNumberRegistry { | |
[CmdLetBinding()] | |
param($OutFile) | |
$InvokeWebRequestParams = @{ | |
Uri = 'https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml' | |
OutFile = $OutFile | |
ErrorAction = 'Stop' | |
Verbose = $false | |
} | |
try { | |
Invoke-WebRequest @InvokeWebRequestParams | Out-Null | |
} | |
catch { | |
$PSCmdlet.ThrowTerminatingError($_) | |
} | |
} | |
if ($PSBoundParameters.ContainsKey('AlternatePath') -and $PSBoundParameters.ContainsKey('RefreshCache')) { | |
$Action = 'SetAlternatePath','Download','ReadCache' | |
} elseif ($PSBoundParameters.ContainsKey('RefreshCache') -and -Not $PSBoundParameters.ContainsKey('AlternatePath') ) { | |
$Action = 'SetPath','Download','ReadCache' | |
} elseif ($PSBoundParameters.ContainsKey('AlternatePath') -and -Not $PSBoundParameters.ContainsKey('RefreshCache') ) { | |
$Action = 'SetAlternatePath','ReadCache' | |
} elseif (Get-Variable -Name IanaRegistryCache -Scope Global -ErrorAction SilentlyContinue) { | |
$Action = 'SetPath','ReadCache' | |
} else { | |
$Action = 'SetPath','Download','ReadCache' | |
} | |
'Performing the following actions : {0}' -f ($Action -join ', ') | Write-Verbose | |
switch ($Action) { | |
'SetPath' { | |
if (Get-Variable -Name IanaRegistryCache -Scope Global -ErrorAction SilentlyContinue) { | |
if ($global:IanaRegistryCache -eq (Join-Path -Path $env:TEMP -ChildPath 'IanaRegistryCache.xml')) { | |
'Existing IanaRegistryCache path : {0}' -f $global:IanaRegistryCache | Write-Verbose | |
} else { | |
$global:IanaRegistryCache = Join-Path -Path $env:TEMP -ChildPath 'IanaRegistryCache.xml' | |
'User TEMP IanaRegistryCache path updated: {0}' -f $global:IanaRegistryCache | Write-Verbose | |
} | |
} else { | |
if (Test-Path -Path $env:TEMP) { | |
$global:IanaRegistryCache = Join-Path -Path $env:TEMP -ChildPath 'IanaRegistryCache.xml' | |
'User TEMP IanaRegistryCache path : {0}' -f $global:IanaRegistryCache | Write-Verbose | |
} else { | |
$global:IanaRegistryCache = Resolve-Path -Path '.\IanaRegistryCache.xml' | |
'Current folder IanaRegistryCache path : {0}' -f $global:IanaRegistryCache | Write-Verbose | |
} | |
} | |
continue | |
} | |
'SetAlternatePath' { | |
if (Get-Variable -Name IanaRegistryCache -Scope Global -ErrorAction SilentlyContinue) { | |
if ($global:IanaRegistryCache -eq (Resolve-Path -Path $AlternatePath)) { | |
'Existing IanaRegistryCache path : {0}' -f $global:IanaRegistryCache | Write-Verbose | |
} else { | |
$global:IanaRegistryCache = Resolve-Path -Path $AlternatePath | |
'Alternate IanaRegistryCache path updated : {0}' -f $global:IanaRegistryCache | Write-Verbose | |
} | |
} else { | |
$global:IanaRegistryCache = Resolve-Path -Path $AlternatePath | |
'Alternate IanaRegistryCache path : {0}' -f $global:IanaRegistryCache | Write-Verbose | |
} | |
continue | |
} | |
'Download' { | |
try { | |
Invoke-DownloadIanaPortNumberRegistry -OutFile $global:IanaRegistryCache -ErrorAction Stop | |
'Downloaded IANA Port Number Registry' | Write-Verbose | |
continue | |
} | |
catch { | |
'Unable to download. Removing IanaRegistryCache variable' | Write-Warning | |
Remove-Variable -Name IanaRegistryCache -Scope Global | Out-Null | |
return | |
} | |
} | |
'ReadCache' { | |
try { | |
[xml]$IanaPortNumberRegistry = Get-Content -Path $global:IanaRegistryCache -Raw -ErrorAction Stop | |
'Read Port Number Registry cache' | Write-Verbose | |
} | |
catch { | |
'Unable to read file; attempting to download' | Write-Warning | |
try { | |
Invoke-DownloadIanaPortNumberRegistry -OutFile $global:IanaRegistryCache -ErrorAction Stop | |
'Second attempt to download IANA Port Number Registry succeeded' | Write-Verbose | |
[xml]$IanaPortNumberRegistry = Get-Content -Path $global:IanaRegistryCache -Raw -ErrorAction Stop | |
'Read IANA Port Number Registry' | Write-Verbose | |
} | |
catch { | |
'Unable to download; removing IanaRegistryCache variable' | Write-Warning | |
Remove-Variable -Name IanaRegistryCache -Scope Global | Out-Null | |
return | |
} | |
} | |
} | |
} | |
$Format = @{l='Protocol';e={$_.protocol.ToUpper()}}, | |
@{l='PortNumber';e={if ($_.number -like '*-*') { [int]::Parse($_.number.Split('-')[0])..[int]::Parse($_.number.Split('-')[1]) } else {$_.number} }}, | |
@{l='ServiceName';e={$_.description}} | |
$Filter = @() | |
if ($Protocol) { | |
$ProtocolFilter = @() | |
foreach ($Transport in $Protocol) { | |
$ProtocolFilter += '$_.Protocol -eq "{0}"' -f $Transport.ToLower() | |
} | |
$Filter += '(' + ($ProtocolFilter -join ' -or ') + ')' | |
} | |
if ($PortNumber) { | |
$PortFilter = @() | |
foreach ($Number in $PortNumber) { | |
$PortFilter += '{0} -in $_.PortNumber' -f $Number | |
} | |
$Filter += '(' + ($PortFilter -join ' -or ') + ')' | |
} | |
if ($ServiceName) { | |
$Filter += '$_.ServiceName -match "{0}"' -f $ServiceName | |
} | |
$FilterString = $Filter -join ' -and ' | |
if ($Filter.count -gt 0) { | |
[scriptblock]$FilterScript = [scriptblock]::Create($FilterString) | |
} | |
$CacheDate = Get-ChildItem -Path $global:IanaRegistryCache | |
$DisplayInformation = [PsCustomObject]@{ | |
Title = $IanaPortNumberRegistry.registry.title | |
XmlUpdated = $IanaPortNumberRegistry.registry.updated | |
Downloaded = $CacheDate.LastWriteTime | |
IanaRegistryCachePath = $global:IanaRegistryCache | |
Records = $IanaPortNumberRegistry.registry.record.count | |
} | |
Write-Information -MessageData $DisplayInformation | |
if ($FilterScript) { | |
'Search string: {0}' -f $FilterScript | Write-Verbose | |
$IanaPortNumberRegistry.registry.record | | |
Select-Object $Format | | |
Where-Object -FilterScript $FilterScript | | |
Select-Object -Property Protocol,PortNumber,ServiceName -Unique | |
} else { | |
'Retrieving all records' | Write-Verbose | |
$IanaPortNumberRegistry.registry.record | | |
Select-Object $Format | |
} | |
<# | |
.SYNOPSIS | |
The command retrieves the IANA Port Number Registry entries using the | |
provided filter parameters. | |
.DESCRIPTION | |
The command retrieves the IANA Port Number Registry entries using the | |
provided filter parameters. | |
The IANA Port Number Registry is available as an XML file. | |
This command uses a global variable to store the path for the last | |
downloaded XML file to prevent numerous downloads. | |
.PARAMETER Protocol | |
The Protocol parameter will be used to filter the results. | |
.PARAMETER PortNumber | |
The PortNumber parameter will be used to filter the results. | |
.PARAMETER ServiceName | |
The ServiceName parameter will be used to filter the results. | |
.PARAMETER RefreshCache | |
The RefreshCache parameter forces the command to download the registry xml | |
even if the registry is cached. | |
.PARAMETER AlternatePath | |
The AlternatePath parameter instructs the command to download to a different | |
path. By default, this file is downloaded to the user's TEMP folder. | |
.EXAMPLE | |
PS > $IanaRegistry = Get-IanaPortNumberRegistry | |
Retrieves the entire port number registry into a variable. | |
Note: On subsequent runs, this will read the registry from the cache. | |
.EXAMPLE | |
PS > Get-IanaPortNumberRegistry -Protocol TCP -PortNumber 25,110 | |
Protocol PortNumber ServiceName | |
-------- ---------- ----------- | |
TCP 25 Simple Mail Transfer | |
TCP 110 Post Office Protocol - Version 3 | |
TCP 143 Internet Message Access Protocol | |
TCP 465 URL Rendezvous Directory for SSM | |
TCP 465 Message Submission over TLS protocol | |
TCP 993 IMAP over TLS protocol | |
TCP 995 POP3 over TLS protocol | |
Filters the cached registry for SMTP, POP, and IMAP entries. | |
.EXAMPLE | |
PS > $UpdateRegistry = Get-IanaPortNumberRegistry -RefreshCache -InformationVariable MyInfo | |
PS > $Myinfo.MessageData | |
Title : Service Name and Transport Protocol Port Number Registry | |
XmlUpdated : 2019-11-25 | |
Downloaded : 11/30/2019 7:30:10 PM | |
IanaRegistryCachePath : C:\Users\Dave\AppData\Local\Temp\IanaRegistryCache.xml | |
Records : 14170 | |
Forces a refresh of the cache by downloading the XML again. | |
This example also shows key information that is sent to the information stream. | |
.INPUTS | |
None | |
.OUTPUTS | |
PsCustomObject[] | |
.LINK | |
https://gist.github.com/thedavecarroll/0024d27e05e95800656b080d7c84f96d | |
.LINK | |
https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml | |
.LINK | |
https://www.iana.org | |
#> | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment