diff --git a/cmd/hello/hello.go b/cmd/hello/hello.go index 0e7b64890..0c135916e 100644 --- a/cmd/hello/hello.go +++ b/cmd/hello/hello.go @@ -112,13 +112,13 @@ func tailscaleIP(who *apitype.WhoIsResponse) string { return "" } for _, nodeIP := range who.Node.Addresses { - if nodeIP.IP.Is4() && nodeIP.IsSingleIP() { - return nodeIP.IP.String() + if nodeIP.IP().Is4() && nodeIP.IsSingleIP() { + return nodeIP.IP().String() } } for _, nodeIP := range who.Node.Addresses { if nodeIP.IsSingleIP() { - return nodeIP.IP.String() + return nodeIP.IP().String() } } return "" diff --git a/cmd/tailscale/cli/file.go b/cmd/tailscale/cli/file.go index 7b6e45600..01dc68d83 100644 --- a/cmd/tailscale/cli/file.go +++ b/cmd/tailscale/cli/file.go @@ -194,7 +194,7 @@ func discoverPeerAPIBase(ctx context.Context, ipStr string) (base string, lastSe for _, ft := range fts { n := ft.Node for _, a := range n.Addresses { - if a.IP != ip { + if a.IP() != ip { continue } if n.LastSeen != nil { @@ -301,7 +301,7 @@ func runCpTargets(ctx context.Context, args []string) error { if detail != "" { detail = "\t" + detail } - fmt.Printf("%s\t%s%s\n", n.Addresses[0].IP, n.ComputedName, detail) + fmt.Printf("%s\t%s%s\n", n.Addresses[0].IP(), n.ComputedName, detail) } return nil } diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 35b29deb9..d8e24a095 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -164,10 +164,10 @@ func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goo routes = append(routes, r) } sort.Slice(routes, func(i, j int) bool { - if routes[i].Bits != routes[j].Bits { - return routes[i].Bits < routes[j].Bits + if routes[i].Bits() != routes[j].Bits() { + return routes[i].Bits() < routes[j].Bits() } - return routes[i].IP.Less(routes[j].IP) + return routes[i].IP().Less(routes[j].IP()) }) var exitNodeIP netaddr.IP @@ -723,10 +723,10 @@ func fmtFlagValueArg(flagName string, val interface{}) string { func hasExitNodeRoutes(rr []netaddr.IPPrefix) bool { var v4, v6 bool for _, r := range rr { - if r.Bits == 0 { - if r.IP.Is4() { + if r.Bits() == 0 { + if r.IP().Is4() { v4 = true - } else if r.IP.Is6() { + } else if r.IP().Is6() { v6 = true } } @@ -743,7 +743,7 @@ func withoutExitNodes(rr []netaddr.IPPrefix) []netaddr.IPPrefix { } var out []netaddr.IPPrefix for _, r := range rr { - if r.Bits > 0 { + if r.Bits() > 0 { out = append(out, r) } } diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 8b4e89a36..63296204d 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -266,7 +266,7 @@ func run() error { if err != nil { return nil, err } - if ns != nil && useNetstackForIP(ipp.IP) { + if ns != nil && useNetstackForIP(ipp.IP()) { return ns.DialContextTCP(ctx, addr) } var d net.Dialer diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 3ebc2d29e..1f884e2ce 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -1091,7 +1091,7 @@ func ipForwardingBroken(routes []netaddr.IPPrefix, state *interfaces.State) bool localIPs := map[netaddr.IP]bool{} for _, addrs := range state.InterfaceIPs { for _, pfx := range addrs { - localIPs[pfx.IP] = true + localIPs[pfx.IP()] = true } } @@ -1100,10 +1100,10 @@ func ipForwardingBroken(routes []netaddr.IPPrefix, state *interfaces.State) bool // It's possible to advertise a route to one of the local // machine's local IPs. IP forwarding isn't required for this // to work, so we shouldn't warn for such exports. - if r.IsSingleIP() && localIPs[r.IP] { + if r.IsSingleIP() && localIPs[r.IP()] { continue } - if r.IP.Is4() { + if r.IP().Is4() { v4Routes = true } else { v6Routes = true diff --git a/control/controlclient/direct_test.go b/control/controlclient/direct_test.go index 4d2607616..01605248b 100644 --- a/control/controlclient/direct_test.go +++ b/control/controlclient/direct_test.go @@ -86,7 +86,7 @@ func TestNewDirect(t *testing.T) { func fakeEndpoints(ports ...uint16) (ret []tailcfg.Endpoint) { for _, port := range ports { ret = append(ret, tailcfg.Endpoint{ - Addr: netaddr.IPPort{Port: port}, + Addr: netaddr.IPPortFrom(netaddr.IP{}, port), }) } return diff --git a/disco/disco.go b/disco/disco.go index e43f6103b..837784fa1 100644 --- a/disco/disco.go +++ b/disco/disco.go @@ -147,9 +147,9 @@ type CallMeMaybe struct { func (m *CallMeMaybe) AppendMarshal(b []byte) []byte { ret, p := appendMsgHeader(b, TypeCallMeMaybe, v0, epLength*len(m.MyNumber)) for _, ipp := range m.MyNumber { - a := ipp.IP.As16() + a := ipp.IP().As16() copy(p[:], a[:]) - binary.BigEndian.PutUint16(p[16:], ipp.Port) + binary.BigEndian.PutUint16(p[16:], ipp.Port()) p = p[epLength:] } return ret @@ -164,10 +164,9 @@ func parseCallMeMaybe(ver uint8, p []byte) (m *CallMeMaybe, err error) { for len(p) > 0 { var a [16]byte copy(a[:], p) - m.MyNumber = append(m.MyNumber, netaddr.IPPort{ - IP: netaddr.IPFrom16(a), - Port: binary.BigEndian.Uint16(p[16:18]), - }) + m.MyNumber = append(m.MyNumber, netaddr.IPPortFrom( + netaddr.IPFrom16(a), + binary.BigEndian.Uint16(p[16:18]))) p = p[epLength:] } return m, nil @@ -187,9 +186,9 @@ type Pong struct { func (m *Pong) AppendMarshal(b []byte) []byte { ret, d := appendMsgHeader(b, TypePong, v0, pongLen) d = d[copy(d, m.TxID[:]):] - ip16 := m.Src.IP.As16() + ip16 := m.Src.IP().As16() d = d[copy(d, ip16[:]):] - binary.BigEndian.PutUint16(d, m.Src.Port) + binary.BigEndian.PutUint16(d, m.Src.Port()) return ret } @@ -201,10 +200,10 @@ func parsePong(ver uint8, p []byte) (m *Pong, err error) { copy(m.TxID[:], p) p = p[12:] - m.Src.IP, _ = netaddr.FromStdIP(net.IP(p[:16])) + srcIP, _ := netaddr.FromStdIP(net.IP(p[:16])) p = p[16:] - - m.Src.Port = binary.BigEndian.Uint16(p) + port := binary.BigEndian.Uint16(p) + m.Src = netaddr.IPPortFrom(srcIP, port) return m, nil } diff --git a/go.mod b/go.mod index 3378debf4..f2f955641 100644 --- a/go.mod +++ b/go.mod @@ -40,10 +40,10 @@ require ( golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8 gopkg.in/yaml.v2 v2.2.8 // indirect honnef.co/go/tools v0.1.0 - inet.af/netaddr v0.0.0-20210511181906-37180328850c + inet.af/netaddr v0.0.0-20210515010201-ad03edc7c841 inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22 inet.af/peercred v0.0.0-20210302202138-56e694897155 - inet.af/wf v0.0.0-20210424212123-eaa011a774a4 + inet.af/wf v0.0.0-20210516214145-a5343001b756 rsc.io/goversion v1.2.0 ) diff --git a/go.sum b/go.sum index d7017de21..aed9021cc 100644 --- a/go.sum +++ b/go.sum @@ -258,11 +258,17 @@ inet.af/netaddr v0.0.0-20210508014949-da1c2a70a83d h1:9tuJMxDV7THGfXWirKBD/v9rbs inet.af/netaddr v0.0.0-20210508014949-da1c2a70a83d/go.mod h1:z0nx+Dh+7N7CC8V5ayHtHGpZpxLQZZxkIaaz6HN65Ls= inet.af/netaddr v0.0.0-20210511181906-37180328850c h1:rzDy/tC8LjEdN94+i0Bu22tTo/qE9cvhKyfD0HMU0NU= inet.af/netaddr v0.0.0-20210511181906-37180328850c/go.mod h1:z0nx+Dh+7N7CC8V5ayHtHGpZpxLQZZxkIaaz6HN65Ls= +inet.af/netaddr v0.0.0-20210515010201-ad03edc7c841 h1:2HpK+rC0Arcu98JukIlyVfEaE2OsvtmBFc8rs/2SJYs= +inet.af/netaddr v0.0.0-20210515010201-ad03edc7c841/go.mod h1:z0nx+Dh+7N7CC8V5ayHtHGpZpxLQZZxkIaaz6HN65Ls= inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22 h1:DNtszwGa6w76qlIr+PbPEnlBJdiRV8SaxeigOy0q1gg= inet.af/netstack v0.0.0-20210317161235-a1bf4e56ef22/go.mod h1:GVx+5OZtbG4TVOW5ilmyRZAZXr1cNwfqUEkTOtWK0PM= inet.af/peercred v0.0.0-20210302202138-56e694897155 h1:KojYNEYqDkZ2O3LdyTstR1l13L3ePKTIEM2h7ONkfkE= inet.af/peercred v0.0.0-20210302202138-56e694897155/go.mod h1:FjawnflS/udxX+SvpsMgZfdqx2aykOlkISeAsADi5IU= inet.af/wf v0.0.0-20210424212123-eaa011a774a4 h1:g1VVXY1xRKoO17aKY3g9KeJxDW0lGx1n2Y+WPSWkOL8= inet.af/wf v0.0.0-20210424212123-eaa011a774a4/go.mod h1:56/0QVlZ4NmPRh1QuU2OfrKqjSgt5P39R534gD2JMpQ= +inet.af/wf v0.0.0-20210515021317-09f8efa8ac30 h1:TLxVVv7rmErJW7l81tbbR2BkOIYBI3YdxbJbEs/HJt8= +inet.af/wf v0.0.0-20210515021317-09f8efa8ac30/go.mod h1:ViGMZRA6+RA318D7GCncrjv5gHUrPYrNDejjU12tikA= +inet.af/wf v0.0.0-20210516214145-a5343001b756 h1:muIT3C1rH3/xpvIH8blKkMvhctV7F+OtZqs7kcwHDBQ= +inet.af/wf v0.0.0-20210516214145-a5343001b756/go.mod h1:ViGMZRA6+RA318D7GCncrjv5gHUrPYrNDejjU12tikA= rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w= rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo= diff --git a/internal/deephash/deephash_test.go b/internal/deephash/deephash_test.go index 909c69ec0..d99612adc 100644 --- a/internal/deephash/deephash_test.go +++ b/internal/deephash/deephash_test.go @@ -33,7 +33,7 @@ func getVal() []interface{} { return []interface{}{ &wgcfg.Config{ Name: "foo", - Addresses: []netaddr.IPPrefix{{Bits: 5, IP: netaddr.IPFrom16([16]byte{3: 3})}}, + Addresses: []netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.IPFrom16([16]byte{3: 3}), 5)}, Peers: []wgcfg.Peer{ { Endpoints: wgcfg.Endpoints{ diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 9bb418514..9ebdf77f5 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -356,14 +356,14 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) { var tailAddr4 string var tailscaleIPs = make([]netaddr.IP, 0, len(p.Addresses)) for _, addr := range p.Addresses { - if addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.IP) { - if addr.IP.Is4() && tailAddr4 == "" { + if addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.IP()) { + if addr.IP().Is4() && tailAddr4 == "" { // The peer struct previously only allowed a single // Tailscale IP address. For compatibility for a few releases starting // with 1.8, keep it pulled out as IPv4-only for a bit. - tailAddr4 = addr.IP.String() + tailAddr4 = addr.IP().String() } - tailscaleIPs = append(tailscaleIPs, addr.IP) + tailscaleIPs = append(tailscaleIPs, addr.IP()) } } sb.AddPeer(key.Public(p.Key), &ipnstate.PeerStatus{ @@ -390,10 +390,10 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) { func (b *LocalBackend) WhoIs(ipp netaddr.IPPort) (n *tailcfg.Node, u tailcfg.UserProfile, ok bool) { b.mu.Lock() defer b.mu.Unlock() - n, ok = b.nodeByAddr[ipp.IP] + n, ok = b.nodeByAddr[ipp.IP()] if !ok { var ip netaddr.IP - if ipp.Port != 0 { + if ipp.Port() != 0 { ip, ok = b.e.WhoIsIPPort(ipp) } if !ok { @@ -552,7 +552,7 @@ func (b *LocalBackend) findExitNodeIDLocked(nm *netmap.NetworkMap) (prefsChanged for _, peer := range nm.Peers { for _, addr := range peer.Addresses { - if !addr.IsSingleIP() || addr.IP != b.prefs.ExitNodeIP { + if !addr.IsSingleIP() || addr.IP() != b.prefs.ExitNodeIP { continue } // Found the node being referenced, upgrade prefs to @@ -891,7 +891,7 @@ func (b *LocalBackend) updateFilter(netMap *netmap.NetworkMap, prefs *ipn.Prefs) } if prefs != nil { for _, r := range prefs.AdvertiseRoutes { - if r.Bits == 0 { + if r.Bits() == 0 { // When offering a default route to the world, we // filter out locally reachable LANs, so that the // default route effectively appears to be a "guest @@ -959,13 +959,13 @@ func (b *LocalBackend) updateFilter(netMap *netmap.NetworkMap, prefs *ipn.Prefs) func interfaceRoutes() (ips *netaddr.IPSet, hostIPs []netaddr.IP, err error) { var b netaddr.IPSetBuilder if err := interfaces.ForeachInterfaceAddress(func(_ interfaces.Interface, pfx netaddr.IPPrefix) { - if tsaddr.IsTailscaleIP(pfx.IP) { + if tsaddr.IsTailscaleIP(pfx.IP()) { return } if pfx.IsSingleIP() { return } - hostIPs = append(hostIPs, pfx.IP) + hostIPs = append(hostIPs, pfx.IP()) b.AddPrefix(pfx) }); err != nil { return nil, nil, err @@ -1751,10 +1751,10 @@ func (b *LocalBackend) authReconfig() { // https://github.com/tailscale/tailscale/issues/1152 // tracks adding the right capability reporting to // enable AAAA in MagicDNS. - if addr.IP.Is6() { + if addr.IP().Is6() { continue } - ips = append(ips, addr.IP) + ips = append(ips, addr.IP()) } dcfg.Hosts[fqdn] = ips } @@ -1809,10 +1809,7 @@ func parseResolver(cfg tailcfg.DNSResolver) (netaddr.IPPort, error) { if err != nil { return netaddr.IPPort{}, fmt.Errorf("[unexpected] non-IP resolver %q", cfg.Addr) } - return netaddr.IPPort{ - IP: ip, - Port: 53, - }, nil + return netaddr.IPPortFrom(ip, 53), nil } // tailscaleVarRoot returns the root directory of Tailscale's writable @@ -1870,7 +1867,7 @@ func (b *LocalBackend) initPeerAPIListener() { if len(b.netMap.Addresses) == len(b.peerAPIListeners) { allSame := true for i, pln := range b.peerAPIListeners { - if pln.ip != b.netMap.Addresses[i].IP { + if pln.ip != b.netMap.Addresses[i].IP() { allSame = false break } @@ -1915,7 +1912,7 @@ func (b *LocalBackend) initPeerAPIListener() { var err error skipListen := i > 0 && isNetstack if !skipListen { - ln, err = ps.listen(a.IP, b.prevIfState) + ln, err = ps.listen(a.IP(), b.prevIfState) if err != nil { if runtime.GOOS == "windows" { // Expected for now. See Issue 1620. @@ -1929,7 +1926,7 @@ func (b *LocalBackend) initPeerAPIListener() { } pln := &peerAPIListener{ ps: ps, - ip: a.IP, + ip: a.IP(), ln: ln, // nil for 2nd+ on netstack lb: b, } @@ -1938,7 +1935,7 @@ func (b *LocalBackend) initPeerAPIListener() { } else { pln.port = ln.Addr().(*net.TCPAddr).Port } - pln.urlStr = "http://" + net.JoinHostPort(a.IP.String(), strconv.Itoa(pln.port)) + pln.urlStr = "http://" + net.JoinHostPort(a.IP().String(), strconv.Itoa(pln.port)) b.logf("peerapi: serving on %s", pln.urlStr) go pln.serve() b.peerAPIListeners = append(b.peerAPIListeners, pln) @@ -1989,14 +1986,14 @@ func peerRoutes(peers []wgcfg.Peer, cgnatThreshold int) (routes []netaddr.IPPref for _, aip := range peer.AllowedIPs { aip = unmapIPPrefix(aip) // Only add the Tailscale IPv6 ULA once, if we see anybody using part of it. - if aip.IP.Is6() && aip.IsSingleIP() && tsULA.Contains(aip.IP) { + if aip.IP().Is6() && aip.IsSingleIP() && tsULA.Contains(aip.IP()) { if !didULA { didULA = true routes = append(routes, tsULA) } continue } - if aip.IsSingleIP() && cgNAT.Contains(aip.IP) { + if aip.IsSingleIP() && cgNAT.Contains(aip.IP()) { cgNATIPs = append(cgNATIPs, aip) } else { routes = append(routes, aip) @@ -2063,16 +2060,13 @@ func (b *LocalBackend) routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs) *router } } - rs.Routes = append(rs.Routes, netaddr.IPPrefix{ - IP: tsaddr.TailscaleServiceIP(), - Bits: 32, - }) + rs.Routes = append(rs.Routes, netaddr.IPPrefixFrom(tsaddr.TailscaleServiceIP(), 32)) return rs } func unmapIPPrefix(ipp netaddr.IPPrefix) netaddr.IPPrefix { - return netaddr.IPPrefix{IP: ipp.IP.Unmap(), Bits: ipp.Bits} + return netaddr.IPPrefixFrom(ipp.IP().Unmap(), ipp.Bits()) } func unmapIPPrefixes(ippsList ...[]netaddr.IPPrefix) (ret []netaddr.IPPrefix) { @@ -2156,7 +2150,7 @@ func (b *LocalBackend) enterState(newState ipn.State) { case ipn.Running: var addrs []string for _, addr := range b.netMap.Addresses { - addrs = append(addrs, addr.IP.String()) + addrs = append(addrs, addr.IP().String()) } systemd.Status("Connected; %s; %s", activeLogin, strings.Join(addrs, " ")) default: @@ -2424,7 +2418,7 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) { addNode := func(n *tailcfg.Node) { for _, ipp := range n.Addresses { if ipp.IsSingleIP() { - b.nodeByAddr[ipp.IP] = n + b.nodeByAddr[ipp.IP()] = n } } } @@ -2576,9 +2570,9 @@ func peerAPIBase(nm *netmap.NetworkMap, peer *tailcfg.Node) string { continue } switch { - case a.IP.Is4(): + case a.IP().Is4(): have4 = true - case a.IP.Is6(): + case a.IP().Is6(): have6 = true } } @@ -2594,11 +2588,11 @@ func peerAPIBase(nm *netmap.NetworkMap, peer *tailcfg.Node) string { var ipp netaddr.IPPort switch { case have4 && p4 != 0: - ipp = netaddr.IPPort{IP: nodeIP(peer, netaddr.IP.Is4), Port: p4} + ipp = netaddr.IPPortFrom(nodeIP(peer, netaddr.IP.Is4), p4) case have6 && p6 != 0: - ipp = netaddr.IPPort{IP: nodeIP(peer, netaddr.IP.Is6), Port: p6} + ipp = netaddr.IPPortFrom(nodeIP(peer, netaddr.IP.Is6), p6) } - if ipp.IP.IsZero() { + if ipp.IP().IsZero() { return "" } return fmt.Sprintf("http://%v", ipp) @@ -2606,8 +2600,8 @@ func peerAPIBase(nm *netmap.NetworkMap, peer *tailcfg.Node) string { func nodeIP(n *tailcfg.Node, pred func(netaddr.IP) bool) netaddr.IP { for _, a := range n.Addresses { - if a.IsSingleIP() && pred(a.IP) { - return a.IP + if a.IsSingleIP() && pred(a.IP()) { + return a.IP() } } return netaddr.IP{} diff --git a/ipn/ipnlocal/local_test.go b/ipn/ipnlocal/local_test.go index b608be492..36427d6dd 100644 --- a/ipn/ipnlocal/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -171,7 +171,7 @@ func TestShrinkDefaultRoute(t *testing.T) { out: []string{ "fe80::1", "ff00::1", - tsaddr.TailscaleULARange().IP.String(), + tsaddr.TailscaleULARange().IP().String(), }, localIPFn: func(ip netaddr.IP) bool { return !inRemove(ip) && ip.Is6() }, }, diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 2343313ae..2e180afbf 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -510,7 +510,7 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
You are the owner of this node.\n") diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index 228d9f1cd..7bba916c6 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -147,7 +147,7 @@ func (s *server) getConnIdentity(c net.Conn) (ci connIdentity, err error) { if err != nil { return ci, fmt.Errorf("parsing local remote: %w", err) } - if !la.IP.IsLoopback() || !ra.IP.IsLoopback() { + if !la.IP().IsLoopback() || !ra.IP().IsLoopback() { return ci, errors.New("non-loopback connection") } tab, err := netstat.Get() diff --git a/net/dns/manager.go b/net/dns/manager.go index e59842548..d7335c584 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -211,7 +211,7 @@ func (m *Manager) compileConfig(cfg Config) (resolver.Config, OSConfig, error) { func toIPsOnly(ipps []netaddr.IPPort) (ret []netaddr.IP) { ret = make([]netaddr.IP, 0, len(ipps)) for _, ipp := range ipps { - ret = append(ret, ipp.IP) + ret = append(ret, ipp.IP()) } return ret } @@ -219,7 +219,7 @@ func toIPsOnly(ipps []netaddr.IPPort) (ret []netaddr.IP) { func toIPPorts(ips []netaddr.IP) (ret []netaddr.IPPort) { ret = make([]netaddr.IPPort, 0, len(ips)) for _, ip := range ips { - ret = append(ret, netaddr.IPPort{IP: ip, Port: 53}) + ret = append(ret, netaddr.IPPortFrom(ip, 53)) } return ret } diff --git a/net/dns/manager_test.go b/net/dns/manager_test.go index 0d49ea344..142c31691 100644 --- a/net/dns/manager_test.go +++ b/net/dns/manager_test.go @@ -368,11 +368,12 @@ func TestManager(t *testing.T) { if err := m.Set(test.in); err != nil { t.Fatalf("m.Set: %v", err) } - tr := cmp.Transformer("ipStr", func(ip netaddr.IP) string { return ip.String() }) - if diff := cmp.Diff(f.OSConfig, test.os, tr, cmpopts.EquateEmpty()); diff != "" { + trIP := cmp.Transformer("ipStr", func(ip netaddr.IP) string { return ip.String() }) + trIPPort := cmp.Transformer("ippStr", func(ipp netaddr.IPPort) string { return ipp.String() }) + if diff := cmp.Diff(f.OSConfig, test.os, trIP, trIPPort, cmpopts.EquateEmpty()); diff != "" { t.Errorf("wrong OSConfig (-got+want)\n%s", diff) } - if diff := cmp.Diff(f.ResolverConfig, test.rs, tr, cmpopts.EquateEmpty()); diff != "" { + if diff := cmp.Diff(f.ResolverConfig, test.rs, trIP, trIPPort, cmpopts.EquateEmpty()); diff != "" { t.Errorf("wrong resolver.Config (-got+want)\n%s", diff) } }) diff --git a/net/dns/resolver/tsdns_test.go b/net/dns/resolver/tsdns_test.go index 993d7411f..02ef3108b 100644 --- a/net/dns/resolver/tsdns_test.go +++ b/net/dns/resolver/tsdns_test.go @@ -433,8 +433,8 @@ func TestDelegateCollision(t *testing.T) { qtype dns.Type addr netaddr.IPPort }{ - {"test.site.", dns.TypeA, netaddr.IPPort{IP: netaddr.IPv4(1, 1, 1, 1), Port: 1001}}, - {"test.site.", dns.TypeAAAA, netaddr.IPPort{IP: netaddr.IPv4(1, 1, 1, 1), Port: 1002}}, + {"test.site.", dns.TypeA, netaddr.IPPortFrom(netaddr.IPv4(1, 1, 1, 1), 1001)}, + {"test.site.", dns.TypeAAAA, netaddr.IPPortFrom(netaddr.IPv4(1, 1, 1, 1), 1002)}, } // packets will have the same dns txid. diff --git a/net/interfaces/interfaces.go b/net/interfaces/interfaces.go index 9b15604f1..555d5f6e3 100644 --- a/net/interfaces/interfaces.go +++ b/net/interfaces/interfaces.go @@ -195,7 +195,7 @@ func ForeachInterface(fn func(Interface, []netaddr.IPPrefix)) error { } } sort.Slice(pfxs, func(i, j int) bool { - return pfxs[i].IP.Less(pfxs[j].IP) + return pfxs[i].IP().Less(pfxs[j].IP()) }) fn(Interface{iface}, pfxs) } @@ -264,7 +264,7 @@ func (s *State) String() string { fmt.Fprintf(&sb, "%s:[", ifName) needSpace := false for _, pfx := range s.InterfaceIPs[ifName] { - if !isInterestingIP(pfx.IP) { + if !isInterestingIP(pfx.IP()) { continue } if needSpace { @@ -367,7 +367,7 @@ func (s *State) AnyInterfaceUp() bool { func hasTailscaleIP(pfxs []netaddr.IPPrefix) bool { for _, pfx := range pfxs { - if tsaddr.IsTailscaleIP(pfx.IP) { + if tsaddr.IsTailscaleIP(pfx.IP()) { return true } } @@ -407,11 +407,11 @@ func GetState() (*State, error) { return } for _, pfx := range pfxs { - if pfx.IP.IsLoopback() || pfx.IP.IsLinkLocalUnicast() { + if pfx.IP().IsLoopback() || pfx.IP().IsLinkLocalUnicast() { continue } - s.HaveV6Global = s.HaveV6Global || isGlobalV6(pfx.IP) - s.HaveV4 = s.HaveV4 || pfx.IP.Is4() + s.HaveV6Global = s.HaveV6Global || isGlobalV6(pfx.IP()) + s.HaveV4 = s.HaveV4 || pfx.IP().Is4() } }); err != nil { return nil, err @@ -447,7 +447,7 @@ func HTTPOfListener(ln net.Listener) string { var goodIP string var privateIP string ForeachInterfaceAddress(func(i Interface, pfx netaddr.IPPrefix) { - ip := pfx.IP + ip := pfx.IP() if isPrivateIP(ip) { if privateIP == "" { privateIP = ip.String() @@ -484,7 +484,7 @@ func LikelyHomeRouterIP() (gateway, myIP netaddr.IP, ok bool) { return } ForeachInterfaceAddress(func(i Interface, pfx netaddr.IPPrefix) { - ip := pfx.IP + ip := pfx.IP() if !i.IsUp() || ip.IsZero() || !myIP.IsZero() { return } @@ -528,7 +528,7 @@ func mustCIDR(s string) netaddr.IPPrefix { // isInterestingIP. func anyInterestingIP(pfxs []netaddr.IPPrefix) bool { for _, pfx := range pfxs { - if isInterestingIP(pfx.IP) { + if isInterestingIP(pfx.IP()) { return true } } diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index 097b58704..84ecd79bc 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -625,7 +625,7 @@ func (rs *reportState) stopTimers() { func (rs *reportState) addNodeLatency(node *tailcfg.DERPNode, ipp netaddr.IPPort, d time.Duration) { var ipPortStr string if ipp != (netaddr.IPPort{}) { - ipPortStr = net.JoinHostPort(ipp.IP.String(), fmt.Sprint(ipp.Port)) + ipPortStr = net.JoinHostPort(ipp.IP().String(), fmt.Sprint(ipp.Port())) } rs.mu.Lock() @@ -650,13 +650,13 @@ func (rs *reportState) addNodeLatency(node *tailcfg.DERPNode, ipp netaddr.IPPort } switch { - case ipp.IP.Is6(): + case ipp.IP().Is6(): updateLatency(ret.RegionV6Latency, node.RegionID, d) ret.IPv6 = true ret.GlobalV6 = ipPortStr // TODO: track MappingVariesByDestIP for IPv6 // too? Would be sad if so, but who knows. - case ipp.IP.Is4(): + case ipp.IP().Is4(): updateLatency(ret.RegionV4Latency, node.RegionID, d) ret.IPv4 = true if rs.gotEP4 == "" { @@ -1172,7 +1172,7 @@ func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeP if proto == probeIPv6 && ip.Is4() { return nil } - return netaddr.IPPort{IP: ip, Port: uint16(port)}.UDPAddr() + return netaddr.IPPortFrom(ip, uint16(port)).UDPAddr() } switch proto { @@ -1182,7 +1182,7 @@ func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeP if !ip.Is4() { return nil } - return netaddr.IPPort{IP: ip, Port: uint16(port)}.UDPAddr() + return netaddr.IPPortFrom(ip, uint16(port)).UDPAddr() } case probeIPv6: if n.IPv6 != "" { @@ -1190,7 +1190,7 @@ func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeP if !ip.Is6() { return nil } - return netaddr.IPPort{IP: ip, Port: uint16(port)}.UDPAddr() + return netaddr.IPPortFrom(ip, uint16(port)).UDPAddr() } default: return nil diff --git a/net/netstat/netstat_windows.go b/net/netstat/netstat_windows.go index e5ff8186f..a3b2d7673 100644 --- a/net/netstat/netstat_windows.go +++ b/net/netstat/netstat_windows.go @@ -157,10 +157,9 @@ func ipport4(addr uint32, port uint16) netaddr.IPPort { if !endian.Big { addr = bits.ReverseBytes32(addr) } - return netaddr.IPPort{ - IP: netaddr.IPv4(byte(addr>>24), byte(addr>>16), byte(addr>>8), byte(addr)), - Port: port, - } + return netaddr.IPPortFrom( + netaddr.IPv4(byte(addr>>24), byte(addr>>16), byte(addr>>8), byte(addr)), + port) } func ipport6(addr [16]byte, scope uint32, port uint16) netaddr.IPPort { @@ -169,10 +168,7 @@ func ipport6(addr [16]byte, scope uint32, port uint16) netaddr.IPPort { // TODO: something better here? ip = ip.WithZone(fmt.Sprint(scope)) } - return netaddr.IPPort{ - IP: ip, - Port: port, - } + return netaddr.IPPortFrom(ip, port) } func port(v *uint32) uint16 { diff --git a/net/packet/packet.go b/net/packet/packet.go index 05c4a382f..7bb31aa5f 100644 --- a/net/packet/packet.go +++ b/net/packet/packet.go @@ -76,8 +76,8 @@ func (p *Parsed) String() string { // // TODO: make netaddr more efficient in this area, and retire this func. func writeIPPort(sb *strbuilder.Builder, ipp netaddr.IPPort) { - if ipp.IP.Is4() { - raw := ipp.IP.As4() + if ipp.IP().Is4() { + raw := ipp.IP().As4() sb.WriteUint(uint64(raw[0])) sb.WriteByte('.') sb.WriteUint(uint64(raw[1])) @@ -88,10 +88,10 @@ func writeIPPort(sb *strbuilder.Builder, ipp netaddr.IPPort) { sb.WriteByte(':') } else { sb.WriteByte('[') - sb.WriteString(ipp.IP.String()) // TODO: faster? + sb.WriteString(ipp.IP().String()) // TODO: faster? sb.WriteString("]:") } - sb.WriteUint(uint64(ipp.Port)) + sb.WriteUint(uint64(ipp.Port())) } // Decode extracts data from the packet in b into q. @@ -142,8 +142,8 @@ func (q *Parsed) decode4(b []byte) { } // If it's valid IPv4, then the IP addresses are valid - q.Src.IP = netaddr.IPv4(b[12], b[13], b[14], b[15]) - q.Dst.IP = netaddr.IPv4(b[16], b[17], b[18], b[19]) + q.Src = q.Src.WithIP(netaddr.IPv4(b[12], b[13], b[14], b[15])) + q.Dst = q.Dst.WithIP(netaddr.IPv4(b[16], b[17], b[18], b[19])) q.subofs = int((b[0] & 0x0F) << 2) if q.subofs > q.length { @@ -185,8 +185,8 @@ func (q *Parsed) decode4(b []byte) { q.IPProto = unknown return } - q.Src.Port = 0 - q.Dst.Port = 0 + q.Src = q.Src.WithPort(0) + q.Dst = q.Dst.WithPort(0) q.dataofs = q.subofs + icmp4HeaderLength return case ipproto.IGMP: @@ -198,8 +198,8 @@ func (q *Parsed) decode4(b []byte) { q.IPProto = unknown return } - q.Src.Port = binary.BigEndian.Uint16(sub[0:2]) - q.Dst.Port = binary.BigEndian.Uint16(sub[2:4]) + q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) + q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) q.TCPFlags = TCPFlag(sub[13]) & 0x3F headerLength := (sub[12] & 0xF0) >> 2 q.dataofs = q.subofs + int(headerLength) @@ -209,8 +209,8 @@ func (q *Parsed) decode4(b []byte) { q.IPProto = unknown return } - q.Src.Port = binary.BigEndian.Uint16(sub[0:2]) - q.Dst.Port = binary.BigEndian.Uint16(sub[2:4]) + q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) + q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) q.dataofs = q.subofs + udpHeaderLength return case ipproto.SCTP: @@ -218,8 +218,8 @@ func (q *Parsed) decode4(b []byte) { q.IPProto = unknown return } - q.Src.Port = binary.BigEndian.Uint16(sub[0:2]) - q.Dst.Port = binary.BigEndian.Uint16(sub[2:4]) + q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) + q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) return case ipproto.TSMP: // Inter-tailscale messages. @@ -265,8 +265,10 @@ func (q *Parsed) decode6(b []byte) { // okay to ignore `ok` here, because IPs pulled from packets are // always well-formed stdlib IPs. - q.Src.IP, _ = netaddr.FromStdIP(net.IP(b[8:24])) - q.Dst.IP, _ = netaddr.FromStdIP(net.IP(b[24:40])) + srcIP, _ := netaddr.FromStdIP(net.IP(b[8:24])) + dstIP, _ := netaddr.FromStdIP(net.IP(b[24:40])) + q.Src = q.Src.WithIP(srcIP) + q.Dst = q.Dst.WithIP(dstIP) // We don't support any IPv6 extension headers. Don't try to // be clever. Therefore, the IP subprotocol always starts at @@ -290,16 +292,16 @@ func (q *Parsed) decode6(b []byte) { q.IPProto = unknown return } - q.Src.Port = 0 - q.Dst.Port = 0 + q.Src = q.Src.WithPort(0) + q.Dst = q.Dst.WithPort(0) q.dataofs = q.subofs + icmp6HeaderLength case ipproto.TCP: if len(sub) < tcpHeaderLength { q.IPProto = unknown return } - q.Src.Port = binary.BigEndian.Uint16(sub[0:2]) - q.Dst.Port = binary.BigEndian.Uint16(sub[2:4]) + q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) + q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) q.TCPFlags = TCPFlag(sub[13]) & 0x3F headerLength := (sub[12] & 0xF0) >> 2 q.dataofs = q.subofs + int(headerLength) @@ -309,16 +311,16 @@ func (q *Parsed) decode6(b []byte) { q.IPProto = unknown return } - q.Src.Port = binary.BigEndian.Uint16(sub[0:2]) - q.Dst.Port = binary.BigEndian.Uint16(sub[2:4]) + q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) + q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) q.dataofs = q.subofs + udpHeaderLength case ipproto.SCTP: if len(sub) < sctpHeaderLength { q.IPProto = unknown return } - q.Src.Port = binary.BigEndian.Uint16(sub[0:2]) - q.Dst.Port = binary.BigEndian.Uint16(sub[2:4]) + q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) + q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) return case ipproto.TSMP: // Inter-tailscale messages. @@ -338,8 +340,8 @@ func (q *Parsed) IP4Header() IP4Header { return IP4Header{ IPID: ipid, IPProto: q.IPProto, - Src: q.Src.IP, - Dst: q.Dst.IP, + Src: q.Src.IP(), + Dst: q.Dst.IP(), } } @@ -351,8 +353,8 @@ func (q *Parsed) IP6Header() IP6Header { return IP6Header{ IPID: ipid, IPProto: q.IPProto, - Src: q.Src.IP, - Dst: q.Dst.IP, + Src: q.Src.IP(), + Dst: q.Dst.IP(), } } @@ -373,8 +375,8 @@ func (q *Parsed) UDP4Header() UDP4Header { } return UDP4Header{ IP4Header: q.IP4Header(), - SrcPort: q.Src.Port, - DstPort: q.Dst.Port, + SrcPort: q.Src.Port(), + DstPort: q.Dst.Port(), } } diff --git a/net/packet/tsmp.go b/net/packet/tsmp.go index 87475d033..7ed382976 100644 --- a/net/packet/tsmp.go +++ b/net/packet/tsmp.go @@ -143,7 +143,7 @@ func (h TailscaleRejectedHeader) Marshal(buf []byte) error { if len(buf) > maxPacketLength { return errLargePacket } - if h.Src.IP.Is4() { + if h.Src.IP().Is4() { iph := IP4Header{ IPProto: ipproto.TSMP, Src: h.IPSrc, @@ -151,7 +151,7 @@ func (h TailscaleRejectedHeader) Marshal(buf []byte) error { } iph.Marshal(buf) buf = buf[ip4HeaderLength:] - } else if h.Src.IP.Is6() { + } else if h.Src.IP().Is6() { iph := IP6Header{ IPProto: ipproto.TSMP, Src: h.IPSrc, @@ -165,8 +165,8 @@ func (h TailscaleRejectedHeader) Marshal(buf []byte) error { buf[0] = byte(TSMPTypeRejectedConn) buf[1] = byte(h.Proto) buf[2] = byte(h.Reason) - binary.BigEndian.PutUint16(buf[3:5], h.Src.Port) - binary.BigEndian.PutUint16(buf[5:7], h.Dst.Port) + binary.BigEndian.PutUint16(buf[3:5], h.Src.Port()) + binary.BigEndian.PutUint16(buf[5:7], h.Dst.Port()) if h.hasFlags() { var flags byte @@ -190,10 +190,10 @@ func (pp *Parsed) AsTailscaleRejectedHeader() (h TailscaleRejectedHeader, ok boo h = TailscaleRejectedHeader{ Proto: ipproto.Proto(p[1]), Reason: TailscaleRejectReason(p[2]), - IPSrc: pp.Src.IP, - IPDst: pp.Dst.IP, - Src: netaddr.IPPort{IP: pp.Dst.IP, Port: binary.BigEndian.Uint16(p[3:5])}, - Dst: netaddr.IPPort{IP: pp.Src.IP, Port: binary.BigEndian.Uint16(p[5:7])}, + IPSrc: pp.Src.IP(), + IPDst: pp.Dst.IP(), + Src: netaddr.IPPortFrom(pp.Dst.IP(), binary.BigEndian.Uint16(p[3:5])), + Dst: netaddr.IPPortFrom(pp.Src.IP(), binary.BigEndian.Uint16(p[5:7])), } if len(p) > 7 { flags := p[7] diff --git a/net/portmapper/portmapper.go b/net/portmapper/portmapper.go index 0bf4e3028..19a2931d6 100644 --- a/net/portmapper/portmapper.go +++ b/net/portmapper/portmapper.go @@ -84,7 +84,7 @@ type pmpMapping struct { // externalValid reports whether m.external is valid, with both its IP and Port populated. func (m *pmpMapping) externalValid() bool { - return !m.external.IP.IsZero() && m.external.Port != 0 + return !m.external.IP().IsZero() && m.external.Port() != 0 } // release does a best effort fire-and-forget release of the PMP mapping m. @@ -94,8 +94,8 @@ func (m *pmpMapping) release() { return } defer uc.Close() - pkt := buildPMPRequestMappingPacket(m.internal.Port, m.external.Port, pmpMapLifetimeDelete) - uc.WriteTo(pkt, netaddr.IPPort{IP: m.gw, Port: pmpPort}.UDPAddr()) + pkt := buildPMPRequestMappingPacket(m.internal.Port(), m.external.Port(), pmpMapLifetimeDelete) + uc.WriteTo(pkt, netaddr.IPPortFrom(m.gw, pmpPort).UDPAddr()) } // NewClient returns a new portmapping client. @@ -256,7 +256,7 @@ func (c *Client) CreateOrGetMapping(ctx context.Context) (external netaddr.IPPor localPort := c.localPort m := &pmpMapping{ gw: gw, - internal: netaddr.IPPort{IP: myIP, Port: localPort}, + internal: netaddr.IPPortFrom(myIP, localPort), } // prevPort is the port we had most previously, if any. We try @@ -271,7 +271,7 @@ func (c *Client) CreateOrGetMapping(ctx context.Context) (external netaddr.IPPor return m.external, nil } // The mapping might still be valid, so just try to renew it. - prevPort = m.external.Port + prevPort = m.external.Port() } // If we just did a Probe (e.g. via netchecker) but didn't @@ -279,7 +279,7 @@ func (c *Client) CreateOrGetMapping(ctx context.Context) (external netaddr.IPPor // again. Cuts down latency for most clients. haveRecentPMP := c.sawPMPRecentlyLocked() if haveRecentPMP { - m.external.IP = c.pmpPubIP + m.external = m.external.WithIP(c.pmpPubIP) } if c.lastProbe.After(now.Add(-5*time.Second)) && !haveRecentPMP { c.mu.Unlock() @@ -297,11 +297,11 @@ func (c *Client) CreateOrGetMapping(ctx context.Context) (external netaddr.IPPor uc.SetReadDeadline(time.Now().Add(portMapServiceTimeout)) defer closeCloserOnContextDone(ctx, uc)() - pmpAddr := netaddr.IPPort{IP: gw, Port: pmpPort} + pmpAddr := netaddr.IPPortFrom(gw, pmpPort) pmpAddru := pmpAddr.UDPAddr() // Ask for our external address if needed. - if m.external.IP.IsZero() { + if m.external.IP().IsZero() { if _, err := uc.WriteTo(pmpReqExternalAddrPacket, pmpAddru); err != nil { return netaddr.IPPort{}, err } @@ -337,10 +337,10 @@ func (c *Client) CreateOrGetMapping(ctx context.Context) (external netaddr.IPPor return netaddr.IPPort{}, NoMappingError{fmt.Errorf("PMP response Op=0x%x,Res=0x%x", pres.OpCode, pres.ResultCode)} } if pres.OpCode == pmpOpReply|pmpOpMapPublicAddr { - m.external.IP = pres.PublicAddr + m.external = m.external.WithIP(pres.PublicAddr) } if pres.OpCode == pmpOpReply|pmpOpMapUDP { - m.external.Port = pres.ExternalPort + m.external = m.external.WithPort(pres.ExternalPort) d := time.Duration(pres.MappingValidSeconds) * time.Second d /= 2 // renew in half the time m.useUntil = time.Now().Add(d) @@ -468,9 +468,9 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) { defer cancel() defer closeCloserOnContextDone(ctx, uc)() - pcpAddr := netaddr.IPPort{IP: gw, Port: pcpPort}.UDPAddr() - pmpAddr := netaddr.IPPort{IP: gw, Port: pmpPort}.UDPAddr() - upnpAddr := netaddr.IPPort{IP: gw, Port: upnpPort}.UDPAddr() + pcpAddr := netaddr.IPPortFrom(gw, pcpPort).UDPAddr() + pmpAddr := netaddr.IPPortFrom(gw, pmpPort).UDPAddr() + upnpAddr := netaddr.IPPortFrom(gw, upnpPort).UDPAddr() // Don't send probes to services that we recently learned (for // the same gw/myIP) are available. See diff --git a/net/tsaddr/tsaddr.go b/net/tsaddr/tsaddr.go index ea75470a8..adb73c607 100644 --- a/net/tsaddr/tsaddr.go +++ b/net/tsaddr/tsaddr.go @@ -92,7 +92,7 @@ func TailscaleEphemeral6Range() netaddr.IPPrefix { // Currently used to work around a Windows limitation when programming // IPv6 routes in corner cases. func Tailscale4To6Placeholder() netaddr.IP { - return Tailscale4To6Range().IP + return Tailscale4To6Range().IP() } // Tailscale4To6 returns a Tailscale IPv6 address that maps 1:1 to the @@ -102,7 +102,7 @@ func Tailscale4To6(ipv4 netaddr.IP) netaddr.IP { if !ipv4.Is4() || !IsTailscaleIP(ipv4) { return netaddr.IP{} } - ret := Tailscale4To6Range().IP.As16() + ret := Tailscale4To6Range().IP().As16() v4 := ipv4.As4() copy(ret[13:], v4[1:]) return netaddr.IPFrom16(ret) @@ -172,16 +172,16 @@ func NewContainsIPFunc(addrs []netaddr.IPPrefix) func(ip netaddr.IP) bool { // Fast paths for 1 and 2 IPs: if len(addrs) == 1 { a := addrs[0] - return func(ip netaddr.IP) bool { return ip == a.IP } + return func(ip netaddr.IP) bool { return ip == a.IP() } } if len(addrs) == 2 { a, b := addrs[0], addrs[1] - return func(ip netaddr.IP) bool { return ip == a.IP || ip == b.IP } + return func(ip netaddr.IP) bool { return ip == a.IP() || ip == b.IP() } } // General case: m := map[netaddr.IP]bool{} for _, a := range addrs { - m[a.IP] = true + m[a.IP()] = true } return func(ip netaddr.IP) bool { return m[ip] } } diff --git a/net/tstun/wrap.go b/net/tstun/wrap.go index 1dbe30a1c..9ba726e71 100644 --- a/net/tstun/wrap.go +++ b/net/tstun/wrap.go @@ -352,7 +352,7 @@ func (t *Wrapper) Read(buf []byte, offset int) (int, error) { p.Decode(buf[offset : offset+n]) if m, ok := t.destIPActivity.Load().(map[netaddr.IP]func()); ok { - if fn := m[p.Dst.IP]; fn != nil { + if fn := m[p.Dst.IP()]; fn != nil { fn() } } @@ -412,7 +412,7 @@ func (t *Wrapper) filterIn(buf []byte) filter.Response { p.IPProto == ipproto.TCP && p.TCPFlags&packet.TCPSyn != 0 && t.PeerAPIPort != nil { - if port, ok := t.PeerAPIPort(p.Dst.IP); ok && port == p.Dst.Port { + if port, ok := t.PeerAPIPort(p.Dst.IP()); ok && port == p.Dst.Port() { outcome = filter.Accept } } @@ -425,8 +425,8 @@ func (t *Wrapper) filterIn(buf []byte) filter.Response { // can show them a rejection history with reasons. if p.IPVersion == 4 && p.IPProto == ipproto.TCP && p.TCPFlags&packet.TCPSyn != 0 && !t.disableTSMPRejected { rj := packet.TailscaleRejectedHeader{ - IPSrc: p.Dst.IP, - IPDst: p.Src.IP, + IPSrc: p.Dst.IP(), + IPDst: p.Src.IP(), Src: p.Src, Dst: p.Dst, Proto: p.IPProto, @@ -536,7 +536,7 @@ func (t *Wrapper) injectOutboundPong(pp *packet.Parsed, req packet.TSMPPingReque Data: req.Data, } if t.PeerAPIPort != nil { - pong.PeerAPIPort, _ = t.PeerAPIPort(pp.Dst.IP) + pong.PeerAPIPort, _ = t.PeerAPIPort(pp.Dst.IP()) } switch pp.IPVersion { case 4: diff --git a/net/tstun/wrap_test.go b/net/tstun/wrap_test.go index c6ce0590d..e9a030a34 100644 --- a/net/tstun/wrap_test.go +++ b/net/tstun/wrap_test.go @@ -82,7 +82,7 @@ func nets(nets ...string) (ret []netaddr.IPPrefix) { if ip.Is6() { bits = 128 } - ret = append(ret, netaddr.IPPrefix{IP: ip, Bits: bits}) + ret = append(ret, netaddr.IPPrefixFrom(ip, bits)) } else { pfx, err := netaddr.ParseIPPrefix(s) if err != nil { diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 4f8829a29..ccf29a94e 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -70,7 +70,7 @@ func (s *Server) WhoIs(addr string) (w *apitype.WhoIsResponse, ok bool) { if err != nil { return nil, false } - ipp.IP = ip + ipp = ipp.WithIP(ip) } n, up, ok := s.lb.WhoIs(ipp) if !ok { diff --git a/tstest/integration/testcontrol/testcontrol.go b/tstest/integration/testcontrol/testcontrol.go index 1771bf65a..0b37b5a95 100644 --- a/tstest/integration/testcontrol/testcontrol.go +++ b/tstest/integration/testcontrol/testcontrol.go @@ -650,7 +650,7 @@ func keepClientEndpoint(ep string) bool { // the incoming JSON response. return false } - ip := ipp.IP + ip := ipp.IP() if ip.Zone() != "" { return false } diff --git a/tstest/natlab/firewall.go b/tstest/natlab/firewall.go index 06af2663e..7f94cf66e 100644 --- a/tstest/natlab/firewall.go +++ b/tstest/natlab/firewall.go @@ -52,7 +52,7 @@ func (s FirewallType) key(src, dst netaddr.IPPort) fwKey { switch s { case EndpointIndependentFirewall: case AddressDependentFirewall: - k.dst.IP = dst.IP + k.dst = k.dst.WithIP(dst.IP()) case AddressAndPortDependentFirewall: k.dst = dst default: diff --git a/tstest/natlab/nat.go b/tstest/natlab/nat.go index a4fbb9ee1..85c88e894 100644 --- a/tstest/natlab/nat.go +++ b/tstest/natlab/nat.go @@ -62,7 +62,7 @@ func (t NATType) key(src, dst netaddr.IPPort) natKey { switch t { case EndpointIndependentNAT: case AddressDependentNAT: - k.dst.IP = dst.IP + k.dst = k.dst.WithIP(dst.IP()) case AddressAndPortDependentNAT: k.dst = dst default: @@ -171,7 +171,7 @@ func (n *SNAT44) HandleIn(p *Packet, iif *Interface) *Packet { func (n *SNAT44) HandleForward(p *Packet, iif, oif *Interface) *Packet { switch { case oif == n.ExternalInterface: - if p.Src.IP == oif.V4() { + if p.Src.IP() == oif.V4() { // Packet already NATed and is just retraversing Forward, // don't touch it again. return p @@ -237,10 +237,7 @@ func (n *SNAT44) allocateMappedPort() (net.PacketConn, netaddr.IPPort) { if err != nil { panic(fmt.Sprintf("ran out of NAT ports: %v", err)) } - addr := netaddr.IPPort{ - IP: ip, - Port: uint16(pc.LocalAddr().(*net.UDPAddr).Port), - } + addr := netaddr.IPPortFrom(ip, uint16(pc.LocalAddr().(*net.UDPAddr).Port)) return pc, addr } diff --git a/tstest/natlab/natlab.go b/tstest/natlab/natlab.go index 2d3f3ae70..d818f98e1 100644 --- a/tstest/natlab/natlab.go +++ b/tstest/natlab/natlab.go @@ -138,7 +138,7 @@ func (n *Network) allocIPv4(iface *Interface) netaddr.IP { return netaddr.IP{} } if n.lastV4.IsZero() { - n.lastV4 = n.Prefix4.IP + n.lastV4 = n.Prefix4.IP() } a := n.lastV4.As16() addOne(&a, 15) @@ -157,7 +157,7 @@ func (n *Network) allocIPv6(iface *Interface) netaddr.IP { return netaddr.IP{} } if n.lastV6.IsZero() { - n.lastV6 = n.Prefix6.IP + n.lastV6 = n.Prefix6.IP() } a := n.lastV6.As16() addOne(&a, 15) @@ -183,15 +183,15 @@ func (n *Network) write(p *Packet) (num int, err error) { n.mu.Lock() defer n.mu.Unlock() - iface, ok := n.machine[p.Dst.IP] + iface, ok := n.machine[p.Dst.IP()] if !ok { // If the destination is within the network's authoritative // range, no route to host. - if p.Dst.IP.Is4() && n.Prefix4.Contains(p.Dst.IP) { + if p.Dst.IP().Is4() && n.Prefix4.Contains(p.Dst.IP()) { p.Trace("no route to %v", p.Dst.IP) return len(p.Payload), nil } - if p.Dst.IP.Is6() && n.Prefix6.Contains(p.Dst.IP) { + if p.Dst.IP().Is6() && n.Prefix6.Contains(p.Dst.IP()) { p.Trace("no route to %v", p.Dst.IP) return len(p.Payload), nil } @@ -363,7 +363,7 @@ func (m *Machine) isLocalIP(ip netaddr.IP) bool { func (m *Machine) deliverIncomingPacket(p *Packet, iface *Interface) { p.setLocator("mach=%s if=%s", m.Name, iface.name) - if m.isLocalIP(p.Dst.IP) { + if m.isLocalIP(p.Dst.IP()) { m.deliverLocalPacket(p, iface) } else { m.forwardPacket(p, iface) @@ -391,13 +391,13 @@ func (m *Machine) deliverLocalPacket(p *Packet, iface *Interface) { defer m.mu.Unlock() conns := m.conns4 - if p.Dst.IP.Is6() { + if p.Dst.IP().Is6() { conns = m.conns6 } possibleDsts := []netaddr.IPPort{ p.Dst, - netaddr.IPPort{IP: v6unspec, Port: p.Dst.Port}, - netaddr.IPPort{IP: v4unspec, Port: p.Dst.Port}, + netaddr.IPPortFrom(v6unspec, p.Dst.Port()), + netaddr.IPPortFrom(v4unspec, p.Dst.Port()), } for _, dest := range possibleDsts { c, ok := conns[dest] @@ -417,7 +417,7 @@ func (m *Machine) deliverLocalPacket(p *Packet, iface *Interface) { } func (m *Machine) forwardPacket(p *Packet, iif *Interface) { - oif, err := m.interfaceForIP(p.Dst.IP) + oif, err := m.interfaceForIP(p.Dst.IP()) if err != nil { p.Trace("%v", err) return @@ -501,7 +501,7 @@ func (m *Machine) Attach(interfaceName string, n *Network) *Interface { } } sort.Slice(m.routes, func(i, j int) bool { - return m.routes[i].prefix.Bits > m.routes[j].prefix.Bits + return m.routes[i].prefix.Bits() > m.routes[j].prefix.Bits() }) return f @@ -515,33 +515,33 @@ func (m *Machine) Attach(interfaceName string, n *Network) *Interface { func (m *Machine) writePacket(p *Packet) (n int, err error) { p.setLocator("mach=%s", m.Name) - iface, err := m.interfaceForIP(p.Dst.IP) + iface, err := m.interfaceForIP(p.Dst.IP()) if err != nil { p.Trace("%v", err) return 0, err } - origSrcIP := p.Src.IP + origSrcIP := p.Src.IP() switch { - case p.Src.IP == v4unspec: + case p.Src.IP() == v4unspec: p.Trace("assigning srcIP=%s", iface.V4()) - p.Src.IP = iface.V4() - case p.Src.IP == v6unspec: + p.Src = p.Src.WithIP(iface.V4()) + case p.Src.IP() == v6unspec: // v6unspec in Go means "any src, but match address families" - if p.Dst.IP.Is6() { + if p.Dst.IP().Is6() { p.Trace("assigning srcIP=%s", iface.V6()) - p.Src.IP = iface.V6() - } else if p.Dst.IP.Is4() { + p.Src = p.Src.WithIP(iface.V6()) + } else if p.Dst.IP().Is4() { p.Trace("assigning srcIP=%s", iface.V4()) - p.Src.IP = iface.V4() + p.Src = p.Src.WithIP(iface.V4()) } default: - if !iface.Contains(p.Src.IP) { - err := fmt.Errorf("can't send to %v with src %v on interface %v", p.Dst.IP, p.Src.IP, iface) + if !iface.Contains(p.Src.IP()) { + err := fmt.Errorf("can't send to %v with src %v on interface %v", p.Dst.IP(), p.Src.IP(), iface) p.Trace("%v", err) return 0, err } } - if p.Src.IP.IsZero() { + if p.Src.IP().IsZero() { err := fmt.Errorf("no matching address for address family for %v", origSrcIP) p.Trace("%v", err) return 0, err @@ -602,12 +602,12 @@ func (m *Machine) pickEphemPort() (port uint16, err error) { func (m *Machine) portInUseLocked(port uint16) bool { for ipp := range m.conns4 { - if ipp.Port == port { + if ipp.Port() == port { return true } } for ipp := range m.conns6 { - if ipp.Port == port { + if ipp.Port() == port { return true } } @@ -617,7 +617,7 @@ func (m *Machine) portInUseLocked(port uint16) bool { func (m *Machine) registerConn4(c *conn) error { m.mu.Lock() defer m.mu.Unlock() - if c.ipp.IP.Is6() && c.ipp.IP != v6unspec { + if c.ipp.IP().Is6() && c.ipp.IP() != v6unspec { return fmt.Errorf("registerConn4 got IPv6 %s", c.ipp) } return registerConn(&m.conns4, c) @@ -632,7 +632,7 @@ func (m *Machine) unregisterConn4(c *conn) { func (m *Machine) registerConn6(c *conn) error { m.mu.Lock() defer m.mu.Unlock() - if c.ipp.IP.Is4() { + if c.ipp.IP().Is4() { return fmt.Errorf("registerConn6 got IPv4 %s", c.ipp) } return registerConn(&m.conns6, c) @@ -707,7 +707,7 @@ func (m *Machine) ListenPacket(ctx context.Context, network, address string) (ne return nil, nil } } - ipp := netaddr.IPPort{IP: ip, Port: port} + ipp := netaddr.IPPortFrom(ip, port) c := &conn{ m: m, diff --git a/tstest/natlab/natlab_test.go b/tstest/natlab/natlab_test.go index 1119e804d..e7f8b6e70 100644 --- a/tstest/natlab/natlab_test.go +++ b/tstest/natlab/natlab_test.go @@ -49,8 +49,8 @@ func TestSendPacket(t *testing.T) { ifFoo := foo.Attach("eth0", internet) ifBar := bar.Attach("enp0s1", internet) - fooAddr := netaddr.IPPort{IP: ifFoo.V4(), Port: 123} - barAddr := netaddr.IPPort{IP: ifBar.V4(), Port: 456} + fooAddr := netaddr.IPPortFrom(ifFoo.V4(), 123) + barAddr := netaddr.IPPortFrom(ifBar.V4(), 456) ctx := context.Background() fooPC, err := foo.ListenPacket(ctx, "udp4", fooAddr.String()) @@ -111,10 +111,10 @@ func TestMultiNetwork(t *testing.T) { t.Fatal(err) } - clientAddr := netaddr.IPPort{IP: ifClient.V4(), Port: 123} - natLANAddr := netaddr.IPPort{IP: ifNATLAN.V4(), Port: 456} - natWANAddr := netaddr.IPPort{IP: ifNATWAN.V4(), Port: 456} - serverAddr := netaddr.IPPort{IP: ifServer.V4(), Port: 789} + clientAddr := netaddr.IPPortFrom(ifClient.V4(), 123) + natLANAddr := netaddr.IPPortFrom(ifNATLAN.V4(), 456) + natWANAddr := netaddr.IPPortFrom(ifNATWAN.V4(), 456) + serverAddr := netaddr.IPPortFrom(ifServer.V4(), 789) const msg1, msg2 = "hello", "world" if _, err := natPC.WriteTo([]byte(msg1), clientAddr.UDPAddr()); err != nil { @@ -154,8 +154,8 @@ type trivialNAT struct { } func (n *trivialNAT) HandleIn(p *Packet, iface *Interface) *Packet { - if iface == n.wanIf && p.Dst.IP == n.wanIf.V4() { - p.Dst.IP = n.clientIP + if iface == n.wanIf && p.Dst.IP() == n.wanIf.V4() { + p.Dst = p.Dst.WithIP(n.clientIP) } return p } @@ -167,13 +167,13 @@ func (n trivialNAT) HandleOut(p *Packet, iface *Interface) *Packet { func (n *trivialNAT) HandleForward(p *Packet, iif, oif *Interface) *Packet { // Outbound from LAN -> apply NAT, continue if iif == n.lanIf && oif == n.wanIf { - if p.Src.IP == n.clientIP { - p.Src.IP = n.wanIf.V4() + if p.Src.IP() == n.clientIP { + p.Src = p.Src.WithIP(n.wanIf.V4()) } return p } // Return traffic to LAN, allow if right dst. - if iif == n.wanIf && oif == n.lanIf && p.Dst.IP == n.clientIP { + if iif == n.wanIf && oif == n.lanIf && p.Dst.IP() == n.clientIP { return p } // Else drop. @@ -216,7 +216,7 @@ func TestPacketHandler(t *testing.T) { } const msg = "some message" - serverAddr := netaddr.IPPort{IP: ifServer.V4(), Port: 456} + serverAddr := netaddr.IPPortFrom(ifServer.V4(), 456) if _, err := clientPC.WriteTo([]byte(msg), serverAddr.UDPAddr()); err != nil { t.Fatal(err) } @@ -230,7 +230,7 @@ func TestPacketHandler(t *testing.T) { if string(buf) != msg { t.Errorf("read %q; want %q", buf, msg) } - mappedAddr := netaddr.IPPort{IP: ifNATWAN.V4(), Port: 123} + mappedAddr := netaddr.IPPortFrom(ifNATWAN.V4(), 123) if addr.String() != mappedAddr.String() { t.Errorf("addr = %q; want %q", addr, mappedAddr) } diff --git a/types/netmap/netmap_test.go b/types/netmap/netmap_test.go index 977a64cf0..628cd68cb 100644 --- a/types/netmap/netmap_test.go +++ b/types/netmap/netmap_test.go @@ -250,7 +250,7 @@ func TestConciseDiffFrom(t *testing.T) { DERP: "127.3.3.40:2", Endpoints: []string{"192.168.0.100:41641", "1.1.1.1:41641"}, DiscoKey: testDiscoKey("f00f00f00f"), - AllowedIPs: []netaddr.IPPrefix{{IP: netaddr.IPv4(100, 102, 103, 104), Bits: 32}}, + AllowedIPs: []netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.IPv4(100, 102, 103, 104), 32)}, }, }, }, @@ -263,7 +263,7 @@ func TestConciseDiffFrom(t *testing.T) { DERP: "127.3.3.40:2", Endpoints: []string{"192.168.0.100:41641", "1.1.1.1:41641"}, DiscoKey: testDiscoKey("ba4ba4ba4b"), - AllowedIPs: []netaddr.IPPrefix{{IP: netaddr.IPv4(100, 102, 103, 104), Bits: 32}}, + AllowedIPs: []netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.IPv4(100, 102, 103, 104), 32)}, }, }, }, diff --git a/wf/firewall.go b/wf/firewall.go index 0eda66e7b..2fc7a3d5b 100644 --- a/wf/firewall.go +++ b/wf/firewall.go @@ -218,7 +218,7 @@ func (f *Firewall) UpdatePermittedRoutes(newRoutes []netaddr.IPPrefix) error { }, } var p protocol - if r.IP.Is4() { + if r.IP().Is4() { p = protocolV4 } else { p = protocolV6 diff --git a/wgengine/bench/bench.go b/wgengine/bench/bench.go index 311a99697..305f0a31f 100644 --- a/wgengine/bench/bench.go +++ b/wgengine/bench/bench.go @@ -87,7 +87,7 @@ func main() { } logf("initialized ok.") - traf.Start(Addr1.IP, Addr2.IP, PayloadSize+ICMPMinSize, 0) + traf.Start(Addr1.IP(), Addr2.IP(), PayloadSize+ICMPMinSize, 0) var cur, prev Snapshot var pps int64 diff --git a/wgengine/bench/bench_test.go b/wgengine/bench/bench_test.go index 253209bb6..739b3d418 100644 --- a/wgengine/bench/bench_test.go +++ b/wgengine/bench/bench_test.go @@ -78,7 +78,7 @@ func runOnce(b *testing.B, setup SetupFunc, payload int) { logf("initialized. (n=%v)", b.N) b.SetBytes(int64(payload)) - traf.Start(Addr1.IP, Addr2.IP, payload, int64(b.N)) + traf.Start(Addr1.IP(), Addr2.IP(), payload, int64(b.N)) var cur, prev Snapshot var pps int64 diff --git a/wgengine/filter/filter.go b/wgengine/filter/filter.go index 3c4964c34..789100edb 100644 --- a/wgengine/filter/filter.go +++ b/wgengine/filter/filter.go @@ -98,8 +98,8 @@ func (r Response) IsDrop() bool { // everything. Use in tests only, as it permits some kinds of spoofing // attacks to reach the OS network stack. func NewAllowAllForTest(logf logger.Logf) *Filter { - any4 := netaddr.IPPrefix{IP: netaddr.IPv4(0, 0, 0, 0), Bits: 0} - any6 := netaddr.IPPrefix{IP: netaddr.IPFrom16([16]byte{}), Bits: 0} + any4 := netaddr.IPPrefixFrom(netaddr.IPv4(0, 0, 0, 0), 0) + any6 := netaddr.IPPrefixFrom(netaddr.IPFrom16([16]byte{}), 0) ms := []Match{ { Srcs: []netaddr.IPPrefix{any4}, @@ -185,12 +185,12 @@ func matchesFamily(ms matches, keep func(netaddr.IP) bool) matches { var retm Match retm.IPProto = m.IPProto for _, src := range m.Srcs { - if keep(src.IP) { + if keep(src.IP()) { retm.Srcs = append(retm.Srcs, src) } } for _, dst := range m.Dsts { - if keep(dst.Net.IP) { + if keep(dst.Net.IP()) { retm.Dsts = append(retm.Dsts, dst) } } @@ -266,12 +266,10 @@ func (f *Filter) CheckTCP(srcIP, dstIP netaddr.IP, dstPort uint16) Response { default: panic("unreachable") } - pkt.Src.IP = srcIP - pkt.Dst.IP = dstIP + pkt.Src = netaddr.IPPortFrom(srcIP, 0) + pkt.Dst = netaddr.IPPortFrom(dstIP, dstPort) pkt.IPProto = ipproto.TCP pkt.TCPFlags = packet.TCPSyn - pkt.Src.Port = 0 - pkt.Dst.Port = dstPort return f.RunIn(pkt, 0) } @@ -321,7 +319,7 @@ func (f *Filter) runIn4(q *packet.Parsed) (r Response, why string) { // A compromised peer could try to send us packets for // destinations we didn't explicitly advertise. This check is to // prevent that. - if !f.local.Contains(q.Dst.IP) { + if !f.local.Contains(q.Dst.IP()) { return Drop, "destination not allowed" } @@ -378,7 +376,7 @@ func (f *Filter) runIn6(q *packet.Parsed) (r Response, why string) { // A compromised peer could try to send us packets for // destinations we didn't explicitly advertise. This check is to // prevent that. - if !f.local.Contains(q.Dst.IP) { + if !f.local.Contains(q.Dst.IP()) { return Drop, "destination not allowed" } @@ -480,11 +478,11 @@ func (f *Filter) pre(q *packet.Parsed, rf RunFlags, dir direction) Response { return Drop } - if q.Dst.IP.IsMulticast() { + if q.Dst.IP().IsMulticast() { f.logRateLimit(rf, q, dir, Drop, "multicast") return Drop } - if q.Dst.IP.IsLinkLocalUnicast() && q.Dst.IP != gcpDNSAddr { + if q.Dst.IP().IsLinkLocalUnicast() && q.Dst.IP() != gcpDNSAddr { f.logRateLimit(rf, q, dir, Drop, "link-local-unicast") return Drop } @@ -506,7 +504,7 @@ func (f *Filter) pre(q *packet.Parsed, rf RunFlags, dir direction) Response { // loggingAllowed reports whether p can appear in logs at all. func (f *Filter) loggingAllowed(p *packet.Parsed) bool { - return f.logIPs.Contains(p.Src.IP) && f.logIPs.Contains(p.Dst.IP) + return f.logIPs.Contains(p.Src.IP()) && f.logIPs.Contains(p.Dst.IP()) } // omitDropLogging reports whether packet p, which has already been @@ -518,5 +516,5 @@ func omitDropLogging(p *packet.Parsed, dir direction) bool { return false } - return p.Dst.IP.IsMulticast() || (p.Dst.IP.IsLinkLocalUnicast() && p.Dst.IP != gcpDNSAddr) || p.IPProto == ipproto.IGMP + return p.Dst.IP().IsMulticast() || (p.Dst.IP().IsLinkLocalUnicast() && p.Dst.IP() != gcpDNSAddr) || p.IPProto == ipproto.IGMP } diff --git a/wgengine/filter/filter_test.go b/wgengine/filter/filter_test.go index ca807a5fd..538a763d3 100644 --- a/wgengine/filter/filter_test.go +++ b/wgengine/filter/filter_test.go @@ -120,9 +120,9 @@ type InOut struct { if test.p.IPProto == ipproto.TCP { var got Response if test.p.IPVersion == 4 { - got = acl.CheckTCP(test.p.Src.IP, test.p.Dst.IP, test.p.Dst.Port) + got = acl.CheckTCP(test.p.Src.IP(), test.p.Dst.IP(), test.p.Dst.Port()) } else { - got = acl.CheckTCP(test.p.Src.IP, test.p.Dst.IP, test.p.Dst.Port) + got = acl.CheckTCP(test.p.Src.IP(), test.p.Dst.IP(), test.p.Dst.Port()) } if test.want != got { t.Errorf("#%d CheckTCP got=%v want=%v packet:%v", i, got, test.want, test.p) @@ -254,7 +254,9 @@ func TestParseIPSet(t *testing.T) { } t.Errorf("parseIPSet(%q, %v) error: %v; want error %q", tt.host, tt.bits, err, tt.wantErr) } - if diff := cmp.Diff(got, tt.want, cmp.Comparer(func(a, b netaddr.IP) bool { return a == b })); diff != "" { + compareIP := cmp.Comparer(func(a, b netaddr.IP) bool { return a == b }) + compareIPPrefix := cmp.Comparer(func(a, b netaddr.IPPrefix) bool { return a == b }) + if diff := cmp.Diff(got, tt.want, compareIP, compareIPPrefix); diff != "" { t.Errorf("parseIPSet(%q, %v) = %s; want %s", tt.host, tt.bits, got, tt.want) continue } @@ -425,10 +427,10 @@ func TestLoggingPrivacy(t *testing.T) { f.logIPs = logB.IPSet() var ( - ts4 = netaddr.IPPort{IP: tsaddr.CGNATRange().IP.Next(), Port: 1234} - internet4 = netaddr.IPPort{IP: netaddr.MustParseIP("8.8.8.8"), Port: 1234} - ts6 = netaddr.IPPort{IP: tsaddr.TailscaleULARange().IP.Next(), Port: 1234} - internet6 = netaddr.IPPort{IP: netaddr.MustParseIP("2001::1"), Port: 1234} + ts4 = netaddr.IPPortFrom(tsaddr.CGNATRange().IP().Next(), 1234) + internet4 = netaddr.IPPortFrom(netaddr.MustParseIP("8.8.8.8"), 1234) + ts6 = netaddr.IPPortFrom(tsaddr.TailscaleULARange().IP().Next(), 1234) + internet6 = netaddr.IPPortFrom(netaddr.MustParseIP("2001::1"), 1234) ) tests := []struct { @@ -545,10 +547,8 @@ func parsed(proto ipproto.Proto, src, dst string, sport, dport uint16) packet.Pa var ret packet.Parsed ret.Decode(dummyPacket) ret.IPProto = proto - ret.Src.IP = sip - ret.Src.Port = sport - ret.Dst.IP = dip - ret.Dst.Port = dport + ret.Src = netaddr.IPPortFrom(sip, sport) + ret.Dst = netaddr.IPPortFrom(dip, dport) ret.TCPFlags = packet.TCPSyn if sip.Is4() { @@ -674,7 +674,7 @@ func nets(nets ...string) (ret []netaddr.IPPrefix) { if ip.Is6() { bits = 128 } - ret = append(ret, netaddr.IPPrefix{IP: ip, Bits: bits}) + ret = append(ret, netaddr.IPPrefixFrom(ip, bits)) } else { pfx, err := netaddr.ParseIPPrefix(s) if err != nil { diff --git a/wgengine/filter/match.go b/wgengine/filter/match.go index a1b356113..74807dda7 100644 --- a/wgengine/filter/match.go +++ b/wgengine/filter/match.go @@ -85,14 +85,14 @@ func (ms matches) match(q *packet.Parsed) bool { if !protoInList(q.IPProto, m.IPProto) { continue } - if !ipInList(q.Src.IP, m.Srcs) { + if !ipInList(q.Src.IP(), m.Srcs) { continue } for _, dst := range m.Dsts { - if !dst.Net.Contains(q.Dst.IP) { + if !dst.Net.Contains(q.Dst.IP()) { continue } - if !dst.Ports.contains(q.Dst.Port) { + if !dst.Ports.contains(q.Dst.Port()) { continue } return true @@ -103,11 +103,11 @@ func (ms matches) match(q *packet.Parsed) bool { func (ms matches) matchIPsOnly(q *packet.Parsed) bool { for _, m := range ms { - if !ipInList(q.Src.IP, m.Srcs) { + if !ipInList(q.Src.IP(), m.Srcs) { continue } for _, dst := range m.Dsts { - if dst.Net.Contains(q.Dst.IP) { + if dst.Net.Contains(q.Dst.IP()) { return true } } diff --git a/wgengine/filter/tailcfg.go b/wgengine/filter/tailcfg.go index 1338a75b4..84e5328ad 100644 --- a/wgengine/filter/tailcfg.go +++ b/wgengine/filter/tailcfg.go @@ -99,8 +99,8 @@ func parseIPSet(arg string, bits *int) ([]netaddr.IPPrefix, error) { if arg == "*" { // User explicitly requested wildcard. return []netaddr.IPPrefix{ - {IP: zeroIP4, Bits: 0}, - {IP: zeroIP6, Bits: 0}, + netaddr.IPPrefixFrom(zeroIP4, 0), + netaddr.IPPrefixFrom(zeroIP6, 0), }, nil } if strings.Contains(arg, "/") { @@ -124,7 +124,7 @@ func parseIPSet(arg string, bits *int) ([]netaddr.IPPrefix, error) { if err != nil { return nil, err } - r := netaddr.IPRange{From: ip1, To: ip2} + r := netaddr.IPRangeFrom(ip1, ip2) if !r.Valid() { return nil, fmt.Errorf("invalid IP range %q", arg) } @@ -141,5 +141,5 @@ func parseIPSet(arg string, bits *int) ([]netaddr.IPPrefix, error) { } bits8 = uint8(*bits) } - return []netaddr.IPPrefix{{IP: ip, Bits: bits8}}, nil + return []netaddr.IPPrefix{netaddr.IPPrefixFrom(ip, bits8)}, nil } diff --git a/wgengine/magicsock/legacy.go b/wgengine/magicsock/legacy.go index 57b4765dd..4facdb5f5 100644 --- a/wgengine/magicsock/legacy.go +++ b/wgengine/magicsock/legacy.go @@ -62,7 +62,7 @@ func (c *Conn) createLegacyEndpointLocked(pk key.Public, addrs wgcfg.IPPortSet, // Add entries to c.addrsByUDP. for _, ipp := range a.ipPorts { - if ipp.IP == derpMagicIPAddr { + if ipp.IP() == derpMagicIPAddr { continue } c.addrsByUDP[ipp] = a @@ -70,7 +70,7 @@ func (c *Conn) createLegacyEndpointLocked(pk key.Public, addrs wgcfg.IPPortSet, // Remove previous c.addrsByUDP entries that are no longer in the new set. for _, ipp := range oldIPP { - if ipp.IP != derpMagicIPAddr && c.addrsByUDP[ipp] != a { + if ipp.IP() != derpMagicIPAddr && c.addrsByUDP[ipp] != a { delete(c.addrsByUDP, ipp) } } @@ -388,8 +388,8 @@ type addrSet struct { // derpID returns this addrSet's home DERP node, or 0 if none is found. func (as *addrSet) derpID() int { for _, ua := range as.ipPorts { - if ua.IP == derpMagicIPAddr { - return int(ua.Port) + if ua.IP() == derpMagicIPAddr { + return int(ua.Port()) } } return 0 @@ -428,7 +428,7 @@ func (a *addrSet) DstToString() string { return a.rawdst } func (a *addrSet) DstIP() net.IP { - return a.dst().IP.IPAddr().IP // TODO: add netaddr accessor to cut an alloc here? + return a.dst().IP().IPAddr().IP // TODO: add netaddr accessor to cut an alloc here? } func (a *addrSet) SrcIP() net.IP { return nil } func (a *addrSet) SrcToString() string { return "" } @@ -437,7 +437,7 @@ func (a *addrSet) ClearSrc() {} // updateDst records receipt of a packet from new. This is used to // potentially update the transmit address used for this addrSet. func (a *addrSet) updateDst(new netaddr.IPPort) error { - if new.IP == derpMagicIPAddr { + if new.IP() == derpMagicIPAddr { // Never consider DERP addresses as a viable candidate for // either curAddr or roamAddr. It's only ever a last resort // choice, never a preferred choice. @@ -539,7 +539,7 @@ func (as *addrSet) populatePeerStatus(ps *ipnstate.PeerStatus) { ps.LastWrite = as.lastSend for i, ua := range as.ipPorts { - if ua.IP == derpMagicIPAddr { + if ua.IP() == derpMagicIPAddr { continue } uaStr := ua.String() diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 4291e13d9..5383251dc 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -832,7 +832,7 @@ func (c *Conn) Ping(peer *tailcfg.Node, res *ipnstate.PingResult, cb func(*ipnst return } if len(peer.Addresses) > 0 { - res.NodeIP = peer.Addresses[0].IP.String() + res.NodeIP = peer.Addresses[0].IP().String() } res.NodeName = peer.Name // prefer DNS name if res.NodeName == "" { @@ -878,11 +878,11 @@ func (c *Conn) Ping(peer *tailcfg.Node, res *ipnstate.PingResult, cb func(*ipnst // c.mu must be held func (c *Conn) populateCLIPingResponseLocked(res *ipnstate.PingResult, latency time.Duration, ep netaddr.IPPort) { res.LatencySeconds = latency.Seconds() - if ep.IP != derpMagicIPAddr { + if ep.IP() != derpMagicIPAddr { res.Endpoint = ep.String() return } - regionID := int(ep.Port) + regionID := int(ep.Port()) res.DERPRegionID = regionID if c.derpMap != nil { if dr, ok := c.derpMap.Regions[regionID]; ok { @@ -965,7 +965,7 @@ func (c *Conn) goDerpConnect(node int) { if node == 0 { return } - go c.derpWriteChanOfAddr(netaddr.IPPort{IP: derpMagicIPAddr, Port: uint16(node)}, key.Public{}) + go c.derpWriteChanOfAddr(netaddr.IPPortFrom(derpMagicIPAddr, uint16(node)), key.Public{}) } // determineEndpoints returns the machine's endpoint addresses. It @@ -1037,7 +1037,7 @@ func (c *Conn) determineEndpoints(ctx context.Context) ([]tailcfg.Endpoint, erro ips = loopback } for _, ip := range ips { - addAddr(netaddr.IPPort{IP: ip, Port: uint16(localAddr.Port)}, tailcfg.EndpointLocal) + addAddr(netaddr.IPPortFrom(ip, uint16(localAddr.Port)), tailcfg.EndpointLocal) } } else { // Our local endpoint is bound to a particular address. @@ -1169,7 +1169,7 @@ func (c *Conn) sendUDPStd(addr *net.UDPAddr, b []byte) (sent bool, err error) { // IPv6 address when the local machine doesn't have IPv6 support // returns (false, nil); it's not an error, but nothing was sent. func (c *Conn) sendAddr(addr netaddr.IPPort, pubKey key.Public, b []byte) (sent bool, err error) { - if addr.IP != derpMagicIPAddr { + if addr.IP() != derpMagicIPAddr { return c.sendUDP(addr, b) } @@ -1211,10 +1211,10 @@ func (c *Conn) sendAddr(addr netaddr.IPPort, pubKey key.Public, b []byte) (sent // If peer is non-zero, it can be used to find an active reverse // path, without using addr. func (c *Conn) derpWriteChanOfAddr(addr netaddr.IPPort, peer key.Public) chan<- derpWriteRequest { - if addr.IP != derpMagicIPAddr { + if addr.IP() != derpMagicIPAddr { return nil } - regionID := int(addr.Port) + regionID := int(addr.Port()) if c.networkDown() { return nil @@ -1402,7 +1402,7 @@ func (c *Conn) runDerpReader(ctx context.Context, derpFakeAddr netaddr.IPPort, d } didCopy := make(chan struct{}, 1) - regionID := int(derpFakeAddr.Port) + regionID := int(derpFakeAddr.Port()) res := derpReadResult{regionID: regionID} var pkt derp.ReceivedPacket res.copyBuf = func(dst []byte) int { @@ -1676,7 +1676,7 @@ func (c *Conn) processDERPReadResult(dm derpReadResult, b []byte) (n int, ep con return 0, nil } - ipp := netaddr.IPPort{IP: derpMagicIPAddr, Port: uint16(regionID)} + ipp := netaddr.IPPortFrom(derpMagicIPAddr, uint16(regionID)) if c.handleDiscoMessage(b[:n], ipp) { return 0, nil } @@ -1922,7 +1922,7 @@ func (c *Conn) handleDiscoMessage(msg []byte, src netaddr.IPPort) (isDiscoMsg bo } de.handlePongConnLocked(dm, src) case *disco.CallMeMaybe: - if src.IP != derpMagicIPAddr { + if src.IP() != derpMagicIPAddr { // CallMeMaybe messages should only come via DERP. c.logf("[unexpected] CallMeMaybe packets should only come via DERP") return @@ -2722,7 +2722,7 @@ func (c *Conn) resetEndpointStates() { // packIPPort packs an IPPort into the form wanted by WireGuard. func packIPPort(ua netaddr.IPPort) []byte { - ip := ua.IP.Unmap() + ip := ua.IP().Unmap() a := ip.As16() ipb := a[:] if ip.Is4() { @@ -2730,8 +2730,8 @@ func packIPPort(ua netaddr.IPPort) []byte { } b := make([]byte, 0, len(ipb)+2) b = append(b, ipb...) - b = append(b, byte(ua.Port)) - b = append(b, byte(ua.Port>>8)) + b = append(b, byte(ua.Port())) + b = append(b, byte(ua.Port()>>8)) return b } @@ -2972,15 +2972,15 @@ func peerShort(k key.Public) string { } func sbPrintAddr(sb *strings.Builder, a netaddr.IPPort) { - is6 := a.IP.Is6() + is6 := a.IP().Is6() if is6 { sb.WriteByte('[') } - fmt.Fprintf(sb, "%s", a.IP) + fmt.Fprintf(sb, "%s", a.IP()) if is6 { sb.WriteByte(']') } - fmt.Fprintf(sb, ":%d", a.Port) + fmt.Fprintf(sb, ":%d", a.Port()) } func (c *Conn) derpRegionCodeOfAddrLocked(ipPort string) string { @@ -3017,15 +3017,15 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { if !addr.IsSingleIP() { continue } - sb.AddTailscaleIP(addr.IP) + sb.AddTailscaleIP(addr.IP()) // TailAddr previously only allowed for a // single Tailscale IP. For compatibility for // a couple releases starting with 1.8, keep // that field pulled out separately. - if addr.IP.Is4() { - tailAddr4 = addr.IP.String() + if addr.IP().Is4() { + tailAddr4 = addr.IP().String() } - tailscaleIPs = append(tailscaleIPs, addr.IP) + tailscaleIPs = append(tailscaleIPs, addr.IP()) } } @@ -3084,8 +3084,8 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { } func ippDebugString(ua netaddr.IPPort) string { - if ua.IP == derpMagicIPAddr { - return fmt.Sprintf("derp-%d", ua.Port) + if ua.IP() == derpMagicIPAddr { + return fmt.Sprintf("derp-%d", ua.Port()) } return ua.String() } @@ -3254,10 +3254,7 @@ func (de *discoEndpoint) initFakeUDPAddr() { addr[0] = 0xfd addr[1] = 0x00 binary.BigEndian.PutUint64(addr[2:], uint64(reflect.ValueOf(de).Pointer())) - de.fakeWGAddr = netaddr.IPPort{ - IP: netaddr.IPFrom16(addr), - Port: 12345, - } + de.fakeWGAddr = netaddr.IPPortFrom(netaddr.IPFrom16(addr), 12345) } // isFirstRecvActivityInAwhile notes that receive activity has occured for this @@ -3632,7 +3629,7 @@ func (de *discoEndpoint) handlePongConnLocked(m *disco.Pong, src netaddr.IPPort) de.mu.Lock() defer de.mu.Unlock() - isDerp := src.IP == derpMagicIPAddr + isDerp := src.IP() == derpMagicIPAddr sp, ok := de.sentPing[m.TxID] if !ok { @@ -3708,13 +3705,13 @@ func betterAddr(a, b addrLatency) bool { if a.IsZero() { return false } - if a.IP.Is6() && b.IP.Is4() { + if a.IP().Is6() && b.IP().Is4() { // Prefer IPv6 for being a bit more robust, as long as // the latencies are roughly equivalent. if a.latency/10*9 < b.latency { return true } - } else if a.IP.Is4() && b.IP.Is6() { + } else if a.IP().Is4() && b.IP().Is6() { if betterAddr(b, a) { return false } @@ -3754,7 +3751,7 @@ func (de *discoEndpoint) handleCallMeMaybe(m *disco.CallMeMaybe) { } var newEPs []netaddr.IPPort for _, ep := range m.MyNumber { - if ep.IP.Is6() && ep.IP.IsLinkLocalUnicast() { + if ep.IP().Is6() && ep.IP().IsLinkLocalUnicast() { // We send these out, but ignore them for now. // TODO: teach the ping code to ping on all interfaces // for these. diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 8545a39dc..af16db82d 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -252,13 +252,13 @@ func meshStacks(logf logger.Logf, ms []*magicStack) (cleanup func()) { nm := &netmap.NetworkMap{ PrivateKey: me.privateKey, NodeKey: tailcfg.NodeKey(me.privateKey.Public()), - Addresses: []netaddr.IPPrefix{{IP: netaddr.IPv4(1, 0, 0, byte(myIdx+1)), Bits: 32}}, + Addresses: []netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.IPv4(1, 0, 0, byte(myIdx+1)), 32)}, } for i, peer := range ms { if i == myIdx { continue } - addrs := []netaddr.IPPrefix{{IP: netaddr.IPv4(1, 0, 0, byte(i+1)), Bits: 32}} + addrs := []netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.IPv4(1, 0, 0, byte(i+1)), 32)} peer := &tailcfg.Node{ ID: tailcfg.NodeID(i + 1), Name: fmt.Sprintf("node%d", i+1), @@ -433,7 +433,7 @@ func TestPickDERPFallback(t *testing.T) { // But move if peers are elsewhere. const otherNode = 789 c.addrsByKey = map[key.Public]*addrSet{ - {1}: {ipPorts: []netaddr.IPPort{{IP: derpMagicIPAddr, Port: otherNode}}}, + {1}: {ipPorts: []netaddr.IPPort{netaddr.IPPortFrom(derpMagicIPAddr, otherNode)}}, } if got := c.pickDERPFallback(); got != otherNode { t.Errorf("didn't join peers: got %v; want %v", got, someNode) @@ -887,8 +887,8 @@ func testTwoDevicePing(t *testing.T, d *devices) { defer m2.Close() addrs := []netaddr.IPPort{ - {IP: d.m1IP, Port: m1.conn.LocalPort()}, - {IP: d.m2IP, Port: m2.conn.LocalPort()}, + netaddr.IPPortFrom(d.m1IP, m1.conn.LocalPort()), + netaddr.IPPortFrom(d.m2IP, m2.conn.LocalPort()), } cfgs := makeConfigs(t, addrs) @@ -1555,7 +1555,7 @@ func TestEndpointSetsEqual(t *testing.T) { s := func(ports ...uint16) (ret []tailcfg.Endpoint) { for _, port := range ports { ret = append(ret, tailcfg.Endpoint{ - Addr: netaddr.IPPort{Port: port}, + Addr: netaddr.IPPortFrom(netaddr.IP{}, port), }) } return diff --git a/wgengine/monitor/monitor_linux.go b/wgengine/monitor/monitor_linux.go index 9f60d7703..e1c573be7 100644 --- a/wgengine/monitor/monitor_linux.go +++ b/wgengine/monitor/monitor_linux.go @@ -130,11 +130,11 @@ func netaddrIP(std net.IP) netaddr.IP { func netaddrIPPrefix(std net.IP, bits uint8) netaddr.IPPrefix { ip, _ := netaddr.FromStdIP(std) - return netaddr.IPPrefix{IP: ip, Bits: bits} + return netaddr.IPPrefixFrom(ip, bits) } func condNetAddrPrefix(ipp netaddr.IPPrefix) string { - if ipp.IP.IsZero() { + if ipp.IP().IsZero() { return "" } return ipp.String() @@ -157,7 +157,7 @@ type newRouteMessage struct { const tsTable = 52 func (m *newRouteMessage) ignore() bool { - return m.Table == tsTable || tsaddr.IsTailscaleIP(m.Dst.IP) + return m.Table == tsTable || tsaddr.IsTailscaleIP(m.Dst.IP()) } // newAddrMessage is a message for a new address being added. diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go index 045e0d6d6..f587755ff 100644 --- a/wgengine/netstack/netstack.go +++ b/wgengine/netstack/netstack.go @@ -179,7 +179,7 @@ func DNSMapFromNetworkMap(nm *netmap.NetworkMap) DNSMap { suffix := nm.MagicDNSSuffix() if nm.Name != "" && len(nm.Addresses) > 0 { - ip := nm.Addresses[0].IP + ip := nm.Addresses[0].IP() ret[strings.TrimRight(nm.Name, ".")] = ip if dnsname.HasSuffix(nm.Name, suffix) { ret[dnsname.TrimSuffix(nm.Name, suffix)] = ip @@ -187,7 +187,7 @@ func DNSMapFromNetworkMap(nm *netmap.NetworkMap) DNSMap { } for _, p := range nm.Peers { if p.Name != "" && len(p.Addresses) > 0 { - ip := p.Addresses[0].IP + ip := p.Addresses[0].IP() ret[strings.TrimRight(p.Name, ".")] = ip if dnsname.HasSuffix(p.Name, suffix) { ret[dnsname.TrimSuffix(p.Name, suffix)] = ip @@ -227,8 +227,8 @@ func (ns *Impl) removeSubnetAddress(ip netaddr.IP) { func ipPrefixToAddressWithPrefix(ipp netaddr.IPPrefix) tcpip.AddressWithPrefix { return tcpip.AddressWithPrefix{ - Address: tcpip.Address(ipp.IP.IPAddr().IP), - PrefixLen: int(ipp.Bits), + Address: tcpip.Address(ipp.IP().IPAddr().IP), + PrefixLen: int(ipp.Bits()), } } @@ -322,7 +322,7 @@ func (m DNSMap) Resolve(ctx context.Context, addr string) (netaddr.IPPort, error // Try MagicDNS first, else otherwise a real DNS lookup. ip := m[host] if !ip.IsZero() { - return netaddr.IPPort{IP: ip, Port: uint16(port16)}, nil + return netaddr.IPPortFrom(ip, uint16(port16)), nil } // No MagicDNS name so try real DNS. @@ -335,7 +335,7 @@ func (m DNSMap) Resolve(ctx context.Context, addr string) (netaddr.IPPort, error return netaddr.IPPort{}, fmt.Errorf("DNS lookup returned no results for %q", host) } ip, _ = netaddr.FromStdIP(ips[0]) - return netaddr.IPPort{IP: ip, Port: uint16(port16)}, nil + return netaddr.IPPortFrom(ip, uint16(port16)), nil } func (ns *Impl) DialContextTCP(ctx context.Context, addr string) (*gonet.TCPConn, error) { @@ -349,11 +349,11 @@ func (ns *Impl) DialContextTCP(ctx context.Context, addr string) (*gonet.TCPConn } remoteAddress := tcpip.FullAddress{ NIC: nicID, - Addr: tcpip.Address(remoteIPPort.IP.IPAddr().IP), - Port: remoteIPPort.Port, + Addr: tcpip.Address(remoteIPPort.IP().IPAddr().IP), + Port: remoteIPPort.Port(), } var ipType tcpip.NetworkProtocolNumber - if remoteIPPort.IP.Is4() { + if remoteIPPort.IP().Is4() { ipType = ipv4.ProtocolNumber } else { ipType = ipv6.ProtocolNumber @@ -395,7 +395,7 @@ func (ns *Impl) isLocalIP(ip netaddr.IP) bool { } func (ns *Impl) injectInbound(p *packet.Parsed, t *tstun.Wrapper) filter.Response { - if ns.onlySubnets && ns.isLocalIP(p.Dst.IP) { + if ns.onlySubnets && ns.isLocalIP(p.Dst.IP()) { // In hybrid ("only subnets") mode, bail out early if // the traffic is destined for an actual Tailscale // address. The real host OS interface will handle it. diff --git a/wgengine/pendopen.go b/wgengine/pendopen.go index df98d670a..fb87c16e5 100644 --- a/wgengine/pendopen.go +++ b/wgengine/pendopen.go @@ -115,8 +115,8 @@ func (e *userspaceEngine) trackOpenPostFilterOut(pp *packet.Parsed, t *tstun.Wra // Don't start timers tracking those. They won't succeed anyway. Avoids log spam // like: // open-conn-track: timeout opening (100.115.73.60:52501 => 17.125.252.5:443); no associated peer node - if runtime.GOOS == "ios" && flow.Dst.Port == 443 && !tsaddr.IsTailscaleIP(flow.Dst.IP) { - if _, err := e.peerForIP(flow.Dst.IP); err != nil { + if runtime.GOOS == "ios" && flow.Dst.Port() == 443 && !tsaddr.IsTailscaleIP(flow.Dst.IP()) { + if _, err := e.peerForIP(flow.Dst.IP()); err != nil { return } } @@ -156,7 +156,7 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) { } // Diagnose why it might've timed out. - n, err := e.peerForIP(flow.Dst.IP) + n, err := e.peerForIP(flow.Dst.IP()) if err != nil { e.logf("open-conn-track: timeout opening %v; peerForIP: %v", flow, err) return @@ -193,7 +193,7 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) { if ps == nil { onlyZeroRoute := true // whether peerForIP returned n only because its /0 route matched for _, r := range n.AllowedIPs { - if r.Bits != 0 && r.Contains(flow.Dst.IP) { + if r.Bits() != 0 && r.Contains(flow.Dst.IP()) { onlyZeroRoute = false break } diff --git a/wgengine/router/ifconfig_windows.go b/wgengine/router/ifconfig_windows.go index 2f948f15f..24da9d50d 100644 --- a/wgengine/router/ifconfig_windows.go +++ b/wgengine/router/ifconfig_windows.go @@ -324,16 +324,16 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) { var firstGateway6 *net.IP addresses := make([]*net.IPNet, 0, len(cfg.LocalAddrs)) for _, addr := range cfg.LocalAddrs { - if (addr.IP.Is4() && ipif4 == nil) || (addr.IP.Is6() && ipif6 == nil) { + if (addr.IP().Is4() && ipif4 == nil) || (addr.IP().Is6() && ipif6 == nil) { // Can't program addresses for disabled protocol. continue } ipnet := addr.IPNet() addresses = append(addresses, ipnet) gateway := ipnet.IP - if addr.IP.Is4() && firstGateway4 == nil { + if addr.IP().Is4() && firstGateway4 == nil { firstGateway4 = &gateway - } else if addr.IP.Is6() && firstGateway6 == nil { + } else if addr.IP().Is6() && firstGateway6 == nil { firstGateway6 = &gateway } } @@ -342,12 +342,12 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) { foundDefault4 := false foundDefault6 := false for _, route := range cfg.Routes { - if (route.IP.Is4() && ipif4 == nil) || (route.IP.Is6() && ipif6 == nil) { + if (route.IP().Is4() && ipif4 == nil) || (route.IP().Is6() && ipif6 == nil) { // Can't program routes for disabled protocol. continue } - if route.IP.Is6() && firstGateway6 == nil { + if route.IP().Is6() && firstGateway6 == nil { // Windows won't let us set IPv6 routes without having an // IPv6 local address set. However, when we've configured // a default route, we want to forcibly grab IPv6 traffic @@ -357,16 +357,16 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) { ipnet := &net.IPNet{tsaddr.Tailscale4To6Placeholder().IPAddr().IP, net.CIDRMask(128, 128)} addresses = append(addresses, ipnet) firstGateway6 = &ipnet.IP - } else if route.IP.Is4() && firstGateway4 == nil { + } else if route.IP().Is4() && firstGateway4 == nil { // TODO: do same dummy behavior as v6? return errors.New("due to a Windows limitation, one cannot have interface routes without an interface address") } ipn := route.IPNet() var gateway net.IP - if route.IP.Is4() { + if route.IP().Is4() { gateway = *firstGateway4 - } else if route.IP.Is6() { + } else if route.IP().Is6() { gateway = *firstGateway6 } r := winipcfg.RouteData{ @@ -385,13 +385,13 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) { // then the interface's IP won't be pingable. continue } - if route.IP.Is4() { - if route.Bits == 0 { + if route.IP().Is4() { + if route.Bits() == 0 { foundDefault4 = true } r.NextHop = *firstGateway4 - } else if route.IP.Is6() { - if route.Bits == 0 { + } else if route.IP().Is6() { + if route.Bits() == 0 { foundDefault6 = true } r.NextHop = *firstGateway6 @@ -760,11 +760,8 @@ func filterRoutes(routes []*winipcfg.RouteData, dontDelete []netaddr.IPPrefix) [ if nr.IsSingleIP() { continue } - lastIP := nr.Range().To - ddm[netaddr.IPPrefix{ - IP: lastIP, - Bits: lastIP.BitLen(), - }] = true + lastIP := nr.Range().To() + ddm[netaddr.IPPrefixFrom(lastIP, lastIP.BitLen())] = true } filtered := make([]*winipcfg.RouteData, 0, len(routes)) for _, r := range routes { diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index 60012ce9f..d1c16d623 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -360,7 +360,7 @@ func (r *linuxRouter) setNetfilterMode(mode preftype.NetfilterMode) error { } for cidr := range r.addrs { - if err := r.addLoopbackRule(cidr.IP); err != nil { + if err := r.addLoopbackRule(cidr.IP()); err != nil { return err } } @@ -372,13 +372,13 @@ func (r *linuxRouter) setNetfilterMode(mode preftype.NetfilterMode) error { // address is already assigned to the interface, or if the addition // fails. func (r *linuxRouter) addAddress(addr netaddr.IPPrefix) error { - if !r.v6Available && addr.IP.Is6() { + if !r.v6Available && addr.IP().Is6() { return nil } if err := r.cmd.run("ip", "addr", "add", addr.String(), "dev", r.tunname); err != nil { return fmt.Errorf("adding address %q to tunnel interface: %w", addr, err) } - if err := r.addLoopbackRule(addr.IP); err != nil { + if err := r.addLoopbackRule(addr.IP()); err != nil { return err } return nil @@ -388,10 +388,10 @@ func (r *linuxRouter) addAddress(addr netaddr.IPPrefix) error { // the address is not assigned to the interface, or if the removal // fails. func (r *linuxRouter) delAddress(addr netaddr.IPPrefix) error { - if !r.v6Available && addr.IP.Is6() { + if !r.v6Available && addr.IP().Is6() { return nil } - if err := r.delLoopbackRule(addr.IP); err != nil { + if err := r.delLoopbackRule(addr.IP()); err != nil { return err } if err := r.cmd.run("ip", "addr", "del", addr.String(), "dev", r.tunname); err != nil { @@ -463,7 +463,7 @@ func (r *linuxRouter) addThrowRoute(cidr netaddr.IPPrefix) error { } func (r *linuxRouter) addRouteDef(routeDef []string, cidr netaddr.IPPrefix) error { - if !r.v6Available && cidr.IP.Is6() { + if !r.v6Available && cidr.IP().Is6() { return nil } args := append([]string{"ip", "route", "add"}, routeDef...) @@ -490,7 +490,7 @@ func (r *linuxRouter) delThrowRoute(cidr netaddr.IPPrefix) error { } func (r *linuxRouter) delRouteDef(routeDef []string, cidr netaddr.IPPrefix) error { - if !r.v6Available && cidr.IP.Is6() { + if !r.v6Available && cidr.IP().Is6() { return nil } args := append([]string{"ip", "route", "del"}, routeDef...) @@ -520,7 +520,7 @@ func dashFam(ip netaddr.IP) string { } func (r *linuxRouter) hasRoute(routeDef []string, cidr netaddr.IPPrefix) (bool, error) { - args := append([]string{"ip", dashFam(cidr.IP), "route", "show"}, routeDef...) + args := append([]string{"ip", dashFam(cidr.IP()), "route", "show"}, routeDef...) if r.ipRuleAvailable { args = append(args, "table", tailscaleRouteTable) } diff --git a/wgengine/router/router_openbsd.go b/wgengine/router/router_openbsd.go index dc88d08cc..def6f30c0 100644 --- a/wgengine/router/router_openbsd.go +++ b/wgengine/router/router_openbsd.go @@ -69,11 +69,11 @@ func (r *openbsdRouter) Set(cfg *Config) error { localAddr4 := netaddr.IPPrefix{} localAddr6 := netaddr.IPPrefix{} for _, addr := range cfg.LocalAddrs { - if addr.IP.Is4() { + if addr.IP().Is4() { numIPv4++ localAddr4 = addr } - if addr.IP.Is6() { + if addr.IP().Is6() { numIPv6++ localAddr6 = addr } @@ -98,7 +98,7 @@ func (r *openbsdRouter) Set(cfg *Config) error { routedel := []string{"route", "-q", "-n", "del", "-inet", r.local4.String(), - "-iface", r.local4.IP.String()} + "-iface", r.local4.IP().String()} if out, err := cmd(routedel...).CombinedOutput(); err != nil { r.logf("route del failed: %v: %v\n%s", routedel, err, out) if errq == nil { @@ -120,7 +120,7 @@ func (r *openbsdRouter) Set(cfg *Config) error { routeadd := []string{"route", "-q", "-n", "add", "-inet", localAddr4.String(), - "-iface", localAddr4.IP.String()} + "-iface", localAddr4.IP().String()} if out, err := cmd(routeadd...).CombinedOutput(); err != nil { r.logf("route add failed: %v: %v\n%s", routeadd, err, out) if errq == nil { @@ -134,7 +134,7 @@ func (r *openbsdRouter) Set(cfg *Config) error { // in https://github.com/tailscale/tailscale/issues/1307 we made // FreeBSD use a /48 for IPv6 addresses, which is nice because we // don't need to additionally add routing entries. Do that here too. - localAddr6 = netaddr.IPPrefix{localAddr6.IP, 48} + localAddr6 = netaddr.IPPrefixFrom(localAddr6.IP(), 48) } if localAddr6 != r.local6 { @@ -171,10 +171,10 @@ func (r *openbsdRouter) Set(cfg *Config) error { if _, keep := newRoutes[route]; !keep { net := route.IPNet() nip := net.IP.Mask(net.Mask) - nstr := fmt.Sprintf("%v/%d", nip, route.Bits) + nstr := fmt.Sprintf("%v/%d", nip, route.Bits()) routedel := []string{"route", "-q", "-n", "del", "-inet", nstr, - "-iface", localAddr4.IP.String()} + "-iface", localAddr4.IP().String()} out, err := cmd(routedel...).CombinedOutput() if err != nil { r.logf("route del failed: %v: %v\n%s", routedel, err, out) @@ -188,10 +188,10 @@ func (r *openbsdRouter) Set(cfg *Config) error { if _, exists := r.routes[route]; !exists { net := route.IPNet() nip := net.IP.Mask(net.Mask) - nstr := fmt.Sprintf("%v/%d", nip, route.Bits) + nstr := fmt.Sprintf("%v/%d", nip, route.Bits()) routeadd := []string{"route", "-q", "-n", "add", "-inet", nstr, - "-iface", localAddr4.IP.String()} + "-iface", localAddr4.IP().String()} out, err := cmd(routeadd...).CombinedOutput() if err != nil { r.logf("addr add failed: %v: %v\n%s", routeadd, err, out) diff --git a/wgengine/router/router_userspace_bsd.go b/wgengine/router/router_userspace_bsd.go index 8ad558827..eacd0ed4c 100644 --- a/wgengine/router/router_userspace_bsd.go +++ b/wgengine/router/router_userspace_bsd.go @@ -87,7 +87,7 @@ func (r *userspaceBSDRouter) Up() error { } func inet(p netaddr.IPPrefix) string { - if p.IP.Is6() { + if p.IP().Is6() { return "inet6" } return "inet" @@ -116,15 +116,15 @@ func (r *userspaceBSDRouter) Set(cfg *Config) (reterr error) { } for _, addr := range r.addrsToAdd(cfg.LocalAddrs) { var arg []string - if runtime.GOOS == "freebsd" && addr.IP.Is6() && addr.Bits == 128 { + if runtime.GOOS == "freebsd" && addr.IP().Is6() && addr.Bits() == 128 { // FreeBSD rejects tun addresses of the form fc00::1/128 -> fc00::1, // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=218508 // Instead add our whole /48, which works because we use a /48 route. // Full history: https://github.com/tailscale/tailscale/issues/1307 - tmp := netaddr.IPPrefix{IP: addr.IP, Bits: 48} + tmp := netaddr.IPPrefixFrom(addr.IP(), 48) arg = []string{"ifconfig", r.tunname, inet(tmp), tmp.String()} } else { - arg = []string{"ifconfig", r.tunname, inet(addr), addr.String(), addr.IP.String()} + arg = []string{"ifconfig", r.tunname, inet(addr), addr.String(), addr.IP().String()} } out, err := cmd(arg...).CombinedOutput() if err != nil { @@ -148,7 +148,7 @@ func (r *userspaceBSDRouter) Set(cfg *Config) (reterr error) { if _, keep := newRoutes[route]; !keep { net := route.IPNet() nip := net.IP.Mask(net.Mask) - nstr := fmt.Sprintf("%v/%d", nip, route.Bits) + nstr := fmt.Sprintf("%v/%d", nip, route.Bits()) del := "del" if version.OS() == "macOS" { del = "delete" @@ -168,7 +168,7 @@ func (r *userspaceBSDRouter) Set(cfg *Config) (reterr error) { if _, exists := r.routes[route]; !exists { net := route.IPNet() nip := net.IP.Mask(net.Mask) - nstr := fmt.Sprintf("%v/%d", nip, route.Bits) + nstr := fmt.Sprintf("%v/%d", nip, route.Bits()) routeadd := []string{"route", "-q", "-n", "add", "-" + inet(route), nstr, "-iface", r.tunname} diff --git a/wgengine/router/router_windows.go b/wgengine/router/router_windows.go index 216b95d0c..d9c1da3aa 100644 --- a/wgengine/router/router_windows.go +++ b/wgengine/router/router_windows.go @@ -91,7 +91,7 @@ func (r *winRouter) Set(cfg *Config) error { func hasDefaultRoute(routes []netaddr.IPPrefix) bool { for _, route := range routes { - if route.Bits == 0 { + if route.Bits() == 0 { return true } } diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 6e56bbd11..0868e87c6 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -399,7 +399,7 @@ func (e *userspaceEngine) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper) isLocalAddr, ok := e.isLocalAddr.Load().(func(netaddr.IP) bool) if !ok { e.logf("[unexpected] e.isLocalAddr was nil, can't check for loopback packet") - } else if isLocalAddr(p.Dst.IP) { + } else if isLocalAddr(p.Dst.IP()) { // macOS NetworkExtension directs packets destined to the // tunnel's local IP address into the tunnel, instead of // looping back within the kernel network stack. We have to @@ -415,7 +415,7 @@ func (e *userspaceEngine) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper) // handleDNS is an outbound pre-filter resolving Tailscale domains. func (e *userspaceEngine) handleDNS(p *packet.Parsed, t *tstun.Wrapper) filter.Response { - if p.Dst.IP == magicDNSIP && p.Dst.Port == magicDNSPort && p.IPProto == ipproto.UDP { + if p.Dst.IP() == magicDNSIP && p.Dst.Port() == magicDNSPort && p.IPProto == ipproto.UDP { err := e.dns.EnqueueRequest(append([]byte(nil), p.Payload()...), p.Src) if err != nil { e.logf("dns: enqueue: %v", err) @@ -440,10 +440,10 @@ func (e *userspaceEngine) pollResolver() { h := packet.UDP4Header{ IP4Header: packet.IP4Header{ Src: magicDNSIP, - Dst: to.IP, + Dst: to.IP(), }, SrcPort: magicDNSPort, - DstPort: to.Port, + DstPort: to.Port(), } hlen := h.Len() @@ -620,8 +620,8 @@ func (e *userspaceEngine) maybeReconfigWireguardLocked(discoChanged map[key.Publ trackDisco = append(trackDisco, dk) recentlyActive := false for _, cidr := range p.AllowedIPs { - trackIPs = append(trackIPs, cidr.IP) - recentlyActive = recentlyActive || e.isActiveSince(dk, cidr.IP, activeCutoff) + trackIPs = append(trackIPs, cidr.IP()) + recentlyActive = recentlyActive || e.isActiveSince(dk, cidr.IP(), activeCutoff) } if recentlyActive { min.Peers = append(min.Peers, *p) @@ -1156,8 +1156,8 @@ func (e *userspaceEngine) mySelfIPMatchingFamily(dst netaddr.IP) (src netaddr.IP return netaddr.IP{}, errors.New("no netmap") } for _, a := range e.netMap.Addresses { - if a.IsSingleIP() && a.IP.BitLen() == dst.BitLen() { - return a.IP, nil + if a.IsSingleIP() && a.IP().BitLen() == dst.BitLen() { + return a.IP(), nil } } if len(e.netMap.Addresses) == 0 { @@ -1293,7 +1293,7 @@ func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, err error) var bestInNM *tailcfg.Node for _, p := range nm.Peers { for _, a := range p.Addresses { - if a.IP == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) { + if a.IP() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) { return p, nil } } @@ -1301,7 +1301,7 @@ func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, err error) if !cidr.Contains(ip) { continue } - if bestInNMPrefix.IsZero() || cidr.Bits > bestInNMPrefix.Bits { + if bestInNMPrefix.IsZero() || cidr.Bits() > bestInNMPrefix.Bits() { bestInNMPrefix = cidr bestInNM = p } @@ -1319,7 +1319,7 @@ func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, err error) if !cidr.Contains(ip) { continue } - if best.IsZero() || cidr.Bits > best.Bits { + if best.IsZero() || cidr.Bits() > best.Bits() { best = cidr bestKey = tailcfg.NodeKey(p.PublicKey) } @@ -1337,7 +1337,7 @@ func (e *userspaceEngine) peerForIP(ip netaddr.IP) (n *tailcfg.Node, err error) if bestInNM == nil { return nil, nil } - if bestInNMPrefix.Bits == 0 { + if bestInNMPrefix.Bits() == 0 { return nil, errors.New("exit node found but not enabled") } return nil, fmt.Errorf("node %q found, but not using its %v route", bestInNM.ComputedNameWithHost, bestInNMPrefix) diff --git a/wgengine/userspace_test.go b/wgengine/userspace_test.go index ea5f3ef08..6954ce63a 100644 --- a/wgengine/userspace_test.go +++ b/wgengine/userspace_test.go @@ -102,7 +102,7 @@ func TestUserspaceEngineReconfig(t *testing.T) { Peers: []wgcfg.Peer{ { AllowedIPs: []netaddr.IPPrefix{ - {IP: netaddr.IPv4(100, 100, 99, 1), Bits: 32}, + netaddr.IPPrefixFrom(netaddr.IPv4(100, 100, 99, 1), 32), }, Endpoints: wgcfg.Endpoints{DiscoKey: dkFromHex(discoHex)}, }, diff --git a/wgengine/wgcfg/nmcfg/nmcfg.go b/wgengine/wgcfg/nmcfg/nmcfg.go index 938bd6826..eaf051c78 100644 --- a/wgengine/wgcfg/nmcfg/nmcfg.go +++ b/wgengine/wgcfg/nmcfg/nmcfg.go @@ -37,7 +37,7 @@ func nodeDebugName(n *tailcfg.Node) string { // cidrIsSubnet reports whether cidr is a non-default-route subnet // exported by node that is not one of its own self addresses. func cidrIsSubnet(node *tailcfg.Node, cidr netaddr.IPPrefix) bool { - if cidr.Bits == 0 { + if cidr.Bits() == 0 { return false } if !cidr.IsSingleIP() { @@ -93,7 +93,7 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags, } didExitNodeWarn := false for _, allowedIP := range peer.AllowedIPs { - if allowedIP.Bits == 0 && peer.StableID != exitNode { + if allowedIP.Bits() == 0 && peer.StableID != exitNode { if didExitNodeWarn { // Don't log about both the IPv4 /0 and IPv6 /0. continue @@ -104,11 +104,11 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags, } fmt.Fprintf(skippedUnselected, "%q (%v)", nodeDebugName(peer), peer.Key.ShortString()) continue - } else if allowedIP.IsSingleIP() && tsaddr.IsTailscaleIP(allowedIP.IP) && (flags&netmap.AllowSingleHosts) == 0 { + } else if allowedIP.IsSingleIP() && tsaddr.IsTailscaleIP(allowedIP.IP()) && (flags&netmap.AllowSingleHosts) == 0 { if skippedIPs.Len() > 0 { skippedIPs.WriteString(", ") } - fmt.Fprintf(skippedIPs, "%v from %q (%v)", allowedIP.IP, nodeDebugName(peer), peer.Key.ShortString()) + fmt.Fprintf(skippedIPs, "%v from %q (%v)", allowedIP.IP(), nodeDebugName(peer), peer.Key.ShortString()) continue } else if cidrIsSubnet(peer, allowedIP) { if (flags & netmap.AllowSubnetRoutes) == 0 {