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

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.
This commit is contained in:
Moses Narrow
2026-06-23 18:19:40 -05:00
committed by Ron Evans
parent 7bf471a0a9
commit 2be2e34090
5 changed files with 105 additions and 53 deletions
+5 -3
View File
@@ -83,7 +83,7 @@ func (a *UDPAddr) opAddr() Addr {
func ResolveUDPAddr(network, address string) (*UDPAddr, error) {
switch network {
case "udp", "udp4":
case "udp", "udp4", "udp6":
default:
return nil, fmt.Errorf("Network '%s' not supported", network)
}
@@ -156,7 +156,7 @@ func ephemeralPort() int {
// local system is assumed.
func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error) {
switch network {
case "udp", "udp4":
case "udp", "udp4", "udp6":
default:
return nil, fmt.Errorf("Network '%s' not supported", network)
}
@@ -173,6 +173,8 @@ func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error) {
if raddr.IP.IsUnspecified() {
return nil, fmt.Errorf("Sorry, localhost isn't available on Tinygo")
} else if len(raddr.IP) != 4 && len(raddr.IP) != 16 {
return nil, fmt.Errorf("invalid IP address")
}
// If no port was given, grab an ephemeral port
@@ -180,7 +182,7 @@ func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error) {
laddr.Port = ephemeralPort()
}
fd, err := netdev.Socket(_AF_INET, _SOCK_DGRAM, _IPPROTO_UDP)
fd, err := netdev.Socket(socketFamily(raddr.IP), _SOCK_DGRAM, _IPPROTO_UDP)
if err != nil {
return nil, err
}