What each platform can do
meshp has to move packets on Linux, Windows, macOS, Android and iOS (ADR-0015). Three of the five do. This page is where that is written down, and it is the only place — the same claim repeated across the README, the security policy and three guides went stale five times at a time, which is what #185 is about.
| Linux | macOS | Windows | Android | iOS | |
|---|---|---|---|---|---|
| A tunnel — carries traffic at all | yes | yes | yes | no | no |
| Names — mesh names resolve, and only mesh names (ADR-0021) | yes | yes | yes | no | no |
| A full-tunnel route — everything can be sent through the tunnel | yes | yes | yes | no | no |
| Fail-closed egress — traffic is refused when the tunnel drops (ADR-0011) | yes | yes | yes | no | no |
| A packet filter — a network's policy is enforced on the device (ADR-0007) | yes | no | no | no | no |
| Prompt recovery — a change of network is noticed rather than waited out (#172) | yes | yes | yes | no | no |
That table is not maintained by hand. Each row is a package with an implementation per
platform and one stub for everywhere else, and the stub's build tag says which platforms have
it — a line the compiler already forces to be right, because an implementation that exists and
is not excluded there does not build. internal/docscheck reads those tags and fails if this
page disagrees.
What a no costs
A device with no tunnel still enrols, holds an address, and reports honestly that it has no tunnel rather than pretending. That is deliberate: a device that can be seen and named is worth having before it can carry traffic.
A capability a platform lacks makes a network's requirement unhonoured, not half-applied. A macOS or Windows device in a network with a packet-filter policy reports the route group unconverged rather than accepting the policy and enforcing none of it — the dishonesty ADR-0007 and ADR-0011 are both written against.
Why the same capability is a different mechanism on each
Nothing here is one implementation with three build tags. Each platform reaches the same property by whatever it actually offers:
| Linux | macOS | Windows | |
|---|---|---|---|
| Tunnel | kernel WireGuard | wireguard-go on a utun |
wireguard-go on WinTun (ADR-0028) |
| Names | systemd-resolved | the SystemConfiguration store | the Name Resolution Policy Table (ADR-0029) |
| Full tunnel | a firewall mark and a routing table | two routes beating a default | the same, through the IP Helper API |
| Fail closed | an nftables table | a pf anchor under com.apple (ADR-0026) |
meshp's own filtering-platform provider (ADR-0030) |
The decision records are where the reasoning is. Each was written before its implementation, and each turned on the same question: is there a real undo — can meshp remove what it installed without keeping a copy of somebody else's configuration.
The two that have nothing
Android and iOS. ADR-0010 records why they will wrap the official WireGuard libraries rather
than porting this data plane, and #144 records the part CI cannot help with: a
NEPacketTunnelProvider does not run in the Simulator, so the packet path there needs
hardware whatever else is arranged.
Rendered from docs/platforms.md, which is where it is edited.