Public/Get-SilkPersistentTargets.ps1

function Get-SilkPersistentTargets {
    # needed for -Verbose to bind, without it the switch just lands in $args
    [CmdletBinding()]
    param(
        [string] $nodeAddress,
        [ipaddress] $cnodeIP
    )

    $regPath = Find-SilkiSCSIRegistryInstance
    $ipString = $cnodeIP.IPAddressToString

    if (-not $regPath) {
        Write-Error "SilkiSCSI registry instance not found."
        return
    }

    $regPath = $regPath + "\PersistentTargets"

    $targets = $targets = Get-ChildItem -Path $regPath

    $targetArray = @()

    foreach ($t in $targets) {
        # NOT $cnodeIP, thats the parameter and the loop would eat it
        $foundIP = $null
        $localIP = $null

        # open the subkey off the key object, the iqn in the key name has a colon in
        # it and powershell reads that as a drive qualifier if you rebuild the path
        $sub = $null
        try { $sub = $t.OpenSubKey('LoginTarget') } catch { }

        if ($sub) {
            # LocalIPAddress is a sockaddr_in - 02 00 <port> <4 byte ip>. thats our own
            # side of the login, we read it so we can rule it out below
            $lb = $sub.GetValue('LocalIPAddress')
            if ($lb -and $lb.Count -ge 8 -and $lb[0] -eq 2 -and $lb[1] -eq 0) {
                $localIP = Convert-SilkByteToIP -bytes $lb -offset 4
            }

            # LoginTargetIN isnt a sockaddr, its a struct with the cnode sat at byte 52
            # as 4 raw octets, right after an 01 00 00 00 marker at 48
            $tb = $sub.GetValue('LoginTargetIN')
            if ($tb -and $tb.Count -ge 56) {

                $candidate = Convert-SilkByteToIP -bytes $tb -offset 52
                if ($candidate -and $candidate -ne $localIP) {
                    $foundIP = $candidate
                    Write-Verbose "$($t.PSChildName) -> cnodeIP $foundIP (offset 52)"
                }

                # offset moved on us, hunt the 01 00 00 00 marker instead
                if (-not $foundIP) {
                    for ($i = 0; $i -le ($tb.Count - 8); $i++) {
                        if ($tb[$i] -ne 1 -or $tb[$i+1] -ne 0 -or $tb[$i+2] -ne 0 -or $tb[$i+3] -ne 0) { continue }
                        $candidate = Convert-SilkByteToIP -bytes $tb -offset ($i + 4)
                        if (-not $candidate -or $candidate -eq $localIP) { continue }
                        $foundIP = $candidate
                        Write-Verbose "$($t.PSChildName) -> cnodeIP $foundIP (marker at $i)"
                        break
                    }
                }

                if (-not $foundIP) {
                    $hex = ($tb | Select-Object -First 64 | ForEach-Object { $_.ToString('X2') }) -join ' '
                    Write-Verbose "$($t.PSChildName) -> no cnode found in $($tb.Count) bytes: $hex"
                }
            }

            $sub.Close()
        } else {
            Write-Verbose "$($t.PSChildName) -> no LoginTarget subkey"
        }

        $o = New-Object psobject 
        $o | Add-Member -MemberType NoteProperty -Name "Name" -Value $t.PSChildName
        $o | Add-Member -MemberType NoteProperty -Name "cnodeIP" -Value $foundIP
        $o | Add-Member -MemberType NoteProperty -Name "PSPath" -Value $t.name
        $targetArray += $o
    }

    if ($nodeAddress) {
        $targetArray = $targetArray | Where-Object { $_.name -like "$nodeAddress*" }
    } 

    if ($ipString) {
        $targetArray = $targetArray | Where-Object {$_.cnodeIP -eq $ipString}
    }
    return $targetArray

}