<# LXS - Network Diagnostics (Windows) Description: Inspect and repair the network stack. Everything is read-only except option 8 (stack reset). Repo: https://git.hyko.cx/hykocx/lxs #> # Load LXS common library (colors, UI helpers, spinner, loggers, guards). # Prefers the sibling ..\lib\common.ps1 (repo checkout or installed layout) and # only hits the network when this script is run standalone. $LxsRawBase = if ($env:LXS_RAW_BASE) { $env:LXS_RAW_BASE } else { 'https://git.hyko.cx/hykocx/lxs/raw/branch/main' } if (-not $env:LXS_RAW_PLATFORM_BASE) { $env:LXS_RAW_PLATFORM_BASE = "$LxsRawBase/windows" } $LxsLibPath = if ($PSScriptRoot) { Join-Path $PSScriptRoot '..\lib\common.ps1' } else { $null } if ($LxsLibPath -and (Test-Path $LxsLibPath)) { . $LxsLibPath } else { try { $LxsLibSource = Invoke-RestMethod -Uri "$env:LXS_RAW_PLATFORM_BASE/lib/common.ps1" -UseBasicParsing -ErrorAction Stop } catch { Write-Error 'Failed to fetch lib/common.ps1' exit 1 } . ([scriptblock]::Create($LxsLibSource)) } $env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_net_diag.log' function Show-LxsIpConfiguration { Clear-Host Show-LxsBoxTop -Title 'IP CONFIGURATION' Write-Host '' try { Get-NetIPConfiguration -Detailed -ErrorAction Stop | ForEach-Object { Write-Host "$($script:Cyan)$($script:Bold)$($_.InterfaceAlias)$($script:NC) $($script:Gray)($($_.InterfaceDescription))$($script:NC)" Write-Host " Status : $($_.NetAdapter.Status) | MAC: $($_.NetAdapter.MacAddress) | Speed: $($_.NetAdapter.LinkSpeed)" Write-Host " IPv4 : $($_.IPv4Address.IPAddress -join ', ')" Write-Host " IPv6 : $($_.IPv6Address.IPAddress -join ', ')" Write-Host " Gateway : $($_.IPv4DefaultGateway.NextHop -join ', ')" Write-Host " DNS : $($_.DNSServer.ServerAddresses -join ', ')" Write-Host '' } } catch { Write-LxsWarn 'Get-NetIPConfiguration unavailable; falling back to ipconfig /all.' ipconfig /all | Out-String | Write-Host } } function Show-LxsListeningPorts { Clear-Host Show-LxsBoxTop -Title 'LISTENING PORTS' Write-Host '' try { $rows = Get-NetTCPConnection -State Listen -ErrorAction Stop | ForEach-Object { $procName = try { (Get-Process -Id $_.OwningProcess -ErrorAction Stop).ProcessName } catch { 'unknown' } [pscustomobject]@{ Local = "$($_.LocalAddress):$($_.LocalPort)" Port = $_.LocalPort PID = $_.OwningProcess Process = $procName } } $rows | Sort-Object Port | Format-Table -AutoSize Local, PID, Process | Out-String | Write-Host } catch { Write-LxsWarn 'Get-NetTCPConnection unavailable; falling back to netstat.' netstat -ano | Select-String 'LISTENING' | Out-String | Write-Host } } function Clear-LxsDnsCache { Clear-Host Show-LxsBoxTop -Title 'FLUSH DNS CACHE' Write-Host '' try { Clear-DnsClientCache -ErrorAction Stop Write-LxsOk 'DNS resolver cache flushed' } catch { Write-LxsWarn 'Clear-DnsClientCache failed; falling back to ipconfig /flushdns.' ipconfig /flushdns | Out-String | Write-Host } } function Invoke-LxsPing { Clear-Host Show-LxsBoxTop -Title 'PING' Write-Host '' $target = Read-Host -Prompt 'Host to ping (default: 1.1.1.1)' if ([string]::IsNullOrWhiteSpace($target)) { $target = '1.1.1.1' } Write-Host '' ping.exe -n 4 $target | Out-String | Write-Host } function Invoke-LxsTraceroute { Clear-Host Show-LxsBoxTop -Title 'TRACEROUTE' Write-Host '' $target = Read-Host -Prompt 'Host to trace (default: 1.1.1.1)' if ([string]::IsNullOrWhiteSpace($target)) { $target = '1.1.1.1' } Write-Host '' Write-LxsInfo "Tracing route to $target (this can take a minute)..." tracert.exe -d -h 20 $target | Out-String | Write-Host } function Test-LxsRemotePort { Clear-Host Show-LxsBoxTop -Title 'TEST TCP PORT' Write-Host '' $target = Read-Host -Prompt 'Host' if ([string]::IsNullOrWhiteSpace($target)) { Write-LxsErr 'No host given.'; return } $port = Read-Host -Prompt 'Port' if ($port -notmatch '^\d+$') { Write-LxsErr 'Port must be a number.'; return } Write-Host '' try { $result = Test-NetConnection -ComputerName $target -Port ([int]$port) -WarningAction SilentlyContinue -ErrorAction Stop if ($result.TcpTestSucceeded) { Write-LxsOk "${target}:${port} is reachable ($($result.RemoteAddress))" } else { Write-LxsErr "${target}:${port} is NOT reachable" } } catch { Write-LxsErr "Test failed: $($_.Exception.Message)" } } function Show-LxsPublicIp { Clear-Host Show-LxsBoxTop -Title 'PUBLIC IP' Write-Host '' Write-LxsInfo 'Querying...' Write-Host '' Write-Host " $($script:White)$($script:Bold)$(Get-LxsPublicIP)$($script:NC)" Write-Host '' } function Reset-LxsNetworkStack { Clear-Host Show-LxsBoxTop -Title 'RESET NETWORK STACK' -Right 'DESTRUCTIVE' Write-Host '' Write-Host 'This resets the Winsock catalog and the TCP/IP stack. It clears' Write-Host 'third-party LSP entries, static IP settings and proxy configuration,' Write-Host "and $($script:Bold)requires a reboot$($script:NC) to take effect." Write-Host '' if (-not (Confirm-LxsAction -Question 'Reset the network stack now?')) { Write-LxsInfo 'Cancelled.' return } if (-not (Test-LxsAdmin)) { Write-LxsErr 'This action requires administrator rights. Re-run lxs from an elevated terminal.' return } Write-Host '' netsh winsock reset | Out-String | Write-Host netsh int ip reset | Out-String | Write-Host Clear-DnsClientCache -ErrorAction SilentlyContinue Write-Host '' Write-LxsOk 'Network stack reset' Write-LxsWarn 'Reboot required for the change to take effect.' } function Show-LxsNetDiagMenu { while ($true) { Clear-Host Show-LxsBoxTop -Title 'NETWORK DIAG' Write-Host '' Show-LxsMenuItem '1' 'Show IP configuration' Show-LxsMenuItem '2' 'Show listening ports' Show-LxsMenuItem '3' 'Flush DNS cache' Show-LxsMenuItem '4' 'Ping a host' Show-LxsMenuItem '5' 'Traceroute a host' Show-LxsMenuItem '6' 'Test a TCP port' Show-LxsMenuItem '7' 'Show public IP' Show-LxsMenuItem '8' 'Reset network stack' 'needs admin + reboot' Show-LxsMenuItem '0' 'Back' '' -Exit Write-Host '' Show-LxsBoxBottom Write-Host '' $choice = Read-LxsChoice Write-Host '' switch ($choice) { '1' { Show-LxsIpConfiguration; Read-LxsEnter } '2' { Show-LxsListeningPorts; Read-LxsEnter } '3' { Clear-LxsDnsCache; Read-LxsEnter } '4' { Invoke-LxsPing; Read-LxsEnter } '5' { Invoke-LxsTraceroute; Read-LxsEnter } '6' { Test-LxsRemotePort; Read-LxsEnter } '7' { Show-LxsPublicIp; Read-LxsEnter } '8' { Reset-LxsNetworkStack; Read-LxsEnter } '0' { return } default { Write-LxsErr 'Invalid protocol. Select 0-8.'; Start-Sleep -Seconds 1 } } } } if (-not (Assert-LxsWindows)) { exit 1 } Show-LxsNetDiagMenu exit 75