Skip to content

net: support IPv6 in the host netdev and TCP/UDP plumbing#60

Open
0pcom wants to merge 2 commits into
tinygo-org:mainfrom
0magnet:native-netdev-ipv6
Open

net: support IPv6 in the host netdev and TCP/UDP plumbing#60
0pcom wants to merge 2 commits into
tinygo-org:mainfrom
0magnet:native-netdev-ipv6

Conversation

@0pcom

@0pcom 0pcom commented Jun 23, 2026

Copy link
Copy Markdown

Summary

Makes the TinyGo net package address-family aware so IPv6 works on the native
Linux host netdev, instead of being hard-coded to IPv4.

Stacked on #59. This branch builds on the host-netdev PR (#59) and includes
its commit; it should be reviewed/merged after #59. The IPv6-specific commit is
net: support IPv6 in the host netdev and TCP/UDP plumbing.

What changes

Shared net plumbing:

  • DialTCP, listenTCP, and DialUDP choose AF_INET/AF_INET6 from the target
    address via a new socketFamily() helper instead of always using AF_INET.
  • The "only ipv4 supported" guard in DialTCP becomes a 4-or-16-byte length
    check; DialUDP gets the same guard.
  • "tcp6"/"udp6" network names are accepted.

Host netdev (netdev_native.go):

  • sockaddrFromParts builds a syscall.SockaddrInet6 for IPv6 addresses
    (SockaddrInet4 otherwise, with the zero address as the 0.0.0.0 wildcard).
  • Accept decodes both SockaddrInet4 and SockaddrInet6.
  • GetHostByName and the /etc/hosts lookup accept IPv6 addresses; the stub
    UDP resolver now queries AAAA after A.

Behaviour / scope

  • Name resolution still prefers IPv4 (A first, then AAAA), and the /etc/hosts
    lookup prefers a v4 match. Because the netdever.GetHostByName interface has no
    family argument, the "4"/"6" network suffix is advisory for host names — this
    is documented on Dial/Listen. Dialing a literal IPv6 address always uses IPv6.
  • Link-local IPv6 zones (%zone) are not resolved to a scope id.

Verification

Built and run with tinygo on linux/amd64:

  • IPv6 loopback: net.Listen("tcp", "[::1]:…") + Accept + net.Dial round-trips,
    RemoteAddr() reports the [::1] peer.
  • net.ResolveTCPAddr("tcp", "ipv6.google.com:80") returns an IPv6 (AAAA) address
    (A-then-AAAA fallback), while a dual-stack host (example.com) still resolves to
    IPv4.
  • All IPv4 paths (loopback, DNS, outbound TCP, http.Get) unchanged.

0pcom added 2 commits June 23, 2026 17:59
On the native linux target the net package defaulted to a NOP netdev that
returns "Netdev not set" for every operation, so net.Dial/Listen, DNS and
anything built on them (net/http, tls) failed at runtime.

Native linux does not override the syscall package, and the TinyGo compiler
lowers syscall.Syscall/RawSyscall into real system calls, so the standard
library socket functions work directly (musl's omitted network module is not
needed). Register a default netdev implementing the netdever interface on top
of syscall.Socket/Connect/Bind/Listen/Accept/Send/Recv/SetSockOpt, plus a
small UDP DNS resolver (/etc/hosts, /etc/resolv.conf) for GetHostByName. Also
restore the net.DNSError type used by resolution errors.

Blocking sockets under the threads scheduler; IPv4 only. This avoids the
internal/poll netpoller dependency that blocked the upstream-net approach.

Refs tinygo-org#28
Make the net package address-family aware instead of IPv4-only: DialTCP,
listenTCP and DialUDP now choose AF_INET or AF_INET6 from the target address
(socketFamily), the "only ipv4 supported" guard is replaced by a 4-or-16 byte
check, and "tcp6"/"udp6" network names are accepted.

In the host netdev, sockaddrFromParts builds a SockaddrInet6 for IPv6 addresses
(SockaddrInet4 otherwise), Accept decodes both families, GetHostByName and the
/etc/hosts lookup accept IPv6, and the stub resolver now queries AAAA after A.
Name resolution still prefers IPv4, so the "4"/"6" suffix is advisory for host
names; this is documented on Dial/Listen. Link-local IPv6 zones are not mapped
to a scope id.

Verified on linux/amd64 with tinygo: IPv6 loopback Listen/Accept/Dial over
[::1], AAAA fallback for an IPv6-only host name, and IPv4 behaviour unchanged.
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.

1 participant