Skip to content

Add Match localnetwork / getifaddrs support on Windows#859

Open
steffen-heil-secforge wants to merge 2 commits into
PowerShell:latestw_allfrom
steffen-heil-secforge:feature/match-localnetwork-windows-upstream
Open

Add Match localnetwork / getifaddrs support on Windows#859
steffen-heil-secforge wants to merge 2 commits into
PowerShell:latestw_allfrom
steffen-heil-secforge:feature/match-localnetwork-windows-upstream

Conversation

@steffen-heil-secforge

@steffen-heil-secforge steffen-heil-secforge commented Jun 23, 2026

Copy link
Copy Markdown

Tracking issue: PowerShell/Win32-OpenSSH#2440

Summary

Adds support for the Match localnetwork ssh_config criterion on Windows by implementing POSIX getifaddrs()/freeifaddrs() over the Win32 GetAdaptersAddresses() API.

Previously check_match_ifaddrs() (readconf.c) and the BindInterface interface enumeration (sshconnect.c) were gated on HAVE_IFADDRS_H, which the Windows build never defined, and win32compat had no getifaddrs() — so Match localnetwork always returned "not supported on this platform".

Changes

  • contrib/win32/win32compat/inc/ifaddrs.h (new): struct ifaddrs, IFF_* flags (Windows has no <net/if.h>), getifaddrs/freeifaddrs prototypes.
  • contrib/win32/win32compat/getifaddrs.c (new): implementation over GetAdaptersAddresses().
  • contrib/win32/openssh/config.h.vs: define HAVE_IFADDRS_H and HAVE_GETIFADDRS.
  • contrib/win32/openssh/win32iocompat.vcxproj (+ .filters): build the new sources into posix_compat.lib.
  • contrib/win32/openssh/ssh.vcxproj: link Iphlpapi.lib.
  • regress/unittests/win32compat/getifaddrs_tests.c (new): unit tests, registered in tests.c/tests.h and unittest-win32compat.

Notes

  • Match localnetwork is client-only in 10.0 (readconf.c / ssh_config).
  • ifa_name is the adapter friendly name (what BindInterface matches on Windows).
  • Disabled/disconnected adapters are returned without IFF_UP, so the existing consumers skip them (matches POSIX getifaddrs(3) semantics).

Testing

Built on Windows x64 (Release). ssh.exe (OpenSSH_for_Windows_10.0p2) builds and links; Match localnetwork 127.0.0.0/8 matches the loopback (enumerated via getifaddrs), 203.0.113.0/24 does not, and the "not supported on this platform" path is gone. The getifaddrs unit checks pass. Sources also cross-compile for ARM64.

The "Match localnetwork" ssh_config criterion (readconf.c
check_match_ifaddrs) and the BindInterface interface enumeration in
sshconnect.c are gated on HAVE_IFADDRS_H. The Windows build never
defined it and win32compat provided no getifaddrs(), so the criterion
returned "match localnetwork: not supported on this platform".

Implement POSIX getifaddrs()/freeifaddrs() over the Win32
GetAdaptersAddresses() API and enable the feature:

- contrib/win32/win32compat/inc/ifaddrs.h: struct ifaddrs, IFF_* flags
  (Windows has no <net/if.h>), getifaddrs/freeifaddrs prototypes.
- contrib/win32/win32compat/getifaddrs.c: implementation over
  GetAdaptersAddresses(); ifa_name is the adapter friendly name, which
  is what BindInterface matches on Windows. Disabled/disconnected
  adapters are returned without IFF_UP, so the consumers skip them.
- config.h.vs: define HAVE_IFADDRS_H and HAVE_GETIFADDRS.
- win32iocompat.vcxproj(.filters): build the new sources into
  posix_compat.lib.
- ssh.vcxproj: link Iphlpapi.lib (GetAdaptersAddresses).
- regress/unittests/win32compat/getifaddrs_tests.c: unit tests for
  getifaddrs()/freeifaddrs(), registered in tests.c/tests.h and the
  unittest-win32compat project.

Verified on Windows: ssh.exe (OpenSSH_for_Windows_10.0p2) builds and
"Match localnetwork" evaluates correctly (matches a CIDR containing a
local interface address, e.g. loopback 127.0.0.0/8); getifaddrs unit
checks pass; sources also cross-compile for ARM64.
Copilot AI review requested due to automatic review settings June 23, 2026 11:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Windows support for ssh_config’s Match localnetwork (and the BindInterface address enumeration path) by providing a Win32-backed getifaddrs()/freeifaddrs() implementation in win32compat, then enabling and wiring it into the Visual Studio build and unit tests.

Changes:

  • Introduces contrib/win32/win32compat/getifaddrs.c plus a Windows ifaddrs.h shim (including minimal IFF_* flags).
  • Enables the feature in the Windows build (HAVE_IFADDRS_H, HAVE_GETIFADDRS) and builds/links the new code (adds Iphlpapi.lib where needed).
  • Adds a Win32compat unit test and registers it in the test runner.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
regress/unittests/win32compat/tests.h Registers the new getifaddrs unit test symbol.
regress/unittests/win32compat/tests.c Runs the new getifaddrs unit test.
regress/unittests/win32compat/getifaddrs_tests.c Adds unit tests for the Windows getifaddrs/freeifaddrs shim.
contrib/win32/win32compat/inc/ifaddrs.h Adds a Windows-compatible struct ifaddrs + prototypes + minimal IFF_* flags.
contrib/win32/win32compat/getifaddrs.c Implements getifaddrs/freeifaddrs over GetAdaptersAddresses().
contrib/win32/openssh/win32iocompat.vcxproj.filters Adds the new source/header to the VS filters.
contrib/win32/openssh/win32iocompat.vcxproj Builds the new getifaddrs.c into posix_compat.lib.
contrib/win32/openssh/unittest-win32compat.vcxproj Builds the new unit test and links Iphlpapi.lib.
contrib/win32/openssh/ssh.vcxproj Links Iphlpapi.lib for the client.
contrib/win32/openssh/config.h.vs Defines HAVE_IFADDRS_H and HAVE_GETIFADDRS for Windows builds.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread contrib/win32/win32compat/getifaddrs.c
Comment thread regress/unittests/win32compat/getifaddrs_tests.c Outdated
Address PR review feedback:

- getifaddrs.c: guarantee ifa_name is always set. Previously an entry
  could be emitted with ifa_name == NULL if the friendly-name conversion
  failed and the AdapterName fallback was unavailable; the consumers
  (readconf.c, sshconnect.c) skip NULL-name entries, which would silently
  drop valid addresses and violates the getifaddrs(3) contract. Treat the
  no-name case (in practice an allocation failure) as ENOMEM instead.

- getifaddrs_tests.c: drop the empty-list and IPv4-loopback assumptions
  (the implementation allows an empty list, and IPv4 may be disabled).
  Assert only the call result and per-entry invariants.
@steffen-heil-secforge steffen-heil-secforge force-pushed the feature/match-localnetwork-windows-upstream branch from 9238271 to 98cbc60 Compare June 23, 2026 12:04
@steffen-heil-secforge

Copy link
Copy Markdown
Author

Thanks for the review. Both points are addressed in 98cbc60 (kept as a separate commit on top of the original):

  1. getifaddrs.cifa_name can be NULL: ifa_name is now guaranteed to be set. GetAdaptersAddresses always provides AdapterName, so a NULL name in practice means an allocation failure; that case is now treated as ENOMEM and fails the call, rather than emitting a NULL-name entry. This keeps the getifaddrs(3) contract and prevents the consumers (readconf.c, sshconnect.c) from silently skipping addresses.

  2. getifaddrs_tests.c — brittle assumptions: dropped the non-empty-list and IPv4-loopback/IFF_UP expectations (an empty list is a valid result, and IPv4 may be disabled). The test now asserts only the call result and per-entry invariants (ifa_name/ifa_addr non-NULL, address family is AF_INET/AF_INET6).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants