Private/Get-WinClatTargetAdapter.ps1
|
Function Get-WinClatTargetAdapter { <# .SYNOPSIS Finds the adapter that Set-WinClatInstance should change and checks that it can run CLAT. .DESCRIPTION Looks up one adapter with Get-NetAdapter, by exact name (case-insensitive, no wildcards) or by interface index (DESIGN.md, section 7.4). Returns an object with InterfaceAlias, InterfaceIndex, InterfaceLuid (the adapter NetLuid, used to match IPxlatCfg events), and Problem. Problem is $null when the adapter can be changed, and otherwise explains why it was refused: - No adapter has that name or index. - The adapter is not up. - IPv6 (ms_tcpip6) is not bound to the adapter, so CLAT can never run on it. If the IPv6 binding cannot be read, the adapter is not refused for that reason. This function must also be available in the remote session. See DESIGN.md, section 4.3. .PARAMETER InterfaceAlias The exact adapter name. Leave empty to look up by index. .PARAMETER InterfaceIndex The interface index, used when InterfaceAlias is empty. .INPUTS None. This function does not accept pipeline input. .OUTPUTS System.Management.Automation.PSCustomObject with InterfaceAlias, InterfaceIndex, InterfaceLuid, and Problem properties. .EXAMPLE Get-WinClatTargetAdapter -InterfaceAlias 'Internal' Returns InterfaceAlias 'Internal', its interface index, and Problem $null when the adapter is up with IPv6 bound. .LINK https://learn.microsoft.com/powershell/module/netadapter/get-netadapter .NOTES Version: 1.0.0 Creation Date: October 28, 2026 Last Updated: October 28, 2026 Author: Richard Hicks Organization: Richard M. Hicks Consulting, Inc. Contact: rich@richardhicks.com Website: https://www.richardhicks.com/ #> [CmdletBinding()] [OutputType([PSCustomObject])] Param ( [AllowNull()] [AllowEmptyString()] [string]$InterfaceAlias, [int]$InterfaceIndex ) $Adapters = @(Get-NetAdapter -ErrorAction SilentlyContinue | Where-Object -FilterScript { $_ }) If ($InterfaceAlias) { $Match = @($Adapters | Where-Object -FilterScript { $_.Name -eq $InterfaceAlias }) $NotFound = "No network adapter named '$InterfaceAlias' was found." $Result = [PSCustomObject]@{ InterfaceAlias = $InterfaceAlias; InterfaceIndex = $null; InterfaceLuid = $null; Problem = $null } } Else { $Match = @($Adapters | Where-Object -FilterScript { $_.ifIndex -eq $InterfaceIndex }) $NotFound = "No network adapter with interface index $InterfaceIndex was found." $Result = [PSCustomObject]@{ InterfaceAlias = $null; InterfaceIndex = $InterfaceIndex; InterfaceLuid = $null; Problem = $null } } If ($Match.Count -eq 0) { $Result.Problem = $NotFound Return $Result } $Adapter = $Match[0] $Result.InterfaceAlias = $Adapter.Name $Result.InterfaceIndex = $Adapter.ifIndex $Result.InterfaceLuid = $Adapter.NetLuid If ($Adapter.Status -ne 'Up') { $Result.Problem = "The adapter is not up (status: $($Adapter.Status)), so its CLAT state was not changed." Return $Result } Try { $Binding = @(Get-NetAdapterBinding -Name $Adapter.Name -ComponentID 'ms_tcpip6' -ErrorAction Stop)[0] If ($Binding -and -not $Binding.Enabled) { $Result.Problem = 'IPv6 is not bound to the adapter, so CLAT can never run on it. Its CLAT state was not changed.' } } Catch { Write-Verbose -Message "The IPv6 binding of '$($Adapter.Name)' could not be read, so it was not checked: $($_.Exception.Message)" } $Result } |