# Copyright (c) 2026, R. W. Rodolico # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # windows_network.ps1 # Up network adapters: IPv4/IPv6 address, netmask, MAC, MTU. # Sensor contract: unix/sensors/Documentation/README.md; keys: Documentation/Spec.md 7.6 # Must stay Windows PowerShell 5.1 compatible and pure ASCII. # # Version 1.0.0 20261018 Claude # Initial version (bug 211, stage W2) Import-Module ([IO.Path]::Combine($PSScriptRoot, '..', 'lib', 'SysinfoSensor.psm1')) Test-SysinfoWindows # dotted netmask from a prefix length (0 to 32) function ConvertTo-Netmask { param([int]$Prefix) if ($Prefix -lt 0 -or $Prefix -gt 32) { return '' } $mask = 0 if ($Prefix -gt 0) { $mask = ([long]4294967295 -shl (32 - $Prefix)) -band 4294967295 } $octets = foreach ($shift in 24, 16, 8, 0) { ($mask -shr $shift) -band 255 } return ($octets -join '.') } Invoke-SysinfoSensor { foreach ($cmd in 'Get-NetAdapter', 'Get-NetIPAddress', 'Get-NetIPInterface') { if ($null -eq (Get-Command $cmd -ErrorAction SilentlyContinue)) { Exit-SysinfoSensor -Code $SYSINFO_EXIT_NOT_APPLICABLE -Message "$cmd not available" } } foreach ($adapter in @(Get-NetAdapter -ErrorAction Stop | Where-Object { $_.Status -eq 'Up' })) { $name = [string]$adapter.Name $index = $adapter.ifIndex $v4 = @(Get-NetIPAddress -InterfaceIndex $index -AddressFamily IPv4 -ErrorAction SilentlyContinue | Where-Object { $_.IPAddress -ne '127.0.0.1' }) $v6 = @(Get-NetIPAddress -InterfaceIndex $index -AddressFamily IPv6 -ErrorAction SilentlyContinue | Where-Object { $_.IPAddress -ne '::1' }) if ($v4.Count -gt 0) { Write-SysinfoFact -Path @('network', $name, 'address') -Value $v4[0].IPAddress Write-SysinfoFact -Path @('network', $name, 'netmask') -Value (ConvertTo-Netmask ([int]$v4[0].PrefixLength)) } if ($v6.Count -gt 0) { $chosen = $v6 | Where-Object { ([string]$_.IPAddress) -notlike 'fe80:*' } | Select-Object -First 1 if ($null -eq $chosen) { $chosen = $v6[0] } Write-SysinfoFact -Path @('network', $name, 'ip6address') -Value (([string]$chosen.IPAddress) -replace '%.*$', '') Write-SysinfoFact -Path @('network', $name, 'ip6networkbits') -Value $chosen.PrefixLength } Write-SysinfoFact -Path @('network', $name, 'mac') -Value (([string]$adapter.MacAddress -replace '-', ':').ToLowerInvariant()) $mtu = '' $iface = Get-NetIPInterface -InterfaceIndex $index -AddressFamily IPv4 -ErrorAction SilentlyContinue | Select-Object -First 1 if ($null -ne $iface -and $null -ne $iface.NlMtu) { $mtu = [string]$iface.NlMtu } Write-SysinfoFact -Path @('network', $name, 'mtu') -Value $mtu } }