diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 4bd935407..6c12862d0 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -493,8 +493,8 @@ func (pln *peerAPIListener) serve() { logf("peerapi: unexpected RemoteAddr %#v", c.RemoteAddr()) continue } - ipp, ok := netaddr.FromStdAddr(ta.IP, ta.Port, "") - if !ok { + ipp := netaddr.Unmap(ta.AddrPort()) + if !ipp.IsValid() { logf("peerapi: bogus TCPAddr %#v", ta) c.Close() continue diff --git a/net/netaddr/netaddr.go b/net/netaddr/netaddr.go index af4e32030..c5515c544 100644 --- a/net/netaddr/netaddr.go +++ b/net/netaddr/netaddr.go @@ -10,7 +10,6 @@ package netaddr import ( - "math" "net" "net/netip" ) @@ -20,6 +19,13 @@ func IPv4(a, b, c, d uint8) netip.Addr { return netip.AddrFrom4([4]byte{a, b, c, d}) } +// Unmap returns the provided AddrPort with its Addr IP component Unmap'ed. +// +// See https://github.com/golang/go/issues/53607#issuecomment-1203466984 +func Unmap(ap netip.AddrPort) netip.AddrPort { + return netip.AddrPortFrom(ap.Addr().Unmap(), ap.Port()) +} + // FromStdIPNet returns an IPPrefix from the standard library's IPNet type. // If std is invalid, ok is false. func FromStdIPNet(std *net.IPNet) (prefix netip.Prefix, ok bool) { @@ -42,21 +48,3 @@ func FromStdIPNet(std *net.IPNet) (prefix netip.Prefix, ok bool) { return netip.PrefixFrom(ip, ones), true } - -// FromStdAddr maps the components of a standard library TCPAddr or -// UDPAddr into an IPPort. -func FromStdAddr(stdIP net.IP, port int, zone string) (_ netip.AddrPort, ok bool) { - ip, ok := netip.AddrFromSlice(stdIP) - if !ok || port < 0 || port > math.MaxUint16 { - return - } - ip = ip.Unmap() - if zone != "" { - if ip.Is4() { - ok = false - return - } - ip = ip.WithZone(zone) - } - return netip.AddrPortFrom(ip, uint16(port)), true -} diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index 7c382a55d..e11887484 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -273,7 +273,8 @@ func (c *Client) ReceiveSTUNPacket(pkt []byte, src netip.AddrPort) { } rs.mu.Unlock() if ok { - if ipp, ok := netaddr.FromStdAddr(addr, int(port), ""); ok { + ta := net.TCPAddr{IP: addr, Port: int(port)} + if ipp := netaddr.Unmap(ta.AddrPort()); ipp.IsValid() { onDone(ipp) } } @@ -516,8 +517,8 @@ func (c *Client) readPackets(ctx context.Context, pc net.PacketConn) { if !stun.Is(pkt) { continue } - if ipp, ok := netaddr.FromStdAddr(ua.IP, ua.Port, ua.Zone); ok { - c.ReceiveSTUNPacket(pkt, ipp) + if ap := netaddr.Unmap(ua.AddrPort()); ap.IsValid() { + c.ReceiveSTUNPacket(pkt, ap) } } } diff --git a/net/portmapper/igd_test.go b/net/portmapper/igd_test.go index b7da94c16..4b56ce196 100644 --- a/net/portmapper/igd_test.go +++ b/net/portmapper/igd_test.go @@ -167,9 +167,8 @@ func (d *TestIGD) servePxP() { } return } - ua := a.(*net.UDPAddr) - src, ok := netaddr.FromStdAddr(ua.IP, ua.Port, ua.Zone) - if !ok { + src := netaddr.Unmap(a.(*net.UDPAddr).AddrPort()) + if !src.IsValid() { panic("bogus addr") } pkt := buf[:n] diff --git a/net/portmapper/portmapper.go b/net/portmapper/portmapper.go index f5bec3262..2eb06a026 100644 --- a/net/portmapper/portmapper.go +++ b/net/portmapper/portmapper.go @@ -531,8 +531,8 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netip.AddrPor return netip.AddrPort{}, NoMappingError{ErrNoPortMappingServices} } srcu := srci.(*net.UDPAddr) - src, ok := netaddr.FromStdAddr(srcu.IP, srcu.Port, srcu.Zone) - if !ok { + src := netaddr.Unmap(srcu.AddrPort()) + if !src.IsValid() { continue } if src == pxpAddr { diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 618ccd3c7..f1330f3ca 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -3037,8 +3037,8 @@ func (c *RebindingUDPConn) ReadFromNetaddr(b []byte) (n int, ipp netip.AddrPort, return 0, netip.AddrPort{}, fmt.Errorf("RebindingUDPConn.ReadFromNetaddr: underlying connection returned address of type %T, want *netaddr.UDPAddr", addr) } if pAddr != nil { - ipp, ok = netaddr.FromStdAddr(pAddr.IP, pAddr.Port, pAddr.Zone) - if !ok { + ipp = netaddr.Unmap(pAddr.AddrPort()) + if !ipp.IsValid() { return 0, netip.AddrPort{}, errors.New("netaddr.FromStdAddr failed") } } diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go index f0424c907..46e23561f 100644 --- a/wgengine/netstack/netstack.go +++ b/wgengine/netstack/netstack.go @@ -848,7 +848,7 @@ func (ns *Impl) forwardTCP(client *gonet.TCPConn, clientRemoteIP netip.Addr, wq } defer server.Close() backendLocalAddr := server.LocalAddr().(*net.TCPAddr) - backendLocalIPPort, _ := netaddr.FromStdAddr(backendLocalAddr.IP, backendLocalAddr.Port, backendLocalAddr.Zone) + backendLocalIPPort := netaddr.Unmap(backendLocalAddr.AddrPort()) ns.e.RegisterIPPortIdentity(backendLocalIPPort, clientRemoteIP) defer ns.e.UnregisterIPPortIdentity(backendLocalIPPort) connClosed := make(chan error, 2) @@ -978,8 +978,9 @@ func (ns *Impl) forwardUDP(client *gonet.UDPConn, wq *waiter.Queue, clientAddr, } } backendLocalAddr := backendConn.LocalAddr().(*net.UDPAddr) - backendLocalIPPort, ok := netaddr.FromStdAddr(backendListenAddr.IP, backendLocalAddr.Port, backendLocalAddr.Zone) - if !ok { + + backendLocalIPPort := netip.AddrPortFrom(backendListenAddr.AddrPort().Addr().Unmap().WithZone(backendLocalAddr.Zone), backendLocalAddr.AddrPort().Port()) + if !backendLocalIPPort.IsValid() { ns.logf("could not get backend local IP:port from %v:%v", backendLocalAddr.IP, backendLocalAddr.Port) } if isLocal { @@ -1061,5 +1062,17 @@ func stringifyTEI(tei stack.TransportEndpointID) string { } func ipPortOfNetstackAddr(a tcpip.Address, port uint16) (ipp netip.AddrPort, ok bool) { - return netaddr.FromStdAddr(net.IP(a), int(port), "") // TODO(bradfitz): can do without allocs + var a16 [16]byte + copy(a16[:], a) + switch len(a) { + case 4: + return netip.AddrPortFrom( + netip.AddrFrom4(*(*[4]byte)(a16[:4])).Unmap(), + port, + ), true + case 16: + return netip.AddrPortFrom(netip.AddrFrom16(a16).Unmap(), port), true + default: + return ipp, false + } }