Introduce shared NIC source ownership and dispatcher handling so a
single dev_name can be shared by multiple tun-enabled instances while
keeping per-member IP and route claims distinct.
Pass Android VpnService fd registration with per-instance source and
route claims. Keep the VPN address list limited to real member
addresses and allow AF_INET6 without installing hidden fd00::1.
Invalidate dispatcher flow and NAT state when source ownership changes
or a member unregisters. Avoid rewriting non-first IPv4 fragment
payloads, and adjust fragmented TCP/UDP checksums without recomputing
over partial fragment bodies.
Preserve source-owner routing for equal-prefix route conflicts, keep
ICMP echo NAT entries distinct by echo id, and retry stale flow-owner
send failures from the original packet. Only record NAT state after a
translated packet is accepted by its member.
Apply Linux IPv4 route preferred-source hints for shared routes and keep
route repair paths source-aware. Keep Darwin ifcfg access scoped to
cleanup-only paths where netns is not available.
Android previously treated setTunFd as a single-instance update, and the
VpnService plugin could only expose one IPv4 address. That made shared
TUN members disable each other or leave only one address configured.
Group enabled Android TUN instances by shared dev_name, send the fd to
every compatible member, and only disable incompatible TUN users. Build
the Android VPN request from the whole running shared group and pass
every IPv4 address to VpnService.
The shared mobile dispatcher now owns current fd device state on a
process-level runtime. New setTunFd calls replace that state even when
the raw fd number is reused, and mobile TUN read/write/create failures
rebuild with backoff while preserving member registrations.
Protect shared member cleanup with per-registration ownership tokens, so
old async cleanup cannot unregister a recreated member or remove its
source claims. Mobile source addresses are registered in the dispatcher
without applying OS ifcfg changes, so Android-originated packets return
through the owning instance.
When one shared member stops while another remains, notify the frontend
to recalculate the VpnService config instead of leaving stale addresses
and routes. Serialize Android VpnService config recalculation so stale
async events cannot overwrite newer shared-group state.
If one shared member is not ready, rebuild from the healthy members and
retry the missing member later. If no healthy member remains, stop the
Android VPN service instead of keeping stale routes active.