Skip to content

fix(libSceNetCtl): read the default route from the routing table on macOS - #6685

Merged
adriadam10 merged 7 commits into
boykopovar:mainfrom
DavidSamir:fix/netctl-default-route-macos
Oct 19, 2026
Merged

adriadam10 merged 7 commits into
boykopovar:mainfrom
DavidSamir:fix/netctl-default-route-macos

Conversation

@DavidSamir

@DavidSamir DavidSamir commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

What

sceNetCtlGetInfo finds the host's default route in /proc/net/route, which macOS does not have, so on macOS every IPv4 query throws:

sceNetCtlGetInfo: the host routing table is unavailable

On macOS it now reads the IPv4 routes that have a gateway with sysctl({CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_FLAGS, RTF_GATEWAY}), the table netstat -rn shows, and keeps the routes to 0.0.0.0 that are up, neither rejecting nor host routes, on an interface that still exists. macOS keeps an unscoped default route, the one it sends traffic by, beside interface-scoped ones (RTF_IFSCOPE), which rank after it. Address, netmask, MTU and DNS servers already come from getifaddrs, SIOCGIFMTU and /etc/resolv.conf, which macOS has. Linux and Windows are unchanged.

The parsing is exported as NetCtlDefaultRoutes_nid_no_patch, like NetCtlReadByteCounter_nid_no_patch, so a test can feed it a routing table built by hand: an unscoped default route, a host route, a host route to 0.0.0.0, a rejecting default route, an interface-scoped one, one that is down, one on an interface that does not exist and a truncated last message.

sceNetCtlGetIfStat keeps throwing on macOS, now with a debt entry: an unprivileged process reads the interface byte counters, through getifaddrs and sysctl(NET_RT_IFLIST2) alike, reduced to their low 32 bits (en0 here: 426753024 received against 47671393472 in netstat -ib, 11 times 2^32 less), so a total would wrap every 4 GiB.

Commits: the macOS route lookup, its test, the debt entries.

Tested

macOS 26.7.1, Apple M2 on Wi-Fi, AppleClang 21.0.0, x86-64 build under Rosetta, Release.

main does not build libc and libkernel on macOS for other reasons as well (#4627, #4630, #6124 and mugurc's macOS branches address them), so the tests ran in a local tree of main ce991f1 with those merged.

  • main: guest_net_ctl aborts with the error above.
  • This branch: guest_net_ctl passes 5 runs of 5. The values it reads match the host: address 192.168.0.102, gateway 192.168.0.1 (route -n get default), MTU 1500, first IPv4 DNS server 192.168.0.1 (/etc/resolv.conf).
  • The new case fails when host routes are kept (aborts) and when scoped routes are not ranked after the unscoped one (aborts).
  • tools/check_conventions.py --base origin/main and git diff --check pass.

Windows 11 (WinLibs GCC 15.2.0 r7, UCRT, Release) and Ubuntu 24.04 under WSL2 (GCC 13.3.0, Release), head 80a9ef9e3 merged onto main 5d9dcc4: guest_net_ctl pass 3 runs of 3 with the change, and 3 runs of 3 with libSceNetCtl/Export.cpp as on main and the tests kept. It passes either way there: their code paths are unchanged and the new test case is compiled on macOS only.

Overlap: #6138 (callbacks) edits the declarations and the start of main in GuestNetCtl.cpp, and #6039, #6138 and #6227 edit the sceNetCtlGetInfo entry next to the new debt entries; none of them changes how the route is found. #6044 moves GuestNetCtl.cpp. Whichever lands second rebases.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Unblocks: none named; ProsperoLichess (PPSA99009) and Prospero Explorer (PPSA99109) import sceNetCtlGetInfo, but on macOS neither reached it in a 45 s run
  • GPUs tested: n/a
  • AI-assisted: yes

…acOS

sceNetCtlGetInfo found the host's default route in /proc/net/route, which
macOS does not have, so every IPv4 query threw "the host routing table is
unavailable" there. On macOS it now reads the IPv4 routes that have a
gateway with sysctl(NET_RT_FLAGS, RTF_GATEWAY) and keeps those to
0.0.0.0 that are up, neither rejecting nor host routes, on an interface
that still exists. An interface-scoped default route ranks after the
unscoped one, the route macOS sends traffic by. The parsing is exported
as NetCtlDefaultRoutes_nid_no_patch so it can be tested on a routing
table built by hand.
… route

A routing table built by hand with an unscoped default route, a host
route, a host route to 0.0.0.0, a rejecting default route, an
interface-scoped default route, one that is down, one on an interface
that does not exist and a truncated last message must give the unscoped
route first and the scoped one after it, and must count every match
while writing only as many as fit.
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 6039 docs/dev/debt/libSceNetCtl.md
PR 6044 core/libs/tests/GuestNetCtl.cpp
PR 7201 core/libs/prx/libSceNetCtl/Export.cpp

@DavidSamir

Copy link
Copy Markdown
Contributor Author

Windows and Linux results for 80a9ef9, merged onto main 5d9dcc4:

Host Toolchain With the change Code as on main, new tests kept Restored
Windows 11 WinLibs GCC 15.2.0 r7 (UCRT), Release guest_net_ctl 3/3 3/3 1/1
Ubuntu 24.04 (WSL2) GCC 13.3.0, Release guest_net_ctl 3/3 3/3 1/1

Reverted for the middle column: libSceNetCtl/Export.cpp. The test passes either way on both hosts, as expected for a macOS-only routing-table path. Windows and Linux still build and pass with it.

AI-assisted: yes

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 17, 2026
@blawesom

Copy link
Copy Markdown
Contributor

Rebase handoff — rebased onto current main (authorship unchanged). One docs-debt conflict, unioned.

Verified on Linux (CachyOS, kernel 7.2.9, GCC 16.2.1, Ninja, Release, BUILD_TESTING=ON, AMD RX 9070 XT / RADV):

To pick it up:

git fetch https://github.com/blawesom/AnyPS5 rebase/6685
git checkout <your branch>
git merge --ff-only FETCH_HEAD

Head is 90d1f458a.

…ute-macos

# Conflicts:
#	docs/dev/debt/libSceNetCtl.md
@DavidSamir

Copy link
Copy Markdown
Contributor Author

Thanks, @blawesom. I checked your rebase/6685 against this branch: the code commits are identical, and the debt-file commit differs only by the conflict resolution. Rather than force-pushing, I merged current main into the branch with the same resolution, so the history stays as reviewed. The PR's diff against main now matches your rebase. Head is 26bc5ce87, and it merges cleanly with main.

AI-assisted: yes

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 17, 2026
ycarogabriel-lgtm added a commit to ycarogabriel-lgtm/AnyPS5 that referenced this pull request Oct 17, 2026
…le on macOS (@DavidSamir)

Replaces this branch's equivalent sysctl(NET_RT_DUMP) reader with the PR's, which parses the routing messages in a separate function with its own tests and is the version going upstream. This branch's macOS byte counters for sceNetCtlGetIfStat, which the PR does not cover, are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 17, 2026
ycarogabriel-lgtm added a commit to ycarogabriel-lgtm/AnyPS5 that referenced this pull request Oct 18, 2026
…le on macOS (@DavidSamir)

Replaces this branch's equivalent sysctl(NET_RT_DUMP) reader with the PR's, which parses the routing messages in a separate function with its own tests and is the version going upstream. This branch's macOS byte counters for sceNetCtlGetIfStat, which the PR does not cover, are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ute-macos

# Conflicts:
#	docs/dev/debt/libSceNetCtl.md
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 18, 2026
…ute-macos

# Conflicts:
#	core/libs/tests/GuestNetCtl.cpp
#	docs/dev/debt/libSceNetCtl.md
…ute-macos

# Conflicts:
#	core/libs/tests/GuestNetCtl.cpp
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 18, 2026
@adriadam10 adriadam10 self-assigned this Oct 19, 2026
@adriadam10
adriadam10 merged commit 1f9e350 into boykopovar:main Oct 19, 2026
10 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the diff: the macOS path is confined to __APPLE__, the routing-message parser stays inside rtm_msglen/sa_len and the buffer size, the filters (up, not reject/host, destination 0.0.0.0, existing interface) and the scoped-route ranking match the description, the test pins values on a hand-built table including the truncated last message, and the debt entries are in place. Linux/Windows code paths are unchanged. macOS runtime behaviour relies on the author's run; merged.

ycarogabriel-lgtm added a commit to ycarogabriel-lgtm/AnyPS5 that referenced this pull request Oct 19, 2026
Brings in main's 49 newer commits. Seven of the PRs this branch carried
are now in main (boykopovar#6647, boykopovar#6667, boykopovar#6668, boykopovar#6685, boykopovar#6686, boykopovar#6767, boykopovar#6802), so
the branch shrinks by them.

Conflicts:
- GuestGetrlimit: main adds a check that 1024 stdio streams open on
  Windows; it runs after this branch's descriptor exhaustion helper,
  which Windows and macOS share.
- the relinker keeps this branch's macOS fixture test beside main's
  macOS fixed-base test from boykopovar#6802.
- the libkernel and shader debt files take main's text and keep this
  branch's short macOS entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs prx unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants