From 7eaf5e509fe3a921a9caa05173b7f7a80c504601 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 24 Jul 2022 20:08:42 -0700 Subject: [PATCH] net/netaddr: start migrating to net/netip via new netaddr adapter package Updates #5162 Change-Id: Id7bdec303b25471f69d542f8ce43805328d56c12 Signed-off-by: Brad Fitzpatrick --- client/tailscale/acl.go | 2 +- client/tailscale/localclient.go | 2 +- client/tailscale/routes.go | 4 +- cmd/hello/hello.go | 6 +- cmd/tailscale/cli/cli_test.go | 2 +- cmd/tailscale/cli/debug.go | 13 +- cmd/tailscale/cli/file.go | 6 +- cmd/tailscale/cli/ip.go | 2 +- cmd/tailscale/cli/ping.go | 2 +- cmd/tailscale/cli/ssh.go | 4 +- cmd/tailscale/cli/status.go | 2 +- cmd/tailscale/cli/up.go | 16 +-- cmd/tailscale/cli/web.go | 2 +- cmd/tailscale/depaware.txt | 8 +- cmd/tailscaled/debug.go | 2 +- cmd/tailscaled/depaware.txt | 11 +- cmd/tailscaled/tailscaled.go | 2 +- cmd/tailscaled/tailscaled_windows.go | 2 +- cmd/tsconnect/wasm/wasm_js.go | 6 +- cmd/viewer/tests/tests.go | 2 +- cmd/viewer/tests/tests_clone.go | 6 +- cmd/viewer/tests/tests_view.go | 10 +- cmd/viewer/viewer.go | 2 +- control/controlclient/direct.go | 4 +- control/controlclient/direct_test.go | 2 +- control/controlclient/map.go | 4 +- derp/derp_client.go | 2 +- derp/derp_server.go | 2 +- derp/derphttp/derphttp_client.go | 2 +- disco/disco.go | 6 +- disco/disco_test.go | 2 +- go.mod | 1 + go.sum | 2 + ipn/handle.go | 2 +- ipn/ipn_clone.go | 7 +- ipn/ipnlocal/dnsconfig_test.go | 5 +- ipn/ipnlocal/local.go | 92 ++++++------ ipn/ipnlocal/local_test.go | 9 +- ipn/ipnlocal/peerapi.go | 17 ++- ipn/ipnlocal/peerapi_macios_ext.go | 2 +- ipn/ipnlocal/peerapi_test.go | 5 +- ipn/ipnserver/server.go | 8 +- ipn/ipnstate/ipnstate.go | 2 +- ipn/localapi/localapi.go | 4 +- ipn/prefs.go | 7 +- ipn/prefs_test.go | 2 +- net/dns/config.go | 2 +- net/dns/direct.go | 2 +- net/dns/direct_test.go | 2 +- net/dns/manager.go | 12 +- net/dns/manager_linux.go | 2 +- net/dns/manager_tcp_test.go | 2 +- net/dns/manager_test.go | 4 +- net/dns/manager_windows.go | 2 +- net/dns/manager_windows_test.go | 2 +- net/dns/nm.go | 2 +- net/dns/osconfig.go | 2 +- net/dns/publicdns/publicdns.go | 2 +- net/dns/publicdns/publicdns_test.go | 2 +- net/dns/resolvconffile/resolvconffile.go | 2 +- net/dns/resolvconffile/resolvconffile_test.go | 2 +- net/dns/resolved.go | 10 +- net/dns/resolver/forwarder.go | 31 ++-- net/dns/resolver/tsdns.go | 7 +- net/dns/resolver/tsdns_server_test.go | 14 +- net/dns/resolver/tsdns_test.go | 2 +- net/dnscache/dnscache.go | 12 +- net/dnscache/dnscache_test.go | 2 +- net/dnsfallback/dns-fallback-servers.json | 23 +-- net/dnsfallback/dnsfallback.go | 4 +- net/flowtrack/flowtrack.go | 2 +- net/flowtrack/flowtrack_test.go | 2 +- net/interfaces/interfaces.go | 26 ++-- net/interfaces/interfaces_bsd.go | 2 +- net/interfaces/interfaces_darwin.go | 2 +- net/interfaces/interfaces_darwin_test.go | 4 +- net/interfaces/interfaces_linux.go | 6 +- net/interfaces/interfaces_test.go | 2 +- net/interfaces/interfaces_windows.go | 6 +- net/netaddr/netaddr.go | 135 ++++++++++++++++++ net/netcheck/netcheck.go | 63 ++++---- net/netcheck/netcheck_test.go | 2 +- net/netns/netns.go | 2 +- net/netstat/netstat.go | 2 +- net/netstat/netstat_windows.go | 2 +- net/netutil/ip_forward.go | 8 +- net/packet/icmp6_test.go | 2 +- net/packet/ip4.go | 2 +- net/packet/ip6.go | 2 +- net/packet/packet.go | 59 ++++---- net/packet/packet_test.go | 2 +- net/packet/tsmp.go | 14 +- net/packet/tsmp_test.go | 2 +- net/portmapper/disabled_stubs.go | 2 +- net/portmapper/igd_test.go | 10 +- net/portmapper/pcp.go | 6 +- net/portmapper/pcp_test.go | 2 +- net/portmapper/portmapper.go | 59 +++++--- net/portmapper/portmapper_test.go | 2 +- net/portmapper/upnp.go | 6 +- net/portmapper/upnp_test.go | 2 +- net/socks5/socks5_test.go | 4 +- net/stun/stuntest/stuntest.go | 2 +- net/tsaddr/tsaddr.go | 29 ++-- net/tsaddr/tsaddr_test.go | 2 +- net/tsdial/dnsmap.go | 10 +- net/tsdial/dnsmap_test.go | 2 +- net/tsdial/tsdial.go | 6 +- net/tstun/tap_linux.go | 6 +- net/tstun/wrap.go | 12 +- net/tstun/wrap_test.go | 13 +- ssh/tailssh/incubator.go | 6 +- ssh/tailssh/tailssh.go | 16 +-- ssh/tailssh/tailssh_test.go | 2 +- tailcfg/tailcfg.go | 2 +- tailcfg/tailcfg_clone.go | 12 +- tailcfg/tailcfg_test.go | 2 +- tailcfg/tailcfg_view.go | 14 +- tsnet/tsnet.go | 2 +- tstest/integration/integration_test.go | 2 +- .../tailscaled_deps_test_darwin.go | 2 +- .../tailscaled_deps_test_freebsd.go | 2 +- .../integration/tailscaled_deps_test_linux.go | 2 +- .../tailscaled_deps_test_openbsd.go | 2 +- .../tailscaled_deps_test_windows.go | 2 +- tstest/integration/testcontrol/testcontrol.go | 8 +- .../integration/vms/derive_bindhost_test.go | 4 +- tstest/integration/vms/harness_test.go | 2 +- tstest/integration/vms/vms_steps_test.go | 2 +- tstest/integration/vms/vms_test.go | 2 +- tstest/iosdeps/iosdeps.go | 2 +- tstest/jsdeps/jsdeps.go | 2 +- tstest/natlab/firewall.go | 5 +- tstest/natlab/nat.go | 7 +- tstest/natlab/natlab.go | 88 +++++++----- tstest/natlab/natlab_test.go | 22 +-- tsweb/tsweb.go | 2 +- types/dnstype/dnstype.go | 2 +- types/dnstype/dnstype_clone.go | 4 +- types/dnstype/dnstype_view.go | 2 +- types/key/node.go | 2 +- types/netmap/netmap.go | 4 +- types/netmap/netmap_test.go | 2 +- types/nettype/nettype.go | 26 ++++ types/views/views.go | 2 +- types/views/views_test.go | 2 +- util/codegen/codegen.go | 2 +- util/deephash/deephash_test.go | 2 +- util/netconv/netconv.go | 63 -------- util/netconv/netconv_test.go | 76 ---------- wf/firewall.go | 4 +- wgengine/bench/bench.go | 4 +- wgengine/bench/bench_test.go | 2 +- wgengine/bench/trafficgen.go | 2 +- wgengine/bench/wg.go | 2 +- wgengine/filter/filter.go | 35 ++--- wgengine/filter/filter_clone.go | 5 +- wgengine/filter/filter_test.go | 19 +-- wgengine/filter/match.go | 14 +- wgengine/filter/tailcfg.go | 7 +- wgengine/magicsock/debughttp.go | 4 +- wgengine/magicsock/magicsock.go | 133 +++++++++-------- wgengine/magicsock/magicsock_test.go | 9 +- wgengine/monitor/monitor.go | 2 +- wgengine/monitor/monitor_darwin.go | 4 +- wgengine/monitor/monitor_linux.go | 12 +- wgengine/monitor/monitor_linux_test.go | 2 +- wgengine/monitor/monitor_windows.go | 4 +- wgengine/netstack/netstack.go | 50 +++---- wgengine/netstack/netstack_test.go | 2 +- wgengine/pendopen.go | 8 +- wgengine/router/ifconfig_windows.go | 34 ++--- wgengine/router/ifconfig_windows_test.go | 5 +- wgengine/router/router.go | 2 +- wgengine/router/router_linux.go | 37 ++--- wgengine/router/router_linux_test.go | 2 +- wgengine/router/router_openbsd.go | 41 +++--- wgengine/router/router_test.go | 2 +- wgengine/router/router_userspace_bsd.go | 15 +- wgengine/router/router_windows.go | 2 +- wgengine/userspace.go | 25 ++-- wgengine/userspace_test.go | 2 +- wgengine/watchdog.go | 2 +- wgengine/wgcfg/config.go | 2 +- wgengine/wgcfg/device_test.go | 2 +- wgengine/wgcfg/nmcfg/nmcfg.go | 6 +- wgengine/wgcfg/parser.go | 2 +- wgengine/wgcfg/parser_test.go | 2 +- wgengine/wgcfg/wgcfg_clone.go | 9 +- wgengine/wgcfg/writer.go | 2 +- wgengine/wgengine.go | 2 +- 191 files changed, 1009 insertions(+), 888 deletions(-) create mode 100644 net/netaddr/netaddr.go delete mode 100644 util/netconv/netconv.go delete mode 100644 util/netconv/netconv_test.go diff --git a/client/tailscale/acl.go b/client/tailscale/acl.go index 824bc31e5..53274c9d0 100644 --- a/client/tailscale/acl.go +++ b/client/tailscale/acl.go @@ -14,7 +14,7 @@ import ( "fmt" "net/http" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) // ACLRow defines a rule that grants access by a set of users or groups to a set diff --git a/client/tailscale/localclient.go b/client/tailscale/localclient.go index 8697c1137..da7ce2430 100644 --- a/client/tailscale/localclient.go +++ b/client/tailscale/localclient.go @@ -28,10 +28,10 @@ import ( "time" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/client/tailscale/apitype" "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/net/netutil" "tailscale.com/paths" "tailscale.com/safesocket" diff --git a/client/tailscale/routes.go b/client/tailscale/routes.go index 5c8109b34..e6cc95f68 100644 --- a/client/tailscale/routes.go +++ b/client/tailscale/routes.go @@ -14,7 +14,7 @@ import ( "fmt" "net/http" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) // Routes contains the lists of subnet routes that are currently advertised by a device, @@ -60,7 +60,7 @@ type postRoutesParams struct { } // SetRoutes updates the list of subnets that are enabled for a device. -// Subnets must be parsable by inet.af/netaddr.ParseIPPrefix. +// Subnets must be parsable by tailscale.com/net/netaddr.ParseIPPrefix. // Subnets do not have to be currently advertised by a device, they may be pre-enabled. // Returns the updated list of enabled and advertised subnet routes in a *Routes object. func (c *Client) SetRoutes(ctx context.Context, deviceID string, subnets []netaddr.IPPrefix) (routes *Routes, err error) { diff --git a/cmd/hello/hello.go b/cmd/hello/hello.go index a0e596f2d..966e329ce 100644 --- a/cmd/hello/hello.go +++ b/cmd/hello/hello.go @@ -135,13 +135,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.Addr().Is4() && nodeIP.IsSingleIP() { + return nodeIP.Addr().String() } } for _, nodeIP := range who.Node.Addresses { if nodeIP.IsSingleIP() { - return nodeIP.IP().String() + return nodeIP.Addr().String() } } return "" diff --git a/cmd/tailscale/cli/cli_test.go b/cmd/tailscale/cli/cli_test.go index c25059db4..74e11fa3d 100644 --- a/cmd/tailscale/cli/cli_test.go +++ b/cmd/tailscale/cli/cli_test.go @@ -15,9 +15,9 @@ import ( qt "github.com/frankban/quicktest" "github.com/google/go-cmp/cmp" - "inet.af/netaddr" "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/types/persist" "tailscale.com/types/preftype" diff --git a/cmd/tailscale/cli/debug.go b/cmd/tailscale/cli/debug.go index 72ef186fb..5870f4bae 100644 --- a/cmd/tailscale/cli/debug.go +++ b/cmd/tailscale/cli/debug.go @@ -17,6 +17,7 @@ import ( "log" "net" "net/http" + "net/netip" "os" "runtime" "strconv" @@ -24,10 +25,10 @@ import ( "time" "github.com/peterbourgon/ff/v3/ffcli" - "inet.af/netaddr" "tailscale.com/control/controlhttp" "tailscale.com/hostinfo" "tailscale.com/ipn" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/paths" "tailscale.com/safesocket" @@ -408,19 +409,19 @@ func runVia(ctx context.Context, args []string) error { if err != nil { return err } - if !ipp.IP().Is6() { + if !ipp.Addr().Is6() { return errors.New("with one argument, expect an IPv6 CIDR") } - if !tsaddr.TailscaleViaRange().Contains(ipp.IP()) { + if !tsaddr.TailscaleViaRange().Contains(ipp.Addr()) { return errors.New("not a via route") } if ipp.Bits() < 96 { return errors.New("short length, want /96 or more") } - v4 := tsaddr.UnmapVia(ipp.IP()) - a := ipp.IP().As16() + v4 := tsaddr.UnmapVia(ipp.Addr()) + a := ipp.Addr().As16() siteID := binary.BigEndian.Uint32(a[8:12]) - fmt.Printf("site %v (0x%x), %v\n", siteID, siteID, netaddr.IPPrefixFrom(v4, ipp.Bits()-96)) + fmt.Printf("site %v (0x%x), %v\n", siteID, siteID, netip.PrefixFrom(v4, ipp.Bits()-96)) case 2: siteID, err := strconv.ParseUint(args[0], 0, 32) if err != nil { diff --git a/cmd/tailscale/cli/file.go b/cmd/tailscale/cli/file.go index 1dc5b9d38..cff347e51 100644 --- a/cmd/tailscale/cli/file.go +++ b/cmd/tailscale/cli/file.go @@ -23,10 +23,10 @@ import ( "github.com/peterbourgon/ff/v3/ffcli" "golang.org/x/time/rate" - "inet.af/netaddr" "tailscale.com/client/tailscale/apitype" "tailscale.com/envknob" "tailscale.com/ipn" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/version" @@ -179,7 +179,7 @@ func getTargetStableID(ctx context.Context, ipStr string) (id tailcfg.StableNode for _, ft := range fts { n := ft.Node for _, a := range n.Addresses { - if a.IP() != ip { + if a.Addr() != ip { continue } isOffline = n.Online != nil && !*n.Online @@ -281,7 +281,7 @@ func runCpTargets(ctx context.Context, args []string) error { if detail != "" { detail = "\t" + detail } - printf("%s\t%s%s\n", n.Addresses[0].IP(), n.ComputedName, detail) + printf("%s\t%s%s\n", n.Addresses[0].Addr(), n.ComputedName, detail) } return nil } diff --git a/cmd/tailscale/cli/ip.go b/cmd/tailscale/cli/ip.go index d4fe055d7..25af35910 100644 --- a/cmd/tailscale/cli/ip.go +++ b/cmd/tailscale/cli/ip.go @@ -11,8 +11,8 @@ import ( "fmt" "github.com/peterbourgon/ff/v3/ffcli" - "inet.af/netaddr" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" ) var ipCmd = &ffcli.Command{ diff --git a/cmd/tailscale/cli/ping.go b/cmd/tailscale/cli/ping.go index 5fe338da5..22f914453 100644 --- a/cmd/tailscale/cli/ping.go +++ b/cmd/tailscale/cli/ping.go @@ -16,8 +16,8 @@ import ( "time" "github.com/peterbourgon/ff/v3/ffcli" - "inet.af/netaddr" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" ) diff --git a/cmd/tailscale/cli/ssh.go b/cmd/tailscale/cli/ssh.go index 0db6ebd51..5043aed65 100644 --- a/cmd/tailscale/cli/ssh.go +++ b/cmd/tailscale/cli/ssh.go @@ -17,9 +17,9 @@ import ( "strings" "github.com/peterbourgon/ff/v3/ffcli" - "inet.af/netaddr" "tailscale.com/envknob" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/version" ) @@ -166,7 +166,7 @@ func nodeDNSNameFromArg(st *ipnstate.Status, arg string) (dnsName string, ok boo argIP, _ := netaddr.ParseIP(arg) for _, ps := range st.Peer { dnsName = ps.DNSName - if !argIP.IsZero() { + if argIP.IsValid() { for _, ip := range ps.TailscaleIPs { if ip == argIP { return dnsName, true diff --git a/cmd/tailscale/cli/status.go b/cmd/tailscale/cli/status.go index e0f05d195..34f83ccd3 100644 --- a/cmd/tailscale/cli/status.go +++ b/cmd/tailscale/cli/status.go @@ -18,10 +18,10 @@ import ( "github.com/peterbourgon/ff/v3/ffcli" "github.com/toqueteos/webbrowser" - "inet.af/netaddr" "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 9a2fd6ab0..afd2abb17 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -24,9 +24,9 @@ import ( shellquote "github.com/kballard/go-shellquote" "github.com/peterbourgon/ff/v3/ffcli" qrcode "github.com/skip2/go-qrcode" - "inet.af/netaddr" "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/safesocket" "tailscale.com/tailcfg" @@ -210,7 +210,7 @@ func validateViaPrefix(ipp netaddr.IPPrefix) error { if ipp.Bits() < (128 - 32) { return fmt.Errorf("%v 4-in-6 prefix must be at least a /%v", ipp, 128-32) } - a := ipp.IP().As16() + a := ipp.Addr().As16() // The first 64 bits of a are the via prefix. // The next 32 bits are the "site ID". // The last 32 bits are the IPv4. @@ -266,7 +266,7 @@ func calcAdvertiseRoutes(advertiseRoutes string, advertiseDefaultRoute bool) ([] 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].Addr().Less(routes[j].Addr()) }) return routes, nil } @@ -913,10 +913,10 @@ func prefsToFlags(env upCheckEnv, prefs *ipn.Prefs) (flagVal map[string]any) { ret := make(map[string]any) exitNodeIPStr := func() string { - if !prefs.ExitNodeIP.IsZero() { + if prefs.ExitNodeIP.IsValid() { return prefs.ExitNodeIP.String() } - if prefs.ExitNodeID.IsZero() || env.curExitNodeIP.IsZero() { + if prefs.ExitNodeID.IsZero() || !env.curExitNodeIP.IsValid() { return "" } return env.curExitNodeIP.String() @@ -995,9 +995,9 @@ func hasExitNodeRoutes(rr []netaddr.IPPrefix) bool { var v4, v6 bool for _, r := range rr { if r.Bits() == 0 { - if r.IP().Is4() { + if r.Addr().Is4() { v4 = true - } else if r.IP().Is6() { + } else if r.Addr().Is6() { v6 = true } } @@ -1027,7 +1027,7 @@ func exitNodeIP(p *ipn.Prefs, st *ipnstate.Status) (ip netaddr.IP) { if p == nil { return } - if !p.ExitNodeIP.IsZero() { + if p.ExitNodeIP.IsValid() { return p.ExitNodeIP } id := p.ExitNodeID diff --git a/cmd/tailscale/cli/web.go b/cmd/tailscale/cli/web.go index 855471d15..98a8916d9 100644 --- a/cmd/tailscale/cli/web.go +++ b/cmd/tailscale/cli/web.go @@ -27,8 +27,8 @@ import ( "strings" "github.com/peterbourgon/ff/v3/ffcli" - "inet.af/netaddr" "tailscale.com/ipn" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/preftype" "tailscale.com/util/groupmember" diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index c5c65c1e4..31eb00d46 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -26,11 +26,9 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck github.com/toqueteos/webbrowser from tailscale.com/cmd/tailscale/cli - πŸ’£ go4.org/intern from inet.af/netaddr πŸ’£ go4.org/mem from tailscale.com/derp+ - go4.org/unsafe/assume-no-moving-gc from go4.org/intern + go4.org/netipx from tailscale.com/wgengine/filter W πŸ’£ golang.zx2c4.com/wireguard/windows/tunnel/winipcfg from tailscale.com/net/interfaces+ - inet.af/netaddr from tailscale.com/cmd/tailscale/cli+ nhooyr.io/websocket from tailscale.com/derp/derphttp+ nhooyr.io/websocket/internal/errd from nhooyr.io/websocket nhooyr.io/websocket/internal/xsync from nhooyr.io/websocket @@ -54,6 +52,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/net/dnsfallback from tailscale.com/control/controlhttp tailscale.com/net/flowtrack from tailscale.com/wgengine/filter+ πŸ’£ tailscale.com/net/interfaces from tailscale.com/cmd/tailscale/cli+ + tailscale.com/net/netaddr from tailscale.com/client/tailscale+ tailscale.com/net/netcheck from tailscale.com/cmd/tailscale/cli tailscale.com/net/neterror from tailscale.com/net/netcheck+ tailscale.com/net/netknob from tailscale.com/net/netns @@ -78,6 +77,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/types/key from tailscale.com/derp+ tailscale.com/types/logger from tailscale.com/cmd/tailscale/cli+ tailscale.com/types/netmap from tailscale.com/ipn + tailscale.com/types/nettype from tailscale.com/net/netcheck+ tailscale.com/types/opt from tailscale.com/net/netcheck+ tailscale.com/types/pad32 from tailscale.com/derp tailscale.com/types/persist from tailscale.com/ipn @@ -190,7 +190,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep net/http/cgi from tailscale.com/cmd/tailscale/cli net/http/httptrace from github.com/tcnksm/go-httpstat+ net/http/internal from net/http - net/netip from net + net/netip from net+ net/textproto from golang.org/x/net/http/httpguts+ net/url from crypto/x509+ os from crypto/rand+ diff --git a/cmd/tailscaled/debug.go b/cmd/tailscaled/debug.go index d4e6df496..0ea517aa4 100644 --- a/cmd/tailscaled/debug.go +++ b/cmd/tailscaled/debug.go @@ -25,11 +25,11 @@ import ( "strings" "time" - "inet.af/netaddr" "tailscale.com/derp/derphttp" "tailscale.com/envknob" "tailscale.com/ipn" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/portmapper" "tailscale.com/net/tshttpproxy" "tailscale.com/tailcfg" diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 052893f58..b24546552 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -113,9 +113,10 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de L github.com/u-root/uio/uio from github.com/insomniacslk/dhcp/dhcpv4+ L πŸ’£ github.com/vishvananda/netlink/nl from github.com/tailscale/netlink L github.com/vishvananda/netns from github.com/tailscale/netlink+ - πŸ’£ go4.org/intern from inet.af/netaddr + W πŸ’£ go4.org/intern from inet.af/netaddr πŸ’£ go4.org/mem from tailscale.com/control/controlbase+ - go4.org/unsafe/assume-no-moving-gc from go4.org/intern + go4.org/netipx from tailscale.com/ipn/ipnlocal+ + W go4.org/unsafe/assume-no-moving-gc from go4.org/intern W πŸ’£ golang.zx2c4.com/wintun from golang.zx2c4.com/wireguard/tun πŸ’£ golang.zx2c4.com/wireguard/conn from golang.zx2c4.com/wireguard/device+ W πŸ’£ golang.zx2c4.com/wireguard/conn/winrio from golang.zx2c4.com/wireguard/conn @@ -168,7 +169,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de gvisor.dev/gvisor/pkg/tcpip/transport/tcpconntrack from gvisor.dev/gvisor/pkg/tcpip/stack gvisor.dev/gvisor/pkg/tcpip/transport/udp from tailscale.com/net/tstun+ gvisor.dev/gvisor/pkg/waiter from gvisor.dev/gvisor/pkg/context+ - inet.af/netaddr from tailscale.com/control/controlclient+ + W inet.af/netaddr from inet.af/wf inet.af/peercred from tailscale.com/ipn/ipnserver W πŸ’£ inet.af/wf from tailscale.com/wf nhooyr.io/websocket from tailscale.com/derp/derphttp+ @@ -216,6 +217,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/net/dnsfallback from tailscale.com/control/controlclient+ tailscale.com/net/flowtrack from tailscale.com/net/packet+ πŸ’£ tailscale.com/net/interfaces from tailscale.com/control/controlclient+ + tailscale.com/net/netaddr from tailscale.com/client/tailscale+ tailscale.com/net/netcheck from tailscale.com/wgengine/magicsock tailscale.com/net/neterror from tailscale.com/net/dns/resolver+ tailscale.com/net/netknob from tailscale.com/net/netns+ @@ -252,7 +254,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/types/key from tailscale.com/control/controlbase+ tailscale.com/types/logger from tailscale.com/control/controlclient+ tailscale.com/types/netmap from tailscale.com/control/controlclient+ - tailscale.com/types/nettype from tailscale.com/wgengine/magicsock + tailscale.com/types/nettype from tailscale.com/wgengine/magicsock+ tailscale.com/types/opt from tailscale.com/control/controlclient+ tailscale.com/types/pad32 from tailscale.com/derp tailscale.com/types/persist from tailscale.com/control/controlclient+ @@ -269,7 +271,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/util/lineread from tailscale.com/hostinfo+ tailscale.com/util/mak from tailscale.com/control/controlclient+ tailscale.com/util/multierr from tailscale.com/control/controlclient+ - tailscale.com/util/netconv from tailscale.com/wgengine/magicsock tailscale.com/util/osshare from tailscale.com/ipn/ipnlocal+ tailscale.com/util/pidowner from tailscale.com/ipn/ipnserver tailscale.com/util/racebuild from tailscale.com/logpolicy diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index 58709a231..fd8c32e86 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -29,7 +29,6 @@ import ( "syscall" "time" - "inet.af/netaddr" "tailscale.com/cmd/tailscaled/childproc" "tailscale.com/control/controlclient" "tailscale.com/envknob" @@ -39,6 +38,7 @@ import ( "tailscale.com/logpolicy" "tailscale.com/logtail" "tailscale.com/net/dns" + "tailscale.com/net/netaddr" "tailscale.com/net/netns" "tailscale.com/net/proxymux" "tailscale.com/net/socks5" diff --git a/cmd/tailscaled/tailscaled_windows.go b/cmd/tailscaled/tailscaled_windows.go index 27f1c2742..8910c2855 100644 --- a/cmd/tailscaled/tailscaled_windows.go +++ b/cmd/tailscaled/tailscaled_windows.go @@ -32,12 +32,12 @@ import ( "golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc/eventlog" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" - "inet.af/netaddr" "tailscale.com/envknob" "tailscale.com/ipn/ipnserver" "tailscale.com/ipn/store" "tailscale.com/logpolicy" "tailscale.com/net/dns" + "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/net/tstun" "tailscale.com/safesocket" diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index 4fae64344..4adc6e654 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -24,12 +24,12 @@ import ( "time" "golang.org/x/crypto/ssh" - "inet.af/netaddr" "tailscale.com/control/controlclient" "tailscale.com/ipn" "tailscale.com/ipn/ipnlocal" "tailscale.com/ipn/ipnserver" "tailscale.com/ipn/store/mem" + "tailscale.com/net/netaddr" "tailscale.com/net/netns" "tailscale.com/net/tsdial" "tailscale.com/safesocket" @@ -175,7 +175,7 @@ func (i *jsIPN) run(jsCallbacks js.Value) { Self: jsNetMapSelfNode{ jsNetMapNode: jsNetMapNode{ Name: nm.Name, - Addresses: mapSlice(nm.Addresses, func(a netaddr.IPPrefix) string { return a.IP().String() }), + Addresses: mapSlice(nm.Addresses, func(a netaddr.IPPrefix) string { return a.Addr().String() }), NodeKey: nm.NodeKey.String(), MachineKey: nm.MachineKey.String(), }, @@ -185,7 +185,7 @@ func (i *jsIPN) run(jsCallbacks js.Value) { return jsNetMapPeerNode{ jsNetMapNode: jsNetMapNode{ Name: p.Name, - Addresses: mapSlice(p.Addresses, func(a netaddr.IPPrefix) string { return a.IP().String() }), + Addresses: mapSlice(p.Addresses, func(a netaddr.IPPrefix) string { return a.Addr().String() }), MachineKey: p.Machine.String(), NodeKey: p.Key.String(), }, diff --git a/cmd/viewer/tests/tests.go b/cmd/viewer/tests/tests.go index ec202ccde..0d3eb2bfd 100644 --- a/cmd/viewer/tests/tests.go +++ b/cmd/viewer/tests/tests.go @@ -8,7 +8,7 @@ package tests import ( "fmt" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) //go:generate go run tailscale.com/cmd/viewer --type=StructWithPtrs,StructWithoutPtrs,Map,StructWithSlices diff --git a/cmd/viewer/tests/tests_clone.go b/cmd/viewer/tests/tests_clone.go index 357fa20a5..0da1be798 100644 --- a/cmd/viewer/tests/tests_clone.go +++ b/cmd/viewer/tests/tests_clone.go @@ -7,7 +7,7 @@ package tests import ( - "inet.af/netaddr" + "net/netip" ) // Clone makes a deep copy of StructWithPtrs. @@ -50,7 +50,7 @@ func (src *StructWithoutPtrs) Clone() *StructWithoutPtrs { // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _StructWithoutPtrsCloneNeedsRegeneration = StructWithoutPtrs(struct { Int int - Pfx netaddr.IPPrefix + Pfx netip.Prefix }{}) // Clone makes a deep copy of Map. @@ -178,6 +178,6 @@ var _StructWithSlicesCloneNeedsRegeneration = StructWithSlices(struct { Structs []StructWithPtrs Ints []*int Slice []string - Prefixes []netaddr.IPPrefix + Prefixes []netip.Prefix Data []byte }{}) diff --git a/cmd/viewer/tests/tests_view.go b/cmd/viewer/tests/tests_view.go index 30d6b1af3..4d0cd8ce1 100644 --- a/cmd/viewer/tests/tests_view.go +++ b/cmd/viewer/tests/tests_view.go @@ -9,9 +9,9 @@ package tests import ( "encoding/json" "errors" + "net/netip" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/types/views" ) @@ -134,13 +134,13 @@ func (v *StructWithoutPtrsView) UnmarshalJSON(b []byte) error { return nil } -func (v StructWithoutPtrsView) Int() int { return v.ΠΆ.Int } -func (v StructWithoutPtrsView) Pfx() netaddr.IPPrefix { return v.ΠΆ.Pfx } +func (v StructWithoutPtrsView) Int() int { return v.ΠΆ.Int } +func (v StructWithoutPtrsView) Pfx() netip.Prefix { return v.ΠΆ.Pfx } // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _StructWithoutPtrsViewNeedsRegeneration = StructWithoutPtrs(struct { Int int - Pfx netaddr.IPPrefix + Pfx netip.Prefix }{}) // View returns a readonly view of Map. @@ -311,6 +311,6 @@ var _StructWithSlicesViewNeedsRegeneration = StructWithSlices(struct { Structs []StructWithPtrs Ints []*int Slice []string - Prefixes []netaddr.IPPrefix + Prefixes []netip.Prefix Data []byte }{}) diff --git a/cmd/viewer/viewer.go b/cmd/viewer/viewer.go index c9909453a..c63a16e2b 100644 --- a/cmd/viewer/viewer.go +++ b/cmd/viewer/viewer.go @@ -177,7 +177,7 @@ func genView(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, thi case "byte": it.Import("go4.org/mem") writeTemplate("byteSliceField") - case "inet.af/netaddr.IPPrefix": + case "inet.af/netaddr.IPPrefix", "net/netip.Prefix": it.Import("tailscale.com/types/views") writeTemplate("ipPrefixSliceField") default: diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index df950abbb..e0e8528f2 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -26,7 +26,6 @@ import ( "time" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/control/controlknobs" "tailscale.com/envknob" "tailscale.com/health" @@ -37,6 +36,7 @@ import ( "tailscale.com/net/dnscache" "tailscale.com/net/dnsfallback" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/netutil" "tailscale.com/net/tlsdial" "tailscale.com/net/tsdial" @@ -1408,7 +1408,7 @@ func (c *Direct) DoNoiseRequest(req *http.Request) (*http.Response, error) { // doPingerPing sends a Ping to pr.IP using pinger, and sends an http request back to // pr.URL with ping response data. func doPingerPing(logf logger.Logf, c *http.Client, pr *tailcfg.PingRequest, pinger Pinger, pingType tailcfg.PingType) { - if pr.URL == "" || pr.IP.IsZero() || pinger == nil { + if pr.URL == "" || !pr.IP.IsValid() || pinger == nil { logf("invalid ping request: missing url, ip or pinger") return } diff --git a/control/controlclient/direct_test.go b/control/controlclient/direct_test.go index e3cad0e1d..eef98e610 100644 --- a/control/controlclient/direct_test.go +++ b/control/controlclient/direct_test.go @@ -11,9 +11,9 @@ import ( "testing" "time" - "inet.af/netaddr" "tailscale.com/hostinfo" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/tailcfg" "tailscale.com/types/key" diff --git a/control/controlclient/map.go b/control/controlclient/map.go index 7533e6616..30e892e63 100644 --- a/control/controlclient/map.go +++ b/control/controlclient/map.go @@ -9,8 +9,8 @@ import ( "log" "sort" - "inet.af/netaddr" "tailscale.com/envknob" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/logger" @@ -309,7 +309,7 @@ func filterSelfAddresses(in []netaddr.IPPrefix) (ret []netaddr.IPPrefix) { return in case debugSelfIPv6Only: for _, a := range in { - if a.IP().Is6() { + if a.Addr().Is6() { ret = append(ret, a) } } diff --git a/derp/derp_client.go b/derp/derp_client.go index 2b612c8b2..518b7926c 100644 --- a/derp/derp_client.go +++ b/derp/derp_client.go @@ -17,7 +17,7 @@ import ( "go4.org/mem" "golang.org/x/time/rate" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/key" "tailscale.com/types/logger" ) diff --git a/derp/derp_server.go b/derp/derp_server.go index 16df37948..b217528be 100644 --- a/derp/derp_server.go +++ b/derp/derp_server.go @@ -36,11 +36,11 @@ import ( "go4.org/mem" "golang.org/x/sync/errgroup" "golang.org/x/time/rate" - "inet.af/netaddr" "tailscale.com/client/tailscale" "tailscale.com/disco" "tailscale.com/envknob" "tailscale.com/metrics" + "tailscale.com/net/netaddr" "tailscale.com/syncs" "tailscale.com/types/key" "tailscale.com/types/logger" diff --git a/derp/derphttp/derphttp_client.go b/derp/derphttp/derphttp_client.go index 376f55519..478bd66df 100644 --- a/derp/derphttp/derphttp_client.go +++ b/derp/derphttp/derphttp_client.go @@ -30,10 +30,10 @@ import ( "time" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/derp" "tailscale.com/envknob" "tailscale.com/net/dnscache" + "tailscale.com/net/netaddr" "tailscale.com/net/netns" "tailscale.com/net/tlsdial" "tailscale.com/net/tshttpproxy" diff --git a/disco/disco.go b/disco/disco.go index c46c83e18..270b169a3 100644 --- a/disco/disco.go +++ b/disco/disco.go @@ -26,7 +26,7 @@ import ( "net" "go4.org/mem" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/key" ) @@ -180,7 +180,7 @@ const epLength = 16 + 2 // 16 byte IP address + 2 byte port 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.Addr().As16() copy(p[:], a[:]) binary.BigEndian.PutUint16(p[16:], ipp.Port()) p = p[epLength:] @@ -219,7 +219,7 @@ const pongLen = 12 + 16 + 2 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.Addr().As16() d = d[copy(d, ip16[:]):] binary.BigEndian.PutUint16(d, m.Src.Port()) return ret diff --git a/disco/disco_test.go b/disco/disco_test.go index c1ec48af4..ec4275f7e 100644 --- a/disco/disco_test.go +++ b/disco/disco_test.go @@ -11,7 +11,7 @@ import ( "testing" "go4.org/mem" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/key" ) diff --git a/go.mod b/go.mod index 4caed6c66..d316f03d8 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,7 @@ require ( github.com/u-root/u-root v0.8.0 github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 go4.org/mem v0.0.0-20210711025021-927187094b94 + go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f golang.org/x/net v0.0.0-20220607020251-c690dde0001d golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f diff --git a/go.sum b/go.sum index 09aea7b23..cedf51792 100644 --- a/go.sum +++ b/go.sum @@ -1248,6 +1248,8 @@ go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3m go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA= go4.org/mem v0.0.0-20210711025021-927187094b94 h1:OAAkygi2Js191AJP1Ds42MhJRgeofeKGjuoUqNp1QC4= go4.org/mem v0.0.0-20210711025021-927187094b94/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= +go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf h1:IdwJUzqoIo5lkr2EOyKoe5qipUaEjbOKKY5+fzPBZ3A= +go4.org/netipx v0.0.0-20220725152314-7e7bdc8411bf/go.mod h1:+QXzaoURFd0rGDIjDNpyIkv+F9R7EmeKorvlKRnhqgA= go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= go4.org/unsafe/assume-no-moving-gc v0.0.0-20211027215541-db492cf91b37/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= diff --git a/ipn/handle.go b/ipn/handle.go index 35f4c041b..2080d5dfa 100644 --- a/ipn/handle.go +++ b/ipn/handle.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/logger" "tailscale.com/types/netmap" diff --git a/ipn/ipn_clone.go b/ipn/ipn_clone.go index 7058c37b1..ab64f1a18 100644 --- a/ipn/ipn_clone.go +++ b/ipn/ipn_clone.go @@ -7,7 +7,8 @@ package ipn import ( - "inet.af/netaddr" + "net/netip" + "tailscale.com/tailcfg" "tailscale.com/types/persist" "tailscale.com/types/preftype" @@ -36,7 +37,7 @@ var _PrefsCloneNeedsRegeneration = Prefs(struct { RouteAll bool AllowSingleHosts bool ExitNodeID tailcfg.StableNodeID - ExitNodeIP netaddr.IP + ExitNodeIP netip.Addr ExitNodeAllowLANAccess bool CorpDNS bool RunSSH bool @@ -47,7 +48,7 @@ var _PrefsCloneNeedsRegeneration = Prefs(struct { Hostname string NotepadURLs bool ForceDaemon bool - AdvertiseRoutes []netaddr.IPPrefix + AdvertiseRoutes []netip.Prefix NoSNAT bool NetfilterMode preftype.NetfilterMode OperatorUser string diff --git a/ipn/ipnlocal/dnsconfig_test.go b/ipn/ipnlocal/dnsconfig_test.go index 2a8cabfdf..967bca6ab 100644 --- a/ipn/ipnlocal/dnsconfig_test.go +++ b/ipn/ipnlocal/dnsconfig_test.go @@ -6,12 +6,13 @@ package ipnlocal import ( "encoding/json" + "net/netip" "reflect" "testing" - "inet.af/netaddr" "tailscale.com/ipn" "tailscale.com/net/dns" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstest" "tailscale.com/types/dnstype" @@ -23,7 +24,7 @@ import ( func ipps(ippStrs ...string) (ipps []netaddr.IPPrefix) { for _, s := range ippStrs { if ip, err := netaddr.ParseIP(s); err == nil { - ipps = append(ipps, netaddr.IPPrefixFrom(ip, ip.BitLen())) + ipps = append(ipps, netip.PrefixFrom(ip, ip.BitLen())) continue } ipps = append(ipps, netaddr.MustParseIPPrefix(s)) diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 84564efd0..788c1ad51 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -11,6 +11,7 @@ import ( "io" "net" "net/http" + "net/netip" "os" "os/user" "path/filepath" @@ -22,7 +23,7 @@ import ( "sync/atomic" "time" - "inet.af/netaddr" + "go4.org/netipx" "tailscale.com/client/tailscale/apitype" "tailscale.com/control/controlclient" "tailscale.com/envknob" @@ -33,6 +34,7 @@ import ( "tailscale.com/ipn/policy" "tailscale.com/net/dns" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/netutil" "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" @@ -231,7 +233,7 @@ func NewLocalBackend(logf logger.Logf, logid string, store ipn.StateStore, diale } // Default filter blocks everything and logs nothing, until Start() is called. - b.setFilter(filter.NewAllowNone(logf, &netaddr.IPSet{})) + b.setFilter(filter.NewAllowNone(logf, &netipx.IPSet{})) b.statusChanged = sync.NewCond(&b.statusLock) b.e.SetStatusCallback(b.setWgengineStatus) @@ -498,8 +500,8 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) { } var tailscaleIPs = make([]netaddr.IP, 0, len(p.Addresses)) for _, addr := range p.Addresses { - if addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.IP()) { - tailscaleIPs = append(tailscaleIPs, addr.IP()) + if addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.Addr()) { + tailscaleIPs = append(tailscaleIPs, addr.Addr()) } } exitNodeOption := tsaddr.PrefixesContainsFunc(p.AllowedIPs, func(r netaddr.IPPrefix) bool { @@ -543,7 +545,7 @@ 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.Addr()] if !ok { var ip netaddr.IP if ipp.Port() != 0 { @@ -580,9 +582,9 @@ func (b *LocalBackend) PeerCaps(src netaddr.IP) []string { if !a.IsSingleIP() { continue } - dstIP := a.IP() + dstIP := a.Addr() if dstIP.BitLen() == src.BitLen() { - return filt.AppendCaps(nil, src, a.IP()) + return filt.AppendCaps(nil, src, a.Addr()) } } return nil @@ -750,7 +752,7 @@ func (b *LocalBackend) findExitNodeIDLocked(nm *netmap.NetworkMap) (prefsChanged // If we have a desired IP on file, try to find the corresponding // node. - if b.prefs.ExitNodeIP.IsZero() { + if !b.prefs.ExitNodeIP.IsValid() { return false } @@ -762,7 +764,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.Addr() != b.prefs.ExitNodeIP { continue } // Found the node being referenced, upgrade prefs to @@ -1123,8 +1125,8 @@ func (b *LocalBackend) updateFilterLocked(netMap *netmap.NetworkMap, prefs *ipn. haveNetmap = netMap != nil addrs []netaddr.IPPrefix packetFilter []filter.Match - localNetsB netaddr.IPSetBuilder - logNetsB netaddr.IPSetBuilder + localNetsB netipx.IPSetBuilder + logNetsB netipx.IPSetBuilder shieldsUp = prefs == nil || prefs.ShieldsUp // Be conservative when not ready ) // Log traffic for Tailscale IPs. @@ -1241,9 +1243,9 @@ func internalAndExternalInterfaces() (internal, external []netaddr.IPPrefix, err func internalAndExternalInterfacesFrom(il interfaces.List, goos string) (internal, external []netaddr.IPPrefix, err error) { // We use an IPSetBuilder here to canonicalize the prefixes // and to remove any duplicate entries. - var internalBuilder, externalBuilder netaddr.IPSetBuilder + var internalBuilder, externalBuilder netipx.IPSetBuilder if err := il.ForeachInterfaceAddress(func(iface interfaces.Interface, pfx netaddr.IPPrefix) { - if tsaddr.IsTailscaleIP(pfx.IP()) { + if tsaddr.IsTailscaleIP(pfx.Addr()) { return } if pfx.IsSingleIP() { @@ -1284,16 +1286,16 @@ func internalAndExternalInterfacesFrom(il interfaces.List, goos string) (interna return iSet.Prefixes(), eSet.Prefixes(), nil } -func interfaceRoutes() (ips *netaddr.IPSet, hostIPs []netaddr.IP, err error) { - var b netaddr.IPSetBuilder +func interfaceRoutes() (ips *netipx.IPSet, hostIPs []netaddr.IP, err error) { + var b netipx.IPSetBuilder if err := interfaces.ForeachInterfaceAddress(func(_ interfaces.Interface, pfx netaddr.IPPrefix) { - if tsaddr.IsTailscaleIP(pfx.IP()) { + if tsaddr.IsTailscaleIP(pfx.Addr()) { return } if pfx.IsSingleIP() { return } - hostIPs = append(hostIPs, pfx.IP()) + hostIPs = append(hostIPs, pfx.Addr()) b.AddPrefix(pfx) }); err != nil { return nil, nil, err @@ -1306,8 +1308,8 @@ func interfaceRoutes() (ips *netaddr.IPSet, hostIPs []netaddr.IP, err error) { // shrinkDefaultRoute returns an IPSet representing the IPs in route, // minus those in removeFromDefaultRoute and localInterfaceRoutes, // plus the IPs in hostIPs. -func shrinkDefaultRoute(route netaddr.IPPrefix, localInterfaceRoutes *netaddr.IPSet, hostIPs []netaddr.IP) (*netaddr.IPSet, error) { - var b netaddr.IPSetBuilder +func shrinkDefaultRoute(route netaddr.IPPrefix, localInterfaceRoutes *netipx.IPSet, hostIPs []netaddr.IP) (*netipx.IPSet, error) { + var b netipx.IPSetBuilder // Add the default route. b.AddPrefix(route) // Remove the local interface routes. @@ -2089,7 +2091,7 @@ func (b *LocalBackend) ServePeerAPIConnection(remote, local netaddr.IPPort, c ne b.mu.Lock() defer b.mu.Unlock() for _, pln := range b.peerAPIListeners { - if pln.ip == local.IP() { + if pln.ip == local.Addr() { go pln.ServeConn(remote, c) return } @@ -2312,8 +2314,8 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Log var ips []netaddr.IP for _, addr := range addrs { if selfV6Only { - if addr.IP().Is6() { - ips = append(ips, addr.IP()) + if addr.Addr().Is6() { + ips = append(ips, addr.Addr()) } continue } @@ -2325,10 +2327,10 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Log // https://github.com/tailscale/tailscale/issues/1152 // tracks adding the right capability reporting to // enable AAAA in MagicDNS. - if addr.IP().Is6() && have4 { + if addr.Addr().Is6() && have4 { continue } - ips = append(ips, addr.IP()) + ips = append(ips, addr.Addr()) } dcfg.Hosts[fqdn] = ips } @@ -2520,7 +2522,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].Addr() { allSame = false break } @@ -2563,20 +2565,20 @@ 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.Addr(), b.prevIfState) if err != nil { if peerAPIListenAsync { // Expected. But we fix it later in linkChange // ("peerAPIListeners too low"). continue } - b.logf("[unexpected] peerapi listen(%q) error: %v", a.IP(), err) + b.logf("[unexpected] peerapi listen(%q) error: %v", a.Addr(), err) continue } } pln := &peerAPIListener{ ps: ps, - ip: a.IP(), + ip: a.Addr(), ln: ln, // nil for 2nd+ on netstack lb: b, } @@ -2585,7 +2587,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.Addr().String(), strconv.Itoa(pln.port)) b.logf("peerapi: serving on %s", pln.urlStr) go pln.serve() b.peerAPIListeners = append(b.peerAPIListeners, pln) @@ -2636,14 +2638,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.Addr().Is6() && aip.IsSingleIP() && tsULA.Contains(aip.Addr()) { if !didULA { didULA = true routes = append(routes, tsULA) } continue } - if aip.IsSingleIP() && cgNAT.Contains(aip.IP()) { + if aip.IsSingleIP() && cgNAT.Contains(aip.Addr()) { cgNATIPs = append(cgNATIPs, aip) } else { routes = append(routes, aip) @@ -2664,10 +2666,10 @@ func peerRoutes(peers []wgcfg.Peer, cgnatThreshold int) (routes []netaddr.IPPref } func ipPrefixLess(ri, rj netaddr.IPPrefix) bool { - if ri.IP() == rj.IP() { + if ri.Addr() == rj.Addr() { return ri.Bits() < rj.Bits() } - return ri.IP().Less(rj.IP()) + return ri.Addr().Less(rj.Addr()) } // routerConfig produces a router.Config from a wireguard config and IPN prefs. @@ -2695,7 +2697,7 @@ func (b *LocalBackend) routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs, oneCGNA // likely to break some functionality, but if the user expressed a // preference for routing remotely, we want to avoid leaking // traffic at the expense of functionality. - if prefs.ExitNodeID != "" || !prefs.ExitNodeIP.IsZero() { + if prefs.ExitNodeID != "" || prefs.ExitNodeIP.IsValid() { var default4, default6 bool for _, route := range rs.Routes { switch route { @@ -2741,7 +2743,7 @@ func (b *LocalBackend) routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs, oneCGNA } func unmapIPPrefix(ipp netaddr.IPPrefix) netaddr.IPPrefix { - return netaddr.IPPrefixFrom(ipp.IP().Unmap(), ipp.Bits()) + return netip.PrefixFrom(ipp.Addr().Unmap(), ipp.Bits()) } func unmapIPPrefixes(ippsList ...[]netaddr.IPPrefix) (ret []netaddr.IPPrefix) { @@ -2828,7 +2830,7 @@ func (b *LocalBackend) enterState(newState ipn.State) { case ipn.Running: var addrs []string for _, addr := range netMap.Addresses { - addrs = append(addrs, addr.IP().String()) + addrs = append(addrs, addr.Addr().String()) } systemd.Status("Connected; %s; %s", activeLogin, strings.Join(addrs, " ")) default: @@ -3114,7 +3116,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.Addr()] = n } } } @@ -3294,9 +3296,9 @@ func peerAPIBase(nm *netmap.NetworkMap, peer *tailcfg.Node) string { continue } switch { - case a.IP().Is4(): + case a.Addr().Is4(): have4 = true - case a.IP().Is6(): + case a.Addr().Is6(): have6 = true } } @@ -3318,7 +3320,7 @@ func peerAPIBase(nm *netmap.NetworkMap, peer *tailcfg.Node) string { case have6 && p6 != 0: ipp = netaddr.IPPortFrom(nodeIP(peer, netaddr.IP.Is6), p6) } - if ipp.IP().IsZero() { + if !ipp.Addr().IsValid() { return "" } return fmt.Sprintf("http://%v", ipp) @@ -3326,8 +3328,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.Addr()) { + return a.Addr() } } return netaddr.IP{} @@ -3369,9 +3371,9 @@ func (b *LocalBackend) OfferingExitNode() bool { if r.Bits() != 0 { continue } - if r.IP().Is4() { + if r.Addr().Is4() { def4 = true - } else if r.IP().Is6() { + } else if r.Addr().Is6() { def6 = true } } @@ -3543,7 +3545,7 @@ func (b *LocalBackend) handleQuad100Port80Conn(w http.ResponseWriter, r *http.Re } io.WriteString(w, "

Local addresses:

\n") } diff --git a/ipn/ipnlocal/local_test.go b/ipn/ipnlocal/local_test.go index 07b8c7ac8..c99a6fc68 100644 --- a/ipn/ipnlocal/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -12,10 +12,11 @@ import ( "testing" "time" - "inet.af/netaddr" + "go4.org/netipx" "tailscale.com/ipn" "tailscale.com/ipn/store/mem" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/logger" @@ -173,7 +174,7 @@ func TestShrinkDefaultRoute(t *testing.T) { out: []string{ "fe80::1", "ff00::1", - tsaddr.TailscaleULARange().IP().String(), + tsaddr.TailscaleULARange().Addr().String(), }, localIPFn: func(ip netaddr.IP) bool { return !inRemove(ip) && ip.Is6() }, }, @@ -182,7 +183,7 @@ func TestShrinkDefaultRoute(t *testing.T) { // Construct a fake local network environment to make this test hermetic. // localInterfaceRoutes and hostIPs would normally come from calling interfaceRoutes, // and localAddresses would normally come from calling interfaces.LocalAddresses. - var b netaddr.IPSetBuilder + var b netipx.IPSetBuilder for _, c := range []string{"127.0.0.0/8", "192.168.9.0/24", "fe80::/32"} { p := netaddr.MustParseIPPrefix(c) b.AddPrefix(p) @@ -561,7 +562,7 @@ func TestInternalAndExternalInterfaces(t *testing.T) { ip := interfaces.Interface{ Interface: &net.Interface{}, AltAddrs: []net.Addr{ - ippfx.IPNet(), + netipx.PrefixIPNet(ippfx), }, } if loopback { diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 0031ecc4c..909b8a6ae 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -31,7 +31,6 @@ import ( "github.com/kortschak/wol" "golang.org/x/net/dns/dnsmessage" - "inet.af/netaddr" "tailscale.com/client/tailscale/apitype" "tailscale.com/health" "tailscale.com/hostinfo" @@ -39,6 +38,7 @@ import ( "tailscale.com/logtail/backoff" "tailscale.com/net/dns/resolver" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/netutil" "tailscale.com/syncs" "tailscale.com/tailcfg" @@ -577,7 +577,7 @@ func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {

Hello, %s (%v)

This is my Tailscale device. Your device is %v. -`, html.EscapeString(who), h.remoteAddr.IP(), html.EscapeString(h.peerNode.ComputedName)) +`, html.EscapeString(who), h.remoteAddr.Addr(), html.EscapeString(h.peerNode.ComputedName)) if h.isSelf { fmt.Fprintf(w, "

You are the owner of this node.\n") @@ -693,7 +693,7 @@ func (h *peerAPIHandler) canWakeOnLAN() bool { } func (h *peerAPIHandler) peerHasCap(wantCap string) bool { - for _, hasCap := range h.ps.b.PeerCaps(h.remoteAddr.IP()) { + for _, hasCap := range h.ps.b.PeerCaps(h.remoteAddr.Addr()) { if hasCap == wantCap { return true } @@ -801,7 +801,7 @@ func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) { } d := time.Since(t0).Round(time.Second / 10) - h.logf("got put of %s in %v from %v/%v", approxSize(finalSize), d, h.remoteAddr.IP, h.peerNode.ComputedName) + h.logf("got put of %s in %v from %v/%v", approxSize(finalSize), d, h.remoteAddr.Addr(), h.peerNode.ComputedName) // TODO: set modtime // TODO: some real response @@ -925,12 +925,11 @@ func (h *peerAPIHandler) handleWakeOnLAN(w http.ResponseWriter, r *http.Request) } for ifName, ips := range st.InterfaceIPs { for _, ip := range ips { - if ip.IP().IsLoopback() || ip.IP().Is6() { + if ip.Addr().IsLoopback() || ip.Addr().Is6() { continue } - ipa := ip.IP().IPAddr() local := &net.UDPAddr{ - IP: ipa.IP, + IP: ip.Addr().AsSlice(), Port: 0, } remote := &net.UDPAddr{ @@ -982,7 +981,7 @@ func (h *peerAPIHandler) replyToDNSQueries() bool { // arbitrary. DNS runs over TCP and UDP, so sure... we check // TCP. dstIP := netaddr.IPv4(0, 0, 0, 0) - remoteIP := h.remoteAddr.IP() + remoteIP := h.remoteAddr.Addr() if remoteIP.Is6() { // autogroup:internet for IPv6 is defined to start with 2000::/3, // so use 2000::0 as the probe "the internet" address. @@ -1171,7 +1170,7 @@ func writePrettyDNSReply(w io.Writer, res []byte) (err error) { // See docs on fakePeerAPIListener. func newFakePeerAPIListener(ip netaddr.IP) net.Listener { return &fakePeerAPIListener{ - addr: netaddr.IPPortFrom(ip, 1).TCPAddr(), + addr: net.TCPAddrFromAddrPort(netaddr.IPPortFrom(ip, 1)), closed: make(chan struct{}), } } diff --git a/ipn/ipnlocal/peerapi_macios_ext.go b/ipn/ipnlocal/peerapi_macios_ext.go index ff1839a43..315df1e4f 100644 --- a/ipn/ipnlocal/peerapi_macios_ext.go +++ b/ipn/ipnlocal/peerapi_macios_ext.go @@ -12,8 +12,8 @@ import ( "fmt" "net" - "inet.af/netaddr" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/netns" ) diff --git a/ipn/ipnlocal/peerapi_test.go b/ipn/ipnlocal/peerapi_test.go index 11a889853..8f627b375 100644 --- a/ipn/ipnlocal/peerapi_test.go +++ b/ipn/ipnlocal/peerapi_test.go @@ -19,8 +19,9 @@ import ( "strings" "testing" - "inet.af/netaddr" + "go4.org/netipx" "tailscale.com/ipn" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstest" "tailscale.com/types/logger" @@ -607,7 +608,7 @@ func TestPeerAPIReplyToDNSQueries(t *testing.T) { t.Errorf("unexpectedly doing DNS without filter") } - h.ps.b.setFilter(filter.NewAllowNone(logger.Discard, new(netaddr.IPSet))) + h.ps.b.setFilter(filter.NewAllowNone(logger.Discard, new(netipx.IPSet))) if h.replyToDNSQueries() { t.Errorf("unexpectedly doing DNS without filter") } diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index a430f750f..609e056ce 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -29,7 +29,6 @@ import ( "time" "go4.org/mem" - "inet.af/netaddr" "inet.af/peercred" "tailscale.com/control/controlclient" "tailscale.com/envknob" @@ -37,6 +36,7 @@ import ( "tailscale.com/ipn/ipnlocal" "tailscale.com/ipn/localapi" "tailscale.com/logtail/backoff" + "tailscale.com/net/netaddr" "tailscale.com/net/netstat" "tailscale.com/net/netutil" "tailscale.com/net/tsdial" @@ -154,7 +154,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.Addr().IsLoopback() || !ra.Addr().IsLoopback() { return ci, errors.New("non-loopback connection") } tab, err := netstat.Get() @@ -1168,7 +1168,7 @@ func findTrueNASTaildropDir(name string) (dir string, err error) { // findQnapTaildropDir checks if a Shared Folder named "Taildrop" exists. func findQnapTaildropDir(name string) (string, error) { dir := fmt.Sprintf("/share/%s", name) - fi, err := os.Stat(dir) + fi, err := os.Stat(dir) if err != nil { return "", fmt.Errorf("shared folder %q not found", name) } @@ -1181,7 +1181,7 @@ func findQnapTaildropDir(name string) (string, error) { if err != nil { return "", fmt.Errorf("symlink to shared folder %q not found", name) } - if fi, err = os.Stat(fullpath); err == nil && fi.IsDir() { + if fi, err = os.Stat(fullpath); err == nil && fi.IsDir() { return dir, nil // return the symlink, how QNAP set it up } return "", fmt.Errorf("shared folder %q not found", name) diff --git a/ipn/ipnstate/ipnstate.go b/ipn/ipnstate/ipnstate.go index fb7babdf6..d2c6ff27e 100644 --- a/ipn/ipnstate/ipnstate.go +++ b/ipn/ipnstate/ipnstate.go @@ -17,7 +17,7 @@ import ( "sync" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/views" diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index 983770167..747688808 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -24,11 +24,11 @@ import ( "sync" "time" - "inet.af/netaddr" "tailscale.com/client/tailscale/apitype" "tailscale.com/ipn" "tailscale.com/ipn/ipnlocal" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/net/netutil" "tailscale.com/tailcfg" "tailscale.com/types/logger" @@ -242,7 +242,7 @@ func (h *Handler) serveWhoIs(w http.ResponseWriter, r *http.Request) { res := &apitype.WhoIsResponse{ Node: n, UserProfile: &u, - Caps: b.PeerCaps(ipp.IP()), + Caps: b.PeerCaps(ipp.Addr()), } j, err := json.MarshalIndent(res, "", "\t") if err != nil { diff --git a/ipn/prefs.go b/ipn/prefs.go index 46df9173b..a27a5008e 100644 --- a/ipn/prefs.go +++ b/ipn/prefs.go @@ -11,15 +11,16 @@ import ( "fmt" "io/ioutil" "log" + "net/netip" "os" "path/filepath" "reflect" "runtime" "strings" - "inet.af/netaddr" "tailscale.com/atomicfile" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/persist" @@ -308,7 +309,7 @@ func (p *Prefs) pretty(goos string) string { if p.ShieldsUp { sb.WriteString("shields=true ") } - if !p.ExitNodeIP.IsZero() { + if p.ExitNodeIP.IsValid() { fmt.Fprintf(&sb, "exit=%v lan=%t ", p.ExitNodeIP, p.ExitNodeAllowLANAccess) } else if !p.ExitNodeID.IsZero() { fmt.Fprintf(&sb, "exit=%v lan=%t ", p.ExitNodeID, p.ExitNodeAllowLANAccess) @@ -478,7 +479,7 @@ func (p *Prefs) SetAdvertiseExitNode(runExit bool) { } p.AdvertiseRoutes = append(p.AdvertiseRoutes, netaddr.IPPrefixFrom(netaddr.IPv4(0, 0, 0, 0), 0), - netaddr.IPPrefixFrom(netaddr.IPv6Unspecified(), 0)) + netaddr.IPPrefixFrom(netip.IPv6Unspecified(), 0)) } // peerWithTailscaleIP returns the peer in st with the provided diff --git a/ipn/prefs_test.go b/ipn/prefs_test.go index 1797d2c24..e333ca395 100644 --- a/ipn/prefs_test.go +++ b/ipn/prefs_test.go @@ -16,8 +16,8 @@ import ( "time" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstest" "tailscale.com/types/key" diff --git a/net/dns/config.go b/net/dns/config.go index d3046a82c..733e08c11 100644 --- a/net/dns/config.go +++ b/net/dns/config.go @@ -9,8 +9,8 @@ import ( "fmt" "sort" - "inet.af/netaddr" "tailscale.com/net/dns/resolver" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/types/dnstype" "tailscale.com/util/dnsname" diff --git a/net/dns/direct.go b/net/dns/direct.go index c63723a75..c32ce5688 100644 --- a/net/dns/direct.go +++ b/net/dns/direct.go @@ -20,8 +20,8 @@ import ( "strings" "time" - "inet.af/netaddr" "tailscale.com/net/dns/resolvconffile" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" "tailscale.com/util/dnsname" "tailscale.com/version/distro" diff --git a/net/dns/direct_test.go b/net/dns/direct_test.go index 93ce261aa..c6d6f0d3e 100644 --- a/net/dns/direct_test.go +++ b/net/dns/direct_test.go @@ -15,7 +15,7 @@ import ( "testing" qt "github.com/frankban/quicktest" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) diff --git a/net/dns/manager.go b/net/dns/manager.go index ac65e4bd8..1b99c3416 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -15,9 +15,9 @@ import ( "sync/atomic" "time" - "inet.af/netaddr" "tailscale.com/health" "tailscale.com/net/dns/resolver" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" @@ -242,7 +242,7 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig func toIPsOnly(resolvers []*dnstype.Resolver) (ret []netaddr.IP) { for _, r := range resolvers { if ipp, ok := r.IPPort(); ok && ipp.Port() == 53 { - ret = append(ret, ipp.IP()) + ret = append(ret, ipp.Addr()) } } return ret @@ -299,11 +299,11 @@ func (m *Manager) NextPacket() ([]byte, error) { var buf []byte switch { - case resp.to.IP().Is4(): + case resp.to.Addr().Is4(): h := packet.UDP4Header{ IP4Header: packet.IP4Header{ Src: magicDNSIP, - Dst: resp.to.IP(), + Dst: resp.to.Addr(), }, SrcPort: 53, DstPort: resp.to.Port(), @@ -312,11 +312,11 @@ func (m *Manager) NextPacket() ([]byte, error) { buf = make([]byte, offset+hlen+len(resp.pkt)) copy(buf[offset+hlen:], resp.pkt) h.Marshal(buf[offset:]) - case resp.to.IP().Is6(): + case resp.to.Addr().Is6(): h := packet.UDP6Header{ IP6Header: packet.IP6Header{ Src: magicDNSIPv6, - Dst: resp.to.IP(), + Dst: resp.to.Addr(), }, SrcPort: 53, DstPort: resp.to.Port(), diff --git a/net/dns/manager_linux.go b/net/dns/manager_linux.go index 5b91b4155..bbbb013b8 100644 --- a/net/dns/manager_linux.go +++ b/net/dns/manager_linux.go @@ -13,8 +13,8 @@ import ( "time" "github.com/godbus/dbus/v5" - "inet.af/netaddr" "tailscale.com/health" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" "tailscale.com/util/cmpver" ) diff --git a/net/dns/manager_tcp_test.go b/net/dns/manager_tcp_test.go index 26b969053..01ed32e02 100644 --- a/net/dns/manager_tcp_test.go +++ b/net/dns/manager_tcp_test.go @@ -12,7 +12,7 @@ import ( "github.com/google/go-cmp/cmp" dns "golang.org/x/net/dns/dnsmessage" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/util/dnsname" ) diff --git a/net/dns/manager_test.go b/net/dns/manager_test.go index 68e68a7db..999179b60 100644 --- a/net/dns/manager_test.go +++ b/net/dns/manager_test.go @@ -11,8 +11,8 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "inet.af/netaddr" "tailscale.com/net/dns/resolver" + "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/types/dnstype" "tailscale.com/util/dnsname" @@ -396,7 +396,7 @@ func TestManager(t *testing.T) { trIP := cmp.Transformer("ipStr", func(ip netaddr.IP) string { return ip.String() }) trIPPort := cmp.Transformer("ippStr", func(ipp netaddr.IPPort) string { if ipp.Port() == 53 { - return ipp.IP().String() + return ipp.Addr().String() } return ipp.String() }) diff --git a/net/dns/manager_windows.go b/net/dns/manager_windows.go index f740a11e0..4ac49901e 100644 --- a/net/dns/manager_windows.go +++ b/net/dns/manager_windows.go @@ -16,8 +16,8 @@ import ( "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" - "inet.af/netaddr" "tailscale.com/envknob" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" "tailscale.com/util/dnsname" ) diff --git a/net/dns/manager_windows_test.go b/net/dns/manager_windows_test.go index e2dfdf3e8..20c84f6b7 100644 --- a/net/dns/manager_windows_test.go +++ b/net/dns/manager_windows_test.go @@ -14,7 +14,7 @@ import ( "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" "tailscale.com/util/winutil" ) diff --git a/net/dns/nm.go b/net/dns/nm.go index bd989b176..b86a52ef2 100644 --- a/net/dns/nm.go +++ b/net/dns/nm.go @@ -14,8 +14,8 @@ import ( "time" "github.com/godbus/dbus/v5" - "inet.af/netaddr" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" "tailscale.com/util/endian" ) diff --git a/net/dns/osconfig.go b/net/dns/osconfig.go index 12bde1f31..b84ea5d72 100644 --- a/net/dns/osconfig.go +++ b/net/dns/osconfig.go @@ -7,7 +7,7 @@ package dns import ( "errors" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) diff --git a/net/dns/publicdns/publicdns.go b/net/dns/publicdns/publicdns.go index 77463cd71..cb7395dd4 100644 --- a/net/dns/publicdns/publicdns.go +++ b/net/dns/publicdns/publicdns.go @@ -9,7 +9,7 @@ package publicdns import ( "sync" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) var knownDoH = map[netaddr.IP]string{} // 8.8.8.8 => "https://..." diff --git a/net/dns/publicdns/publicdns_test.go b/net/dns/publicdns/publicdns_test.go index af07da55c..4d7dbd4a5 100644 --- a/net/dns/publicdns/publicdns_test.go +++ b/net/dns/publicdns/publicdns_test.go @@ -7,7 +7,7 @@ package publicdns import ( "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func TestInit(t *testing.T) { diff --git a/net/dns/resolvconffile/resolvconffile.go b/net/dns/resolvconffile/resolvconffile.go index 2b2bc3617..5c568cdaa 100644 --- a/net/dns/resolvconffile/resolvconffile.go +++ b/net/dns/resolvconffile/resolvconffile.go @@ -19,7 +19,7 @@ import ( "os" "strings" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) diff --git a/net/dns/resolvconffile/resolvconffile_test.go b/net/dns/resolvconffile/resolvconffile_test.go index c43f1677b..1e51b4a90 100644 --- a/net/dns/resolvconffile/resolvconffile_test.go +++ b/net/dns/resolvconffile/resolvconffile_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) diff --git a/net/dns/resolved.go b/net/dns/resolved.go index 5642cfd49..53a359f2c 100644 --- a/net/dns/resolved.go +++ b/net/dns/resolved.go @@ -15,11 +15,11 @@ import ( "strings" "time" - "tailscale.com/logtail/backoff" "github.com/godbus/dbus/v5" "golang.org/x/sys/unix" - "inet.af/netaddr" "tailscale.com/health" + "tailscale.com/logtail/backoff" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" "tailscale.com/util/dnsname" ) @@ -78,7 +78,7 @@ type resolvedLinkDomain struct { // changeRequest tracks latest OSConfig and related error responses to update. type changeRequest struct { config OSConfig // configs OSConfigs, one per each SetDNS call - res chan <- error // response channel + res chan<- error // response channel } // resolvedManager is an OSConfigurator which uses the systemd-resolved DBus API. @@ -139,8 +139,8 @@ func (m *resolvedManager) SetDNS(config OSConfig) error { func (m *resolvedManager) run(ctx context.Context) { var ( - conn *dbus.Conn - signals chan *dbus.Signal + conn *dbus.Conn + signals chan *dbus.Signal rManager dbus.BusObject // rManager is the Resolved DBus connection ) bo := backoff.NewBackoff("resolved-dbus", m.logf, 30*time.Second) diff --git a/net/dns/resolver/forwarder.go b/net/dns/resolver/forwarder.go index 0ee0751ba..56f7ee579 100644 --- a/net/dns/resolver/forwarder.go +++ b/net/dns/resolver/forwarder.go @@ -24,16 +24,17 @@ import ( "time" dns "golang.org/x/net/dns/dnsmessage" - "inet.af/netaddr" "tailscale.com/envknob" "tailscale.com/hostinfo" "tailscale.com/net/dns/publicdns" "tailscale.com/net/dnscache" + "tailscale.com/net/netaddr" "tailscale.com/net/neterror" "tailscale.com/net/netns" "tailscale.com/net/tsdial" "tailscale.com/types/dnstype" "tailscale.com/types/logger" + "tailscale.com/types/nettype" "tailscale.com/util/cloudenv" "tailscale.com/util/dnsname" "tailscale.com/wgengine/monitor" @@ -267,7 +268,7 @@ func resolversWithDelays(resolvers []*dnstype.Resolver) []resolverAndDelay { if !ok { continue } - dohBase, ok := publicdns.KnownDoH()[ipp.IP()] + dohBase, ok := publicdns.KnownDoH()[ipp.Addr()] if !ok || didDoH[dohBase] { continue } @@ -288,12 +289,12 @@ func resolversWithDelays(resolvers []*dnstype.Resolver) []resolverAndDelay { rr = append(rr, resolverAndDelay{name: r}) continue } - ip := ipp.IP() + ip := ipp.Addr() var startDelay time.Duration if host, ok := publicdns.KnownDoH()[ip]; ok { // We already did the DoH query early. These startDelay = dohHeadStart - key := hostAndFam{host, ip.BitLen()} + key := hostAndFam{host, uint8(ip.BitLen())} if done[key] > 0 { startDelay += wellKnownHostBackupDelay } @@ -364,13 +365,9 @@ func (f *forwarder) setRoutes(routesBySuffix map[dnsname.FQDN][]*dnstype.Resolve f.cloudHostFallback = cloudHostFallback } -var stdNetPacketListener packetListener = new(net.ListenConfig) +var stdNetPacketListener nettype.PacketListenerWithNetIP = nettype.MakePacketListenerWithNetIP(new(net.ListenConfig)) -type packetListener interface { - ListenPacket(ctx context.Context, network, address string) (net.PacketConn, error) -} - -func (f *forwarder) packetListener(ip netaddr.IP) (packetListener, error) { +func (f *forwarder) packetListener(ip netaddr.IP) (nettype.PacketListenerWithNetIP, error) { if f.linkSel == nil || initListenConfig == nil { return stdNetPacketListener, nil } @@ -382,7 +379,7 @@ func (f *forwarder) packetListener(ip netaddr.IP) (packetListener, error) { if err := initListenConfig(lc, f.linkMon, linkName); err != nil { return nil, err } - return lc, nil + return nettype.MakePacketListenerWithNetIP(lc), nil } // getKnownDoHClientForProvider returns an HTTP client for a specific DoH @@ -528,11 +525,17 @@ func (f *forwarder) sendUDP(ctx context.Context, fq *forwardQuery, rr resolverAn } metricDNSFwdUDP.Add(1) - ln, err := f.packetListener(ipp.IP()) + ln, err := f.packetListener(ipp.Addr()) if err != nil { return nil, err } - conn, err := ln.ListenPacket(ctx, "udp", ":0") + + // Specify the exact UDP family to work around https://github.com/golang/go/issues/52264 + udpFam := "udp4" + if ipp.Addr().Is6() { + udpFam = "udp6" + } + conn, err := ln.ListenPacket(ctx, udpFam, ":0") if err != nil { f.logf("ListenPacket failed: %v", err) return nil, err @@ -542,7 +545,7 @@ func (f *forwarder) sendUDP(ctx context.Context, fq *forwardQuery, rr resolverAn fq.closeOnCtxDone.Add(conn) defer fq.closeOnCtxDone.Remove(conn) - if _, err := conn.WriteTo(fq.packet, ipp.UDPAddr()); err != nil { + if _, err := conn.WriteToUDPAddrPort(fq.packet, ipp); err != nil { metricDNSFwdUDPErrorWrite.Add(1) if err := ctx.Err(); err != nil { return nil, err diff --git a/net/dns/resolver/tsdns.go b/net/dns/resolver/tsdns.go index 625493da6..cc91c4517 100644 --- a/net/dns/resolver/tsdns.go +++ b/net/dns/resolver/tsdns.go @@ -14,6 +14,7 @@ import ( "fmt" "io" "net" + "net/netip" "os" "runtime" "sort" @@ -24,8 +25,8 @@ import ( "time" dns "golang.org/x/net/dns/dnsmessage" - "inet.af/netaddr" "tailscale.com/net/dns/resolvconffile" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" "tailscale.com/types/dnstype" @@ -680,8 +681,8 @@ func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netaddr.IP } // MapVia will never error when given an ipv4 netaddr.IPPrefix. - out, _ := tsaddr.MapVia(uint32(prefix), netaddr.IPPrefixFrom(ip4, ip4.BitLen())) - return out.IP(), true + out, _ := tsaddr.MapVia(uint32(prefix), netip.PrefixFrom(ip4, ip4.BitLen())) + return out.Addr(), true } // resolveReverse returns the unique domain name that maps to the given address. diff --git a/net/dns/resolver/tsdns_server_test.go b/net/dns/resolver/tsdns_server_test.go index db8eeea67..ab0f6c2b0 100644 --- a/net/dns/resolver/tsdns_server_test.go +++ b/net/dns/resolver/tsdns_server_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/miekg/dns" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) // This file exists to isolate the test infrastructure @@ -41,7 +41,7 @@ func resolveToIP(ipv4, ipv6 netaddr.IP, ns string) dns.HandlerFunc { Rrtype: dns.TypeA, Class: dns.ClassINET, }, - A: ipv4.IPAddr().IP, + A: ipv4.AsSlice(), } case dns.TypeAAAA: ans = &dns.AAAA{ @@ -50,7 +50,7 @@ func resolveToIP(ipv4, ipv6 netaddr.IP, ns string) dns.HandlerFunc { Rrtype: dns.TypeAAAA, Class: dns.ClassINET, }, - AAAA: ipv6.IPAddr().IP, + AAAA: ipv6.AsSlice(), } case dns.TypeNS: ans = &dns.NS{ @@ -93,7 +93,7 @@ func resolveToIPLowercase(ipv4, ipv6 netaddr.IP, ns string) dns.HandlerFunc { Rrtype: dns.TypeA, Class: dns.ClassINET, }, - A: ipv4.IPAddr().IP, + A: ipv4.AsSlice(), } case dns.TypeAAAA: ans = &dns.AAAA{ @@ -102,7 +102,7 @@ func resolveToIPLowercase(ipv4, ipv6 netaddr.IP, ns string) dns.HandlerFunc { Rrtype: dns.TypeAAAA, Class: dns.ClassINET, }, - AAAA: ipv6.IPAddr().IP, + AAAA: ipv6.AsSlice(), } case dns.TypeNS: ans = &dns.NS{ @@ -244,7 +244,7 @@ func dnsHandler(answers ...any) dns.HandlerFunc { Rrtype: dns.TypeA, Class: dns.ClassINET, }, - A: ip.IPAddr().IP, + A: ip.AsSlice(), }) } else if ip.Is6() { m.Answer = append(m.Answer, &dns.AAAA{ @@ -253,7 +253,7 @@ func dnsHandler(answers ...any) dns.HandlerFunc { Rrtype: dns.TypeAAAA, Class: dns.ClassINET, }, - AAAA: ip.IPAddr().IP, + AAAA: ip.AsSlice(), }) } case dns.PTR: diff --git a/net/dns/resolver/tsdns_test.go b/net/dns/resolver/tsdns_test.go index 4ca528654..e97d6463e 100644 --- a/net/dns/resolver/tsdns_test.go +++ b/net/dns/resolver/tsdns_test.go @@ -23,7 +23,7 @@ import ( miekdns "github.com/miekg/dns" "golang.org/x/net/dns/dnsmessage" dns "golang.org/x/net/dns/dnsmessage" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/tstest" "tailscale.com/types/dnstype" diff --git a/net/dnscache/dnscache.go b/net/dnscache/dnscache.go index 37b48bc97..18031af3b 100644 --- a/net/dnscache/dnscache.go +++ b/net/dnscache/dnscache.go @@ -19,8 +19,8 @@ import ( "sync" "time" - "inet.af/netaddr" "tailscale.com/envknob" + "tailscale.com/net/netaddr" "tailscale.com/util/cloudenv" "tailscale.com/util/singleflight" ) @@ -153,7 +153,10 @@ func (r *Resolver) LookupIP(ctx context.Context, host string) (ip, v6 net.IP, al return nil, nil, nil, fmt.Errorf("dnscache: unexpected hostname %q doesn't match expected %q", host, r.SingleHost) } for _, naIP := range r.SingleHostStaticResult { - ipa := naIP.IPAddr() + ipa := &net.IPAddr{ + IP: naIP.AsSlice(), + Zone: naIP.Zone(), + } if ip == nil && naIP.Is4() { ip = ipa.IP } @@ -273,7 +276,10 @@ func (r *Resolver) lookupIP(host string) (ip, ip6 net.IP, allIPs []net.IPAddr, e if err == nil { ips = nil for _, fip := range fips { - ips = append(ips, *fip.IPAddr()) + ips = append(ips, net.IPAddr{ + IP: fip.AsSlice(), + Zone: fip.Zone(), + }) } } } diff --git a/net/dnscache/dnscache_test.go b/net/dnscache/dnscache_test.go index 6b005500d..c0cef4700 100644 --- a/net/dnscache/dnscache_test.go +++ b/net/dnscache/dnscache_test.go @@ -14,7 +14,7 @@ import ( "testing" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) var dialTest = flag.String("dial-test", "", "if non-empty, addr:port to test dial") diff --git a/net/dnsfallback/dns-fallback-servers.json b/net/dnsfallback/dns-fallback-servers.json index 584562765..6b8780147 100644 --- a/net/dnsfallback/dns-fallback-servers.json +++ b/net/dnsfallback/dns-fallback-servers.json @@ -90,18 +90,25 @@ "RegionName": "r2", "Nodes": [ { - "Name": "2a", + "Name": "2d", "RegionID": 2, - "HostName": "derp2.tailscale.com", - "IPv4": "167.172.206.31", - "IPv6": "2604:a880:2:d1::c5:7001" + "HostName": "derp2d.tailscale.com", + "IPv4": "192.73.252.65", + "IPv6": "2607:f740:0:3f::287" }, { - "Name": "2b", + "Name": "2e", "RegionID": 2, - "HostName": "derp2b.tailscale.com", - "IPv4": "64.227.106.23", - "IPv6": "2604:a880:4:1d0::29:9000" + "HostName": "derp2e.tailscale.com", + "IPv4": "192.73.252.134", + "IPv6": "2607:f740:0:3f::44c" + }, + { + "Name": "2f", + "RegionID": 2, + "HostName": "derp2f.tailscale.com", + "IPv4": "208.111.34.178", + "IPv6": "2607:f740:0:3f::f4" } ] }, diff --git a/net/dnsfallback/dnsfallback.go b/net/dnsfallback/dnsfallback.go index 8266be168..8ab3e04c7 100644 --- a/net/dnsfallback/dnsfallback.go +++ b/net/dnsfallback/dnsfallback.go @@ -21,7 +21,7 @@ import ( "net/url" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/netns" "tailscale.com/net/tlsdial" "tailscale.com/net/tshttpproxy" @@ -29,7 +29,7 @@ import ( ) func Lookup(ctx context.Context, host string) ([]netaddr.IP, error) { - if ip, err := netaddr.ParseIP(host); err == nil && !ip.IsZero() { + if ip, err := netaddr.ParseIP(host); err == nil && ip.IsValid() { return []netaddr.IP{ip}, nil } diff --git a/net/flowtrack/flowtrack.go b/net/flowtrack/flowtrack.go index 427b80099..61cde8738 100644 --- a/net/flowtrack/flowtrack.go +++ b/net/flowtrack/flowtrack.go @@ -14,7 +14,7 @@ import ( "container/list" "fmt" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) diff --git a/net/flowtrack/flowtrack_test.go b/net/flowtrack/flowtrack_test.go index 4f00a6973..cca43382c 100644 --- a/net/flowtrack/flowtrack_test.go +++ b/net/flowtrack/flowtrack_test.go @@ -7,7 +7,7 @@ package flowtrack import ( "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tstest" ) diff --git a/net/interfaces/interfaces.go b/net/interfaces/interfaces.go index d724af602..95054b026 100644 --- a/net/interfaces/interfaces.go +++ b/net/interfaces/interfaces.go @@ -14,8 +14,8 @@ import ( "sort" "strings" - "inet.af/netaddr" "tailscale.com/hostinfo" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/net/tshttpproxy" ) @@ -248,7 +248,7 @@ func (ifaces List) ForeachInterface(fn func(Interface, []netaddr.IPPrefix)) erro } } sort.Slice(pfxs, func(i, j int) bool { - return pfxs[i].IP().Less(pfxs[j].IP()) + return pfxs[i].Addr().Less(pfxs[j].Addr()) }) fn(iface, pfxs) } @@ -326,7 +326,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.Addr()) { continue } if needSpace { @@ -413,7 +413,7 @@ func filteredIPPs(ipps []netaddr.IPPrefix, useIP IPFilter) []netaddr.IPPrefix { // TODO: rewrite prefixesEqualFiltered to avoid making copies x := make([]netaddr.IPPrefix, 0, len(ipps)) for _, ipp := range ipps { - if useIP(ipp.IP()) { + if useIP(ipp.Addr()) { x = append(x, ipp) } } @@ -467,7 +467,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.Addr()) { return true } } @@ -507,11 +507,11 @@ func GetState() (*State, error) { return } for _, pfx := range pfxs { - if pfx.IP().IsLoopback() { + if pfx.Addr().IsLoopback() { continue } - s.HaveV6 = s.HaveV6 || isUsableV6(pfx.IP()) - s.HaveV4 = s.HaveV4 || isUsableV4(pfx.IP()) + s.HaveV6 = s.HaveV6 || isUsableV6(pfx.Addr()) + s.HaveV4 = s.HaveV4 || isUsableV4(pfx.Addr()) } }); err != nil { return nil, err @@ -556,7 +556,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.Addr() if ip.IsPrivate() { if privateIP == "" { privateIP = ip.String() @@ -593,8 +593,8 @@ func LikelyHomeRouterIP() (gateway, myIP netaddr.IP, ok bool) { return } ForeachInterfaceAddress(func(i Interface, pfx netaddr.IPPrefix) { - ip := pfx.IP() - if !i.IsUp() || ip.IsZero() || !myIP.IsZero() { + ip := pfx.Addr() + if !i.IsUp() || !ip.IsValid() || myIP.IsValid() { return } if gateway.IsPrivate() && ip.IsPrivate() { @@ -603,7 +603,7 @@ func LikelyHomeRouterIP() (gateway, myIP netaddr.IP, ok bool) { return } }) - return gateway, myIP, !myIP.IsZero() + return gateway, myIP, myIP.IsValid() } // isUsableV4 reports whether ip is a usable IPv4 address which could @@ -637,7 +637,7 @@ var ( // isInterestingIP. func anyInterestingIP(pfxs []netaddr.IPPrefix) bool { for _, pfx := range pfxs { - if isInterestingIP(pfx.IP()) { + if isInterestingIP(pfx.Addr()) { return true } } diff --git a/net/interfaces/interfaces_bsd.go b/net/interfaces/interfaces_bsd.go index 8f63f55bc..5e35ffbe9 100644 --- a/net/interfaces/interfaces_bsd.go +++ b/net/interfaces/interfaces_bsd.go @@ -19,7 +19,7 @@ import ( "golang.org/x/net/route" "golang.org/x/sys/unix" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func defaultRoute() (d DefaultRouteDetails, err error) { diff --git a/net/interfaces/interfaces_darwin.go b/net/interfaces/interfaces_darwin.go index f0fe1f5b5..5453e9e6a 100644 --- a/net/interfaces/interfaces_darwin.go +++ b/net/interfaces/interfaces_darwin.go @@ -13,7 +13,7 @@ import ( "golang.org/x/net/route" "golang.org/x/sys/unix" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func defaultRoute() (d DefaultRouteDetails, err error) { diff --git a/net/interfaces/interfaces_darwin_test.go b/net/interfaces/interfaces_darwin_test.go index 3a3903c00..959e21ab8 100644 --- a/net/interfaces/interfaces_darwin_test.go +++ b/net/interfaces/interfaces_darwin_test.go @@ -10,7 +10,7 @@ import ( "testing" "go4.org/mem" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/util/lineread" "tailscale.com/version" ) @@ -80,7 +80,7 @@ func likelyHomeRouterIPDarwinExec() (ret netaddr.IP, ok bool) { } return nil }) - return ret, !ret.IsZero() + return ret, ret.IsValid() } func TestFetchRoutingTable(t *testing.T) { diff --git a/net/interfaces/interfaces_linux.go b/net/interfaces/interfaces_linux.go index 2465fcfa2..750b3ea0e 100644 --- a/net/interfaces/interfaces_linux.go +++ b/net/interfaces/interfaces_linux.go @@ -21,7 +21,7 @@ import ( "github.com/mdlayher/netlink" "go4.org/mem" "golang.org/x/sys/unix" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/syncs" "tailscale.com/util/lineread" ) @@ -98,7 +98,7 @@ func likelyHomeRouterIPLinux() (ret netaddr.IP, ok bool) { } log.Printf("interfaces: failed to read /proc/net/route: %v", err) } - return ret, !ret.IsZero() + return ret, ret.IsValid() } // Android apps don't have permission to read /proc/net/route, at @@ -133,7 +133,7 @@ func likelyHomeRouterIPAndroid() (ret netaddr.IP, ok bool) { }) cmd.Process.Kill() cmd.Wait() - return ret, !ret.IsZero() + return ret, ret.IsValid() } func defaultRoute() (d DefaultRouteDetails, err error) { diff --git a/net/interfaces/interfaces_test.go b/net/interfaces/interfaces_test.go index e3afb669f..e262ebcdb 100644 --- a/net/interfaces/interfaces_test.go +++ b/net/interfaces/interfaces_test.go @@ -9,7 +9,7 @@ import ( "net" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func TestGetState(t *testing.T) { diff --git a/net/interfaces/interfaces_windows.go b/net/interfaces/interfaces_windows.go index 82d029060..3e82a87da 100644 --- a/net/interfaces/interfaces_windows.go +++ b/net/interfaces/interfaces_windows.go @@ -14,7 +14,7 @@ import ( "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tsconst" ) @@ -92,12 +92,12 @@ func likelyHomeRouterIPWindows() (ret netaddr.IP, ok bool) { } } - if !ret.IsZero() && !ret.IsPrivate() { + if ret.IsValid() && !ret.IsPrivate() { // Default route has a non-private gateway return netaddr.IP{}, false } - return ret, !ret.IsZero() + return ret, ret.IsValid() } // NonTailscaleMTUs returns a map of interface LUID to interface MTU, diff --git a/net/netaddr/netaddr.go b/net/netaddr/netaddr.go new file mode 100644 index 000000000..2c4f1174c --- /dev/null +++ b/net/netaddr/netaddr.go @@ -0,0 +1,135 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package netaddr is a transitional package while we finish migrating from inet.af/netaddr +// to Go 1.18's net/netip. +// +// TODO(bradfitz): delete this package eventually. Tracking bug is +// https://github.com/tailscale/tailscale/issues/5162 +package netaddr + +import ( + "math" + "net" + "net/netip" +) + +type ( + IP = netip.Addr + IPPort = netip.AddrPort + IPPrefix = netip.Prefix +) + +// IPv4 returns the IP of the IPv4 address a.b.c.d. +func IPv4(a, b, c, d uint8) IP { + return netip.AddrFrom4([4]byte{a, b, c, d}) +} + +// IPFrom16 returns the IP address given by the bytes in addr, unmapping any +// v6-mapped IPv4 address. +// +// It is equivalent to calling IPv6Raw(addr).Unmap(). +func IPFrom16(a [16]byte) IP { + return netip.AddrFrom16(a).Unmap() +} + +// IPv6Raw returns the IPv6 address given by the bytes in addr, without an +// implicit Unmap call to unmap any v6-mapped IPv4 address. +func IPv6Raw(a [16]byte) IP { + return netip.AddrFrom16(a) // no implicit unmapping +} + +// IPFrom4 returns the IPv4 address given by the bytes in addr. It is equivalent +// to calling IPv4(addr[0], addr[1], addr[2], addr[3]). +func IPFrom4(a [4]byte) IP { + return netip.AddrFrom4(a) +} + +// IPPrefixFrom returns an IPPrefix with IP ip and provided bits prefix length. +// It does not allocate. +func IPPrefixFrom(ip IP, bits uint8) IPPrefix { + return netip.PrefixFrom(ip, int(bits)) +} + +// IPPortFrom returns an IPPort with IP ip and port port. It does not allocate. +func IPPortFrom(ip IP, port uint16) IPPort { + return netip.AddrPortFrom(ip, port) +} + +// FromStdIPRaw returns an IP from the standard library's IP type. +// If std is invalid, ok is false. +// Unlike FromStdIP, FromStdIPRaw does not do an implicit Unmap if +// len(std) == 16 and contains an IPv6-mapped IPv4 address. +func FromStdIPRaw(std net.IP) (ip IP, ok bool) { + return netip.AddrFromSlice(std) +} + +// FromStdIP returns an IP from the standard library's IP type. +// +// If std is invalid, ok is false. +// +// FromStdIP implicitly unmaps IPv6-mapped IPv4 addresses. That is, if +// len(std) == 16 and contains an IPv4 address, only the IPv4 part is +// returned, without the IPv6 wrapper. This is the common form returned by +// the standard library's ParseIP: https://play.golang.org/p/qdjylUkKWxl. +// To convert a standard library IP without the implicit unmapping, use +// FromStdIPRaw. +func FromStdIP(std net.IP) (ip IP, ok bool) { + ret, ok := FromStdIPRaw(std) + if !ok { + return ret, false + } + if ret.Is4In6() { + return ret.Unmap(), true + } + return ret, true +} + +// FromStdIPNet returns an IPPrefix from the standard library's IPNet type. +// If std is invalid, ok is false. +func FromStdIPNet(std *net.IPNet) (prefix IPPrefix, ok bool) { + ip, ok := FromStdIP(std.IP) + if !ok { + return IPPrefix{}, false + } + + if l := len(std.Mask); l != net.IPv4len && l != net.IPv6len { + // Invalid mask. + return IPPrefix{}, false + } + + ones, bits := std.Mask.Size() + if ones == 0 && bits == 0 { + // IPPrefix does not support non-contiguous masks. + return IPPrefix{}, false + } + + 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) (_ IPPort, ok bool) { + ip, ok := FromStdIP(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 +} + +func ParseIP(s string) (IP, error) { return netip.ParseAddr(s) } +func ParseIPPrefix(s string) (IPPrefix, error) { return netip.ParsePrefix(s) } +func ParseIPPort(s string) (IPPort, error) { return netip.ParseAddrPort(s) } + +func MustParseIP(s string) IP { return netip.MustParseAddr(s) } +func MustParseIPPrefix(s string) IPPrefix { return netip.MustParsePrefix(s) } +func MustParseIPPort(s string) IPPort { return netip.MustParseAddrPort(s) } diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index 535cb39dd..257d324e0 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -16,16 +16,17 @@ import ( "log" "net" "net/http" + "net/netip" "runtime" "sort" "sync" "time" "github.com/tcnksm/go-httpstat" - "inet.af/netaddr" "tailscale.com/derp/derphttp" "tailscale.com/envknob" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/neterror" "tailscale.com/net/netns" "tailscale.com/net/portmapper" @@ -33,6 +34,7 @@ import ( "tailscale.com/syncs" "tailscale.com/tailcfg" "tailscale.com/types/logger" + "tailscale.com/types/nettype" "tailscale.com/types/opt" "tailscale.com/util/clientmetric" ) @@ -179,6 +181,7 @@ type Client struct { // STUNConn is the interface required by the netcheck Client when // reusing an existing UDP connection. type STUNConn interface { + WriteToUDPAddrPort([]byte, netip.AddrPort) (int, error) WriteTo([]byte, net.Addr) (int, error) ReadFrom([]byte) (int, net.Addr, error) } @@ -234,9 +237,9 @@ func (c *Client) MakeNextReportFull() { func (c *Client) ReceiveSTUNPacket(pkt []byte, src netaddr.IPPort) { c.vlogf("received STUN packet from %s", src) - if src.IP().Is4() { + if src.Addr().Is4() { metricSTUNRecv4.Add(1) - } else if src.IP().Is6() { + } else if src.Addr().Is6() { metricSTUNRecv6.Add(1) } @@ -527,7 +530,7 @@ type reportState struct { hairTimeout chan struct{} // closed on timeout pc4 STUNConn pc6 STUNConn - pc4Hair net.PacketConn + pc4Hair nettype.PacketConn incremental bool // doing a lite, follow-up netcheck stopProbeCh chan struct{} waitPortMap sync.WaitGroup @@ -592,9 +595,8 @@ func (rs *reportState) startHairCheckLocked(dst netaddr.IPPort) { return } rs.sentHairCheck = true - ua := dst.UDPAddr() - rs.pc4Hair.WriteTo(stun.Request(rs.hairTX), ua) - rs.c.vlogf("sent haircheck to %v", ua) + rs.pc4Hair.WriteToUDPAddrPort(stun.Request(rs.hairTX), dst) + rs.c.vlogf("sent haircheck to %v", dst) time.AfterFunc(hairpinCheckTimeout, func() { close(rs.hairTimeout) }) } @@ -643,7 +645,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.Addr().String(), fmt.Sprint(ipp.Port())) } rs.mu.Lock() @@ -668,13 +670,13 @@ func (rs *reportState) addNodeLatency(node *tailcfg.DERPNode, ipp netaddr.IPPort } switch { - case ipp.IP().Is6(): + case ipp.Addr().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.Addr().Is4(): updateLatency(ret.RegionV4Latency, node.RegionID, d) ret.IPv4 = true if rs.gotEP4 == "" { @@ -809,14 +811,14 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, // See if IPv6 works at all, or if it's been hard disabled at the // OS level. - v6udp, err := netns.Listener(c.logf).ListenPacket(ctx, "udp6", "[::1]:0") + v6udp, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, "udp6", "[::1]:0") if err == nil { rs.report.OSHasIPv6 = true v6udp.Close() } // Create a UDP4 socket used for sending to our discovered IPv4 address. - rs.pc4Hair, err = netns.Listener(c.logf).ListenPacket(ctx, "udp4", ":0") + rs.pc4Hair, err = nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, "udp4", ":0") if err != nil { c.logf("udp4: %v", err) return nil, err @@ -844,7 +846,7 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, if f := c.GetSTUNConn4; f != nil { rs.pc4 = f() } else { - u4, err := netns.Listener(c.logf).ListenPacket(ctx, "udp4", c.udpBindAddr()) + u4, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, "udp4", c.udpBindAddr()) if err != nil { c.logf("udp4: %v", err) return nil, err @@ -857,7 +859,7 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, if f := c.GetSTUNConn6; f != nil { rs.pc6 = f() } else { - u6, err := netns.Listener(c.logf).ListenPacket(ctx, "udp6", c.udpBindAddr()) + u6, err := nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, "udp6", c.udpBindAddr()) if err != nil { c.logf("udp6: %v", err) } else { @@ -1238,7 +1240,7 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe } addr := c.nodeAddr(ctx, node, probe.proto) - if addr == nil { + if !addr.IsValid() { return } @@ -1257,7 +1259,7 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe switch probe.proto { case probeIPv4: metricSTUNSend4.Add(1) - n, err := rs.pc4.WriteTo(req, addr) + n, err := rs.pc4.WriteToUDPAddrPort(req, addr) if n == len(req) && err == nil || neterror.TreatAsLostUDP(err) { rs.mu.Lock() rs.report.IPv4CanSend = true @@ -1265,7 +1267,7 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe } case probeIPv6: metricSTUNSend6.Add(1) - n, err := rs.pc6.WriteTo(req, addr) + n, err := rs.pc6.WriteToUDPAddrPort(req, addr) if n == len(req) && err == nil || neterror.TreatAsLostUDP(err) { rs.mu.Lock() rs.report.IPv6CanSend = true @@ -1279,26 +1281,26 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe // proto is 4 or 6 // If it returns nil, the node is skipped. -func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeProto) *net.UDPAddr { +func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeProto) (ap netip.AddrPort) { port := n.STUNPort if port == 0 { port = 3478 } if port < 0 || port > 1<<16-1 { - return nil + return } if n.STUNTestIP != "" { ip, err := netaddr.ParseIP(n.STUNTestIP) if err != nil { - return nil + return } if proto == probeIPv4 && ip.Is6() { - return nil + return } if proto == probeIPv6 && ip.Is4() { - return nil + return } - return netaddr.IPPortFrom(ip, uint16(port)).UDPAddr() + return netip.AddrPortFrom(ip, uint16(port)) } switch proto { @@ -1306,30 +1308,31 @@ func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeP if n.IPv4 != "" { ip, _ := netaddr.ParseIP(n.IPv4) if !ip.Is4() { - return nil + return } - return netaddr.IPPortFrom(ip, uint16(port)).UDPAddr() + return netip.AddrPortFrom(ip, uint16(port)) } case probeIPv6: if n.IPv6 != "" { ip, _ := netaddr.ParseIP(n.IPv6) if !ip.Is6() { - return nil + return } - return netaddr.IPPortFrom(ip, uint16(port)).UDPAddr() + return netip.AddrPortFrom(ip, uint16(port)) } default: - return nil + return } // TODO(bradfitz): add singleflight+dnscache here. addrs, _ := net.DefaultResolver.LookupIPAddr(ctx, n.HostName) for _, a := range addrs { if (a.IP.To4() != nil) == (proto == probeIPv4) { - return &net.UDPAddr{IP: a.IP, Port: port} + na, _ := netaddr.FromStdIP(a.IP.To4()) + return netip.AddrPortFrom(na, uint16(port)) } } - return nil + return } func regionHasDERPNode(r *tailcfg.DERPRegion) bool { diff --git a/net/netcheck/netcheck_test.go b/net/netcheck/netcheck_test.go index a6c843af7..ebb513240 100644 --- a/net/netcheck/netcheck_test.go +++ b/net/netcheck/netcheck_test.go @@ -16,8 +16,8 @@ import ( "testing" "time" - "inet.af/netaddr" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/stun" "tailscale.com/net/stun/stuntest" "tailscale.com/tailcfg" diff --git a/net/netns/netns.go b/net/netns/netns.go index bdcf97089..e0c6274d8 100644 --- a/net/netns/netns.go +++ b/net/netns/netns.go @@ -18,7 +18,7 @@ import ( "context" "net" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/netknob" "tailscale.com/syncs" "tailscale.com/types/logger" diff --git a/net/netstat/netstat.go b/net/netstat/netstat.go index 3aef7ea1e..aa969d8ba 100644 --- a/net/netstat/netstat.go +++ b/net/netstat/netstat.go @@ -9,7 +9,7 @@ import ( "errors" "runtime" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) var ErrNotImplemented = errors.New("not implemented for GOOS=" + runtime.GOOS) diff --git a/net/netstat/netstat_windows.go b/net/netstat/netstat_windows.go index a3b2d7673..b2979e65f 100644 --- a/net/netstat/netstat_windows.go +++ b/net/netstat/netstat_windows.go @@ -13,7 +13,7 @@ import ( "unsafe" "golang.org/x/sys/windows" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/util/endian" ) diff --git a/net/netutil/ip_forward.go b/net/netutil/ip_forward.go index 03f791a86..c42f2b240 100644 --- a/net/netutil/ip_forward.go +++ b/net/netutil/ip_forward.go @@ -15,8 +15,8 @@ import ( "strconv" "strings" - "inet.af/netaddr" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" ) // protocolsRequiredForForwarding reports whether IPv4 and/or IPv6 protocols are @@ -31,7 +31,7 @@ func protocolsRequiredForForwarding(routes []netaddr.IPPrefix, state *interfaces localIPs := make(map[netaddr.IP]bool) for _, addrs := range state.InterfaceIPs { for _, pfx := range addrs { - localIPs[pfx.IP()] = true + localIPs[pfx.Addr()] = true } } @@ -39,10 +39,10 @@ func protocolsRequiredForForwarding(routes []netaddr.IPPrefix, state *interfaces // 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.Addr()] { continue } - if r.IP().Is4() { + if r.Addr().Is4() { v4 = true } else { v6 = true diff --git a/net/packet/icmp6_test.go b/net/packet/icmp6_test.go index 203da02db..378b9760c 100644 --- a/net/packet/icmp6_test.go +++ b/net/packet/icmp6_test.go @@ -7,7 +7,7 @@ package packet import ( "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) diff --git a/net/packet/ip4.go b/net/packet/ip4.go index 2c090d9f1..21941d733 100644 --- a/net/packet/ip4.go +++ b/net/packet/ip4.go @@ -8,7 +8,7 @@ import ( "encoding/binary" "errors" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) diff --git a/net/packet/ip6.go b/net/packet/ip6.go index 374e9459b..4f30aea3c 100644 --- a/net/packet/ip6.go +++ b/net/packet/ip6.go @@ -7,7 +7,7 @@ package packet import ( "encoding/binary" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) diff --git a/net/packet/packet.go b/net/packet/packet.go index 48633b89d..79e5b7412 100644 --- a/net/packet/packet.go +++ b/net/packet/packet.go @@ -8,9 +8,10 @@ import ( "encoding/binary" "fmt" "net" + "net/netip" "strings" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) @@ -126,8 +127,8 @@ func (q *Parsed) decode4(b []byte) { } // If it's valid IPv4, then the IP addresses are valid - 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.Src = withIP(q.Src, netaddr.IPv4(b[12], b[13], b[14], b[15])) + q.Dst = withIP(q.Dst, netaddr.IPv4(b[16], b[17], b[18], b[19])) q.subofs = int((b[0] & 0x0F) << 2) if q.subofs > q.length { @@ -169,8 +170,8 @@ func (q *Parsed) decode4(b []byte) { q.IPProto = unknown return } - q.Src = q.Src.WithPort(0) - q.Dst = q.Dst.WithPort(0) + q.Src = withPort(q.Src, 0) + q.Dst = withPort(q.Dst, 0) q.dataofs = q.subofs + icmp4HeaderLength return case ipproto.IGMP: @@ -182,8 +183,8 @@ func (q *Parsed) decode4(b []byte) { q.IPProto = unknown return } - q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) - q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) + q.Src = withPort(q.Src, binary.BigEndian.Uint16(sub[0:2])) + q.Dst = withPort(q.Dst, binary.BigEndian.Uint16(sub[2:4])) q.TCPFlags = TCPFlag(sub[13]) headerLength := (sub[12] & 0xF0) >> 2 q.dataofs = q.subofs + int(headerLength) @@ -193,8 +194,8 @@ func (q *Parsed) decode4(b []byte) { q.IPProto = unknown return } - q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) - q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) + q.Src = withPort(q.Src, binary.BigEndian.Uint16(sub[0:2])) + q.Dst = withPort(q.Dst, binary.BigEndian.Uint16(sub[2:4])) q.dataofs = q.subofs + udpHeaderLength return case ipproto.SCTP: @@ -202,8 +203,8 @@ func (q *Parsed) decode4(b []byte) { q.IPProto = unknown return } - q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) - q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) + q.Src = withPort(q.Src, binary.BigEndian.Uint16(sub[0:2])) + q.Dst = withPort(q.Dst, binary.BigEndian.Uint16(sub[2:4])) return case ipproto.TSMP: // Inter-tailscale messages. @@ -251,8 +252,8 @@ func (q *Parsed) decode6(b []byte) { // always well-formed stdlib IPs. 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) + q.Src = withIP(q.Src, srcIP) + q.Dst = withIP(q.Dst, dstIP) // We don't support any IPv6 extension headers. Don't try to // be clever. Therefore, the IP subprotocol always starts at @@ -276,16 +277,16 @@ func (q *Parsed) decode6(b []byte) { q.IPProto = unknown return } - q.Src = q.Src.WithPort(0) - q.Dst = q.Dst.WithPort(0) + q.Src = withPort(q.Src, 0) + q.Dst = withPort(q.Dst, 0) q.dataofs = q.subofs + icmp6HeaderLength case ipproto.TCP: if len(sub) < tcpHeaderLength { q.IPProto = unknown return } - q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) - q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) + q.Src = withPort(q.Src, binary.BigEndian.Uint16(sub[0:2])) + q.Dst = withPort(q.Dst, binary.BigEndian.Uint16(sub[2:4])) q.TCPFlags = TCPFlag(sub[13]) headerLength := (sub[12] & 0xF0) >> 2 q.dataofs = q.subofs + int(headerLength) @@ -295,16 +296,16 @@ func (q *Parsed) decode6(b []byte) { q.IPProto = unknown return } - q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) - q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) + q.Src = withPort(q.Src, binary.BigEndian.Uint16(sub[0:2])) + q.Dst = withPort(q.Dst, binary.BigEndian.Uint16(sub[2:4])) q.dataofs = q.subofs + udpHeaderLength case ipproto.SCTP: if len(sub) < sctpHeaderLength { q.IPProto = unknown return } - q.Src = q.Src.WithPort(binary.BigEndian.Uint16(sub[0:2])) - q.Dst = q.Dst.WithPort(binary.BigEndian.Uint16(sub[2:4])) + q.Src = withPort(q.Src, binary.BigEndian.Uint16(sub[0:2])) + q.Dst = withPort(q.Dst, binary.BigEndian.Uint16(sub[2:4])) return case ipproto.TSMP: // Inter-tailscale messages. @@ -324,8 +325,8 @@ func (q *Parsed) IP4Header() IP4Header { return IP4Header{ IPID: ipid, IPProto: q.IPProto, - Src: q.Src.IP(), - Dst: q.Dst.IP(), + Src: q.Src.Addr(), + Dst: q.Dst.Addr(), } } @@ -337,8 +338,8 @@ func (q *Parsed) IP6Header() IP6Header { return IP6Header{ IPID: ipid, IPProto: q.IPProto, - Src: q.Src.IP(), - Dst: q.Dst.IP(), + Src: q.Src.Addr(), + Dst: q.Dst.Addr(), } } @@ -488,3 +489,11 @@ func Hexdump(b []byte) string { } return out.String() } + +func withIP(ap netip.AddrPort, ip netip.Addr) netip.AddrPort { + return netip.AddrPortFrom(ip, ap.Port()) +} + +func withPort(ap netip.AddrPort, port uint16) netip.AddrPort { + return netip.AddrPortFrom(ap.Addr(), port) +} diff --git a/net/packet/packet_test.go b/net/packet/packet_test.go index c39abc3fb..00438f9b5 100644 --- a/net/packet/packet_test.go +++ b/net/packet/packet_test.go @@ -9,7 +9,7 @@ import ( "reflect" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/types/ipproto" ) diff --git a/net/packet/tsmp.go b/net/packet/tsmp.go index 0fb6dfb89..7f116c618 100644 --- a/net/packet/tsmp.go +++ b/net/packet/tsmp.go @@ -15,8 +15,8 @@ import ( "errors" "fmt" - "inet.af/netaddr" "tailscale.com/net/flowtrack" + "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) @@ -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.Addr().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.Addr().Is6() { iph := IP6Header{ IPProto: ipproto.TSMP, Src: h.IPSrc, @@ -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.IPPortFrom(pp.Dst.IP(), binary.BigEndian.Uint16(p[3:5])), - Dst: netaddr.IPPortFrom(pp.Src.IP(), binary.BigEndian.Uint16(p[5:7])), + IPSrc: pp.Src.Addr(), + IPDst: pp.Dst.Addr(), + Src: netaddr.IPPortFrom(pp.Dst.Addr(), binary.BigEndian.Uint16(p[3:5])), + Dst: netaddr.IPPortFrom(pp.Src.Addr(), binary.BigEndian.Uint16(p[5:7])), } if len(p) > 7 { flags := p[7] diff --git a/net/packet/tsmp_test.go b/net/packet/tsmp_test.go index d4a0cf1a0..1cb11e9ac 100644 --- a/net/packet/tsmp_test.go +++ b/net/packet/tsmp_test.go @@ -7,7 +7,7 @@ package packet import ( "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func TestTailscaleRejectedHeader(t *testing.T) { diff --git a/net/portmapper/disabled_stubs.go b/net/portmapper/disabled_stubs.go index 4a288473d..67e250a3b 100644 --- a/net/portmapper/disabled_stubs.go +++ b/net/portmapper/disabled_stubs.go @@ -10,7 +10,7 @@ package portmapper import ( "context" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) type upnpClient any diff --git a/net/portmapper/igd_test.go b/net/portmapper/igd_test.go index d3f8e5f3e..f7516eb28 100644 --- a/net/portmapper/igd_test.go +++ b/net/portmapper/igd_test.go @@ -13,7 +13,7 @@ import ( "sync" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/syncs" "tailscale.com/types/logger" ) @@ -214,10 +214,10 @@ func (d *TestIGD) handlePCPQuery(pkt []byte, src netaddr.IPPort) { pktSrcBytes := [16]byte{} copy(pktSrcBytes[:], pkt[8:24]) pktSrc := netaddr.IPFrom16(pktSrcBytes) - if pktSrc != src.IP() { + if pktSrc != src.Addr() { // TODO this error isn't fatal but should be rejected by server. // Since it's a test it's difficult to get them the same though. - d.logf("mismatch of packet source and source IP: got %v, expected %v", pktSrc, src.IP()) + d.logf("mismatch of packet source and source IP: got %v, expected %v", pktSrc, src.Addr()) } switch op { case pcpOpAnnounce: @@ -226,7 +226,7 @@ func (d *TestIGD) handlePCPQuery(pkt []byte, src netaddr.IPPort) { return } resp := buildPCPDiscoResponse(pkt) - if _, err := d.pxpConn.WriteTo(resp, src.UDPAddr()); err != nil { + if _, err := d.pxpConn.WriteTo(resp, net.UDPAddrFromAddrPort(src)); err != nil { d.inc(&d.counters.numFailedWrites) } case pcpOpMap: @@ -240,7 +240,7 @@ func (d *TestIGD) handlePCPQuery(pkt []byte, src netaddr.IPPort) { return } resp := buildPCPMapResponse(pkt) - d.pxpConn.WriteTo(resp, src.UDPAddr()) + d.pxpConn.WriteTo(resp, net.UDPAddrFromAddrPort(src)) default: // unknown op code, ignore it for now. d.inc(&d.counters.numPCPOtherRecv) diff --git a/net/portmapper/pcp.go b/net/portmapper/pcp.go index 66b93845c..db5848c36 100644 --- a/net/portmapper/pcp.go +++ b/net/portmapper/pcp.go @@ -11,7 +11,7 @@ import ( "fmt" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) // References: @@ -69,8 +69,8 @@ func (p *pcpMapping) Release(ctx context.Context) { return } defer uc.Close() - pkt := buildPCPRequestMappingPacket(p.internal.IP(), p.internal.Port(), p.external.Port(), 0, p.external.IP()) - uc.WriteTo(pkt, p.gw.UDPAddr()) + pkt := buildPCPRequestMappingPacket(p.internal.Addr(), p.internal.Port(), p.external.Port(), 0, p.external.Addr()) + uc.WriteToUDPAddrPort(pkt, p.gw) } // buildPCPRequestMappingPacket generates a PCP packet with a MAP opcode. diff --git a/net/portmapper/pcp_test.go b/net/portmapper/pcp_test.go index f696795d9..8389656a4 100644 --- a/net/portmapper/pcp_test.go +++ b/net/portmapper/pcp_test.go @@ -8,7 +8,7 @@ import ( "encoding/binary" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) var examplePCPMapResponse = []byte{2, 129, 0, 0, 0, 0, 28, 32, 0, 2, 155, 237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 112, 9, 24, 241, 208, 251, 45, 157, 76, 10, 188, 17, 0, 0, 0, 4, 210, 4, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 135, 180, 175, 246} diff --git a/net/portmapper/portmapper.go b/net/portmapper/portmapper.go index 9c84bec56..7f100f964 100644 --- a/net/portmapper/portmapper.go +++ b/net/portmapper/portmapper.go @@ -14,15 +14,17 @@ import ( "io" "net" "net/http" + "net/netip" "sync" "time" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/neterror" "tailscale.com/net/netns" "tailscale.com/types/logger" + "tailscale.com/types/nettype" "tailscale.com/util/clientmetric" ) @@ -128,7 +130,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.Addr().IsValid() && m.external.Port() != 0 } func (p *pmpMapping) GoodUntil() time.Time { return p.goodUntil } @@ -143,7 +145,7 @@ func (m *pmpMapping) Release(ctx context.Context) { } defer uc.Close() pkt := buildPMPRequestMappingPacket(m.internal.Port(), m.external.Port(), pmpMapLifetimeDelete) - uc.WriteTo(pkt, m.gw.UDPAddr()) + uc.WriteToUDPAddrPort(pkt, m.gw) } // NewClient returns a new portmapping client. @@ -236,7 +238,7 @@ func (c *Client) upnpPort() uint16 { return upnpDefaultPort } -func (c *Client) listenPacket(ctx context.Context, network, addr string) (net.PacketConn, error) { +func (c *Client) listenPacket(ctx context.Context, network, addr string) (nettype.PacketConn, error) { // When running under testing conditions, we bind the IGD server // to localhost, and may be running in an environment where our // netns code would decide that binding the portmapper client @@ -251,9 +253,17 @@ func (c *Client) listenPacket(ctx context.Context, network, addr string) (net.Pa // so we don't care. if c.testPxPPort != 0 || c.testUPnPPort != 0 { var lc net.ListenConfig - return lc.ListenPacket(ctx, network, addr) + pc, err := lc.ListenPacket(ctx, network, addr) + if err != nil { + return nil, err + } + return pc.(*net.UDPConn), nil + } + pc, err := netns.Listener(c.logf).ListenPacket(ctx, network, addr) + if err != nil { + return nil, err } - return netns.Listener(c.logf).ListenPacket(ctx, network, addr) + return pc.(*net.UDPConn), nil } func (c *Client) invalidateMappingsLocked(releaseOld bool) { @@ -277,7 +287,7 @@ func (c *Client) sawPMPRecently() bool { } func (c *Client) sawPMPRecentlyLocked() bool { - return !c.pmpPubIP.IsZero() && c.pmpPubIPTime.After(time.Now().Add(-trustServiceStillAvailableDuration)) + return c.pmpPubIP.IsValid() && c.pmpPubIPTime.After(time.Now().Add(-trustServiceStillAvailableDuration)) } func (c *Client) sawPCPRecently() bool { @@ -333,6 +343,7 @@ func IsNoMappingError(err error) bool { var ( ErrNoPortMappingServices = errors.New("no port mapping services were found") ErrGatewayRange = errors.New("skipping portmap; gateway range likely lacks support") + ErrGatewayIPv6 = errors.New("skipping portmap; no IPv6 support for portmapping") ) // GetCachedMappingOrStartCreatingOne quickly returns with our current cached portmapping, if any. @@ -401,6 +412,9 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor if !ok { return netaddr.IPPort{}, NoMappingError{ErrGatewayRange} } + if gw.Is6() { + return netaddr.IPPort{}, NoMappingError{ErrGatewayIPv6} + } c.mu.Lock() localPort := c.localPort @@ -447,7 +461,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor internal: internalAddr, } if haveRecentPMP { - m.external = m.external.WithIP(c.pmpPubIP) + m.external = netip.AddrPortFrom(c.pmpPubIP, m.external.Port()) } if c.lastProbe.After(now.Add(-5*time.Second)) && !haveRecentPMP && !haveRecentPCP { c.mu.Unlock() @@ -469,7 +483,6 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor defer closeCloserOnContextDone(ctx, uc)() pxpAddr := netaddr.IPPortFrom(gw, c.pxpPort()) - pxpAddru := pxpAddr.UDPAddr() preferPCP := !DisablePCP && (DisablePMP || (!haveRecentPMP && haveRecentPCP)) @@ -478,7 +491,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor // TODO replace wildcardIP here with previous external if known. // Only do PCP mapping in the case when PMP did not appear to be available recently. pkt := buildPCPRequestMappingPacket(myIP, localPort, prevPort, pcpMapLifetimeSec, wildcardIP) - if _, err := uc.WriteTo(pkt, pxpAddru); err != nil { + if _, err := uc.WriteToUDPAddrPort(pkt, pxpAddr); err != nil { if neterror.TreatAsLostUDP(err) { err = NoMappingError{ErrNoPortMappingServices} } @@ -486,8 +499,8 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor } } else { // Ask for our external address if needed. - if m.external.IP().IsZero() { - if _, err := uc.WriteTo(pmpReqExternalAddrPacket, pxpAddru); err != nil { + if !m.external.Addr().IsValid() { + if _, err := uc.WriteToUDPAddrPort(pmpReqExternalAddrPacket, pxpAddr); err != nil { if neterror.TreatAsLostUDP(err) { err = NoMappingError{ErrNoPortMappingServices} } @@ -496,7 +509,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor } pkt := buildPMPRequestMappingPacket(localPort, prevPort, pmpMapLifetimeSec) - if _, err := uc.WriteTo(pkt, pxpAddru); err != nil { + if _, err := uc.WriteToUDPAddrPort(pkt, pxpAddr); err != nil { if neterror.TreatAsLostUDP(err) { err = NoMappingError{ErrNoPortMappingServices} } @@ -535,10 +548,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 = m.external.WithIP(pres.PublicAddr) + m.external = netip.AddrPortFrom(pres.PublicAddr, m.external.Port()) } if pres.OpCode == pmpOpReply|pmpOpMapUDP { - m.external = m.external.WithPort(pres.ExternalPort) + m.external = netip.AddrPortFrom(m.external.Addr(), pres.ExternalPort) d := time.Duration(pres.MappingValidSeconds) * time.Second now := time.Now() m.goodUntil = now.Add(d) @@ -688,9 +701,9 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) { defer cancel() defer closeCloserOnContextDone(ctx, uc)() - pxpAddr := netaddr.IPPortFrom(gw, c.pxpPort()).UDPAddr() - upnpAddr := netaddr.IPPortFrom(gw, c.upnpPort()).UDPAddr() - upnpMulticastAddr := netaddr.IPPortFrom(netaddr.IPv4(239, 255, 255, 250), c.upnpPort()).UDPAddr() + pxpAddr := netaddr.IPPortFrom(gw, c.pxpPort()) + upnpAddr := netaddr.IPPortFrom(gw, c.upnpPort()) + upnpMulticastAddr := netaddr.IPPortFrom(netaddr.IPv4(239, 255, 255, 250), c.upnpPort()) // Don't send probes to services that we recently learned (for // the same gw/myIP) are available. See @@ -699,13 +712,13 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) { res.PMP = true } else if !DisablePMP { metricPMPSent.Add(1) - uc.WriteTo(pmpReqExternalAddrPacket, pxpAddr) + uc.WriteToUDPAddrPort(pmpReqExternalAddrPacket, pxpAddr) } if c.sawPCPRecently() { res.PCP = true } else if !DisablePCP { metricPCPSent.Add(1) - uc.WriteTo(pcpAnnounceRequest(myIP), pxpAddr) + uc.WriteToUDPAddrPort(pcpAnnounceRequest(myIP), pxpAddr) } if c.sawUPnPRecently() { res.UPnP = true @@ -756,9 +769,9 @@ func (c *Client) Probe(ctx context.Context) (res ProbeResult, err error) { // their first descriptor (like urn:schemas-wifialliance-org:device:WFADevice:1) // in response to ssdp:all. https://github.com/tailscale/tailscale/issues/3557 metricUPnPSent.Add(1) - uc.WriteTo(uPnPPacket, upnpAddr) - uc.WriteTo(uPnPPacket, upnpMulticastAddr) - uc.WriteTo(uPnPIGDPacket, upnpMulticastAddr) + uc.WriteToUDPAddrPort(uPnPPacket, upnpAddr) + uc.WriteToUDPAddrPort(uPnPPacket, upnpMulticastAddr) + uc.WriteToUDPAddrPort(uPnPIGDPacket, upnpMulticastAddr) } buf := make([]byte, 1500) diff --git a/net/portmapper/portmapper_test.go b/net/portmapper/portmapper_test.go index 503d03103..b8f328e25 100644 --- a/net/portmapper/portmapper_test.go +++ b/net/portmapper/portmapper_test.go @@ -116,7 +116,7 @@ func TestPCPIntegration(t *testing.T) { if err != nil { t.Fatalf("failed to get mapping: %v", err) } - if external.IsZero() { + if !external.IsValid() { t.Errorf("got zero IP, expected non-zero") } if c.mapping == nil { diff --git a/net/portmapper/upnp.go b/net/portmapper/upnp.go index a28d774b7..15d8f4eb2 100644 --- a/net/portmapper/upnp.go +++ b/net/portmapper/upnp.go @@ -22,8 +22,8 @@ import ( "github.com/tailscale/goupnp" "github.com/tailscale/goupnp/dcps/internetgateway2" - "inet.af/netaddr" "tailscale.com/control/controlknobs" + "tailscale.com/net/netaddr" "tailscale.com/net/netns" "tailscale.com/types/logger" ) @@ -174,7 +174,7 @@ func getUPnPClient(ctx context.Context, logf logger.Logf, gw netaddr.IP, meta uP if err != nil { return nil, fmt.Errorf("unexpected host %q in %q", u.Host, meta.Location) } - if ipp.IP() != gw { + if ipp.Addr() != gw { return nil, fmt.Errorf("UPnP discovered root %q does not match gateway IP %v; ignoring UPnP", meta.Location, gw) } @@ -274,7 +274,7 @@ func (c *Client) getUPnPPortMapping( client, prevPort, internal.Port(), - internal.IP().String(), + internal.Addr().String(), time.Second*pmpMapLifetimeSec, ) if VerboseLogs { diff --git a/net/portmapper/upnp_test.go b/net/portmapper/upnp_test.go index 6a74e3d85..9b3963222 100644 --- a/net/portmapper/upnp_test.go +++ b/net/portmapper/upnp_test.go @@ -15,7 +15,7 @@ import ( "regexp" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tstest" ) diff --git a/net/socks5/socks5_test.go b/net/socks5/socks5_test.go index 8a5225da6..e05fed261 100644 --- a/net/socks5/socks5_test.go +++ b/net/socks5/socks5_test.go @@ -19,7 +19,7 @@ func socks5Server(listener net.Listener) { if err != nil { panic(err) } - listener.Close() + listener.Close() } func backendServer(listener net.Listener) { @@ -29,7 +29,7 @@ func backendServer(listener net.Listener) { } conn.Write([]byte("Test")) conn.Close() - listener.Close() + listener.Close() } func TestRead(t *testing.T) { diff --git a/net/stun/stuntest/stuntest.go b/net/stun/stuntest/stuntest.go index 6057a43a9..fa8559eec 100644 --- a/net/stun/stuntest/stuntest.go +++ b/net/stun/stuntest/stuntest.go @@ -14,7 +14,7 @@ import ( "sync" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/stun" "tailscale.com/tailcfg" "tailscale.com/types/nettype" diff --git a/net/tsaddr/tsaddr.go b/net/tsaddr/tsaddr.go index d2e7497e1..fe5117ef2 100644 --- a/net/tsaddr/tsaddr.go +++ b/net/tsaddr/tsaddr.go @@ -8,9 +8,10 @@ package tsaddr import ( "encoding/binary" "errors" + "net/netip" "sync" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) // ChromeOSVMRange returns the subset of the CGNAT IPv4 range used by @@ -56,7 +57,7 @@ func TailscaleServiceIP() netaddr.IP { // For IPv4, use TailscaleServiceIP. func TailscaleServiceIPv6() netaddr.IP { serviceIPv6.Do(func() { mustPrefix(&serviceIPv6.v, "fd7a:115c:a1e0::53/128") }) - return serviceIPv6.v.IP() + return serviceIPv6.v.Addr() } // IsTailscaleIP reports whether ip is an IP address in a range that @@ -112,7 +113,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().Addr() } // Tailscale4To6 returns a Tailscale IPv6 address that maps 1:1 to the @@ -122,7 +123,7 @@ func Tailscale4To6(ipv4 netaddr.IP) netaddr.IP { if !ipv4.Is4() || !IsTailscaleIP(ipv4) { return netaddr.IP{} } - ret := Tailscale4To6Range().IP().As16() + ret := Tailscale4To6Range().Addr().As16() v4 := ipv4.As4() copy(ret[13:], v4[1:]) return netaddr.IPFrom16(ret) @@ -186,16 +187,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.Addr() } } 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.Addr() || ip == b.Addr() } } // General case: m := map[netaddr.IP]bool{} for _, a := range addrs { - m[a.IP()] = true + m[a.Addr()] = true } return func(ip netaddr.IP) bool { return m[ip] } } @@ -232,10 +233,10 @@ func IPsContainsFunc(ips []netaddr.IP, f func(netaddr.IP) bool) bool { } // PrefixIs4 reports whether p is an IPv4 prefix. -func PrefixIs4(p netaddr.IPPrefix) bool { return p.IP().Is4() } +func PrefixIs4(p netaddr.IPPrefix) bool { return p.Addr().Is4() } // PrefixIs6 reports whether p is an IPv6 prefix. -func PrefixIs6(p netaddr.IPPrefix) bool { return p.IP().Is6() } +func PrefixIs6(p netaddr.IPPrefix) bool { return p.Addr().Is6() } // ContainsExitRoutes reports whether rr contains both the IPv4 and // IPv6 /0 route. @@ -280,7 +281,7 @@ func FilterPrefixesCopy(in []netaddr.IPPrefix, f func(netaddr.IPPrefix) bool) [] // IsViaPrefix reports whether p is a CIDR in the Tailscale "via" range. // See TailscaleViaRange. func IsViaPrefix(p netaddr.IPPrefix) bool { - return TailscaleViaRange().Contains(p.IP()) + return TailscaleViaRange().Contains(p.Addr()) } // UnmapVia returns the IPv4 address that corresponds to the provided Tailscale @@ -297,14 +298,14 @@ func UnmapVia(ip netaddr.IP) netaddr.IP { // MapVia returns an IPv6 "via" route for an IPv4 CIDR in a given siteID. func MapVia(siteID uint32, v4 netaddr.IPPrefix) (via netaddr.IPPrefix, err error) { - if !v4.IP().Is4() { + if !v4.Addr().Is4() { return via, errors.New("want IPv4 CIDR with a site ID") } - viaRange16 := TailscaleViaRange().IP().As16() + viaRange16 := TailscaleViaRange().Addr().As16() var a [16]byte copy(a[:], viaRange16[:8]) binary.BigEndian.PutUint32(a[8:], siteID) - ip4a := v4.IP().As4() + ip4a := v4.Addr().As4() copy(a[12:], ip4a[:]) - return netaddr.IPPrefixFrom(netaddr.IPFrom16(a), v4.Bits()+64+32), nil + return netip.PrefixFrom(netaddr.IPFrom16(a), v4.Bits()+64+32), nil } diff --git a/net/tsaddr/tsaddr_test.go b/net/tsaddr/tsaddr_test.go index 0cb9277d7..5f013b1d3 100644 --- a/net/tsaddr/tsaddr_test.go +++ b/net/tsaddr/tsaddr_test.go @@ -7,7 +7,7 @@ package tsaddr import ( "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func TestInCrostiniRange(t *testing.T) { diff --git a/net/tsdial/dnsmap.go b/net/tsdial/dnsmap.go index 7f0f23743..14705a1ec 100644 --- a/net/tsdial/dnsmap.go +++ b/net/tsdial/dnsmap.go @@ -12,7 +12,7 @@ import ( "strconv" "strings" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/netmap" "tailscale.com/util/dnsname" ) @@ -37,13 +37,13 @@ func dnsMapFromNetworkMap(nm *netmap.NetworkMap) dnsMap { suffix := nm.MagicDNSSuffix() have4 := false if nm.Name != "" && len(nm.Addresses) > 0 { - ip := nm.Addresses[0].IP() + ip := nm.Addresses[0].Addr() ret[canonMapKey(nm.Name)] = ip if dnsname.HasSuffix(nm.Name, suffix) { ret[canonMapKey(dnsname.TrimSuffix(nm.Name, suffix))] = ip } for _, a := range nm.Addresses { - if a.IP().Is4() { + if a.Addr().Is4() { have4 = true } } @@ -53,7 +53,7 @@ func dnsMapFromNetworkMap(nm *netmap.NetworkMap) dnsMap { continue } for _, a := range p.Addresses { - ip := a.IP() + ip := a.Addr() if ip.Is4() && !have4 { continue } @@ -112,7 +112,7 @@ func (m dnsMap) resolveMemory(ctx context.Context, network, addr string) (_ neta // Try MagicDNS first, otherwise a real DNS lookup. ip := m[canonMapKey(host)] - if !ip.IsZero() { + if ip.IsValid() { return netaddr.IPPortFrom(ip, port), nil } diff --git a/net/tsdial/dnsmap_test.go b/net/tsdial/dnsmap_test.go index 58520f801..d14d77a9f 100644 --- a/net/tsdial/dnsmap_test.go +++ b/net/tsdial/dnsmap_test.go @@ -8,7 +8,7 @@ import ( "reflect" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/netmap" ) diff --git a/net/tsdial/tsdial.go b/net/tsdial/tsdial.go index 0b2468c1c..287216b8a 100644 --- a/net/tsdial/tsdial.go +++ b/net/tsdial/tsdial.go @@ -18,9 +18,9 @@ import ( "syscall" "time" - "inet.af/netaddr" "tailscale.com/net/dnscache" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/netknob" "tailscale.com/net/netns" "tailscale.com/types/logger" @@ -309,7 +309,7 @@ func (d *Dialer) UserDial(ctx context.Context, network, addr string) (net.Conn, if err != nil { return nil, err } - if d.UseNetstackForIP != nil && d.UseNetstackForIP(ipp.IP()) { + if d.UseNetstackForIP != nil && d.UseNetstackForIP(ipp.Addr()) { if d.NetstackDialTCP == nil { return nil, errors.New("Dialer not initialized correctly") } @@ -334,7 +334,7 @@ func (d *Dialer) dialPeerAPI(ctx context.Context, network, addr string) (net.Con if err != nil { return nil, fmt.Errorf("peerAPI dial requires ip:port, not name resolution: %w", err) } - if d.UseNetstackForIP != nil && d.UseNetstackForIP(ipp.IP()) { + if d.UseNetstackForIP != nil && d.UseNetstackForIP(ipp.Addr()) { if d.NetstackDialTCP == nil { return nil, errors.New("Dialer not initialized correctly") } diff --git a/net/tstun/tap_linux.go b/net/tstun/tap_linux.go index 153cf5cda..9ff8a9029 100644 --- a/net/tstun/tap_linux.go +++ b/net/tstun/tap_linux.go @@ -17,7 +17,7 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" "gvisor.dev/gvisor/pkg/tcpip/transport/udp" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/types/ipproto" ) @@ -292,9 +292,9 @@ func packLayer2UDP(payload []byte, srcMAC, dstMAC net.HardwareAddr, src, dst net buf := make([]byte, header.EthernetMinimumSize+header.UDPMinimumSize+header.IPv4MinimumSize+len(payload)) payloadStart := len(buf) - len(payload) copy(buf[payloadStart:], payload) - srcB := src.IP().As4() + srcB := src.Addr().As4() srcIP := tcpip.Address(srcB[:]) - dstB := dst.IP().As4() + dstB := dst.Addr().As4() dstIP := tcpip.Address(dstB[:]) // Ethernet header eth := header.Ethernet(buf) diff --git a/net/tstun/wrap.go b/net/tstun/wrap.go index 1c50eccda..f4b678614 100644 --- a/net/tstun/wrap.go +++ b/net/tstun/wrap.go @@ -20,8 +20,8 @@ import ( "golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/tun" "gvisor.dev/gvisor/pkg/tcpip/stack" - "inet.af/netaddr" "tailscale.com/disco" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/tstime/mono" @@ -545,7 +545,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.Addr()]; fn != nil { fn() } } @@ -620,7 +620,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.Addr()); ok && port == p.Dst.Port() { outcome = filter.Accept } } @@ -634,8 +634,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.Addr(), + IPDst: p.Src.Addr(), Src: p.Src, Dst: p.Dst, Proto: p.IPProto, @@ -775,7 +775,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.Addr()) } switch pp.IPVersion { case 4: diff --git a/net/tstun/wrap_test.go b/net/tstun/wrap_test.go index b8f43dd15..1c09ce01b 100644 --- a/net/tstun/wrap_test.go +++ b/net/tstun/wrap_test.go @@ -14,9 +14,10 @@ import ( "unsafe" "go4.org/mem" + "go4.org/netipx" "golang.zx2c4.com/wireguard/tun/tuntest" - "inet.af/netaddr" "tailscale.com/disco" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/tstest" "tailscale.com/tstime/mono" @@ -148,7 +149,7 @@ func setfilter(logf logger.Logf, tun *Wrapper) { {IPProto: protos, Srcs: nets("5.6.7.8"), Dsts: netports("1.2.3.4:89-90")}, {IPProto: protos, Srcs: nets("1.2.3.4"), Dsts: netports("5.6.7.8:98")}, } - var sb netaddr.IPSetBuilder + var sb netipx.IPSetBuilder sb.AddPrefix(netaddr.MustParseIPPrefix("1.2.0.0/16")) ipSet, _ := sb.IPSet() tun.SetFilter(filter.New(matches, ipSet, ipSet, nil, logf)) @@ -454,28 +455,28 @@ func TestPeerAPIBypass(t *testing.T) { { name: "reject_with_filter", w: &Wrapper{}, - filter: filter.NewAllowNone(logger.Discard, new(netaddr.IPSet)), + filter: filter.NewAllowNone(logger.Discard, new(netipx.IPSet)), pkt: tcp4syn("1.2.3.4", "100.64.1.2", 1234, 60000), want: filter.Drop, }, { name: "peerapi_bypass_filter", w: wrapperWithPeerAPI, - filter: filter.NewAllowNone(logger.Discard, new(netaddr.IPSet)), + filter: filter.NewAllowNone(logger.Discard, new(netipx.IPSet)), pkt: tcp4syn("1.2.3.4", "100.64.1.2", 1234, 60000), want: filter.Accept, }, { name: "peerapi_dont_bypass_filter_wrong_port", w: wrapperWithPeerAPI, - filter: filter.NewAllowNone(logger.Discard, new(netaddr.IPSet)), + filter: filter.NewAllowNone(logger.Discard, new(netipx.IPSet)), pkt: tcp4syn("1.2.3.4", "100.64.1.2", 1234, 60001), want: filter.Drop, }, { name: "peerapi_dont_bypass_filter_wrong_dst_ip", w: wrapperWithPeerAPI, - filter: filter.NewAllowNone(logger.Discard, new(netaddr.IPSet)), + filter: filter.NewAllowNone(logger.Discard, new(netipx.IPSet)), pkt: tcp4syn("1.2.3.4", "100.64.1.3", 1234, 60000), want: filter.Drop, }, diff --git a/ssh/tailssh/incubator.go b/ssh/tailssh/incubator.go index 912438b58..299b8eacc 100644 --- a/ssh/tailssh/incubator.go +++ b/ssh/tailssh/incubator.go @@ -104,7 +104,7 @@ func (ss *sshSession) newIncubatorCommand() *exec.Cmd { "--groups=" + gids, "--local-user=" + lu.Username, "--remote-user=" + remoteUser, - "--remote-ip=" + ci.src.IP().String(), + "--remote-ip=" + ci.src.Addr().String(), "--has-tty=false", // updated in-place by startWithPTY "--tty-name=", // updated in-place by startWithPTY } @@ -295,8 +295,8 @@ func (ss *sshSession) launchProcess() error { ci := ss.conn.info cmd.Env = append(cmd.Env, - fmt.Sprintf("SSH_CLIENT=%s %d %d", ci.src.IP(), ci.src.Port(), ci.dst.Port()), - fmt.Sprintf("SSH_CONNECTION=%s %d %s %d", ci.src.IP(), ci.src.Port(), ci.dst.IP(), ci.dst.Port()), + fmt.Sprintf("SSH_CLIENT=%s %d %d", ci.src.Addr(), ci.src.Port(), ci.dst.Port()), + fmt.Sprintf("SSH_CONNECTION=%s %d %s %d", ci.src.Addr(), ci.src.Port(), ci.dst.Addr(), ci.dst.Port()), ) if ss.agentListener != nil { diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 7d9a130c8..7ba22cbe2 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -32,10 +32,10 @@ import ( "time" gossh "github.com/tailscale/golang-x-crypto/ssh" - "inet.af/netaddr" "tailscale.com/envknob" "tailscale.com/ipn/ipnlocal" "tailscale.com/logtail/backoff" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/syncs" "tailscale.com/tailcfg" @@ -424,10 +424,10 @@ func (c *conn) setInfo(cm gossh.ConnMetadata) error { src: toIPPort(cm.RemoteAddr()), dst: toIPPort(cm.LocalAddr()), } - if !tsaddr.IsTailscaleIP(ci.dst.IP()) { + if !tsaddr.IsTailscaleIP(ci.dst.Addr()) { return fmt.Errorf("tailssh: rejecting non-Tailscale local address %v", ci.dst) } - if !tsaddr.IsTailscaleIP(ci.src.IP()) { + if !tsaddr.IsTailscaleIP(ci.src.Addr()) { return fmt.Errorf("tailssh: rejecting non-Tailscale remote address %v", ci.src) } node, uprof, ok := c.srv.lb.WhoIs(ci.src) @@ -612,7 +612,7 @@ func (c *conn) handleSessionPostSSHAuth(s ssh.Session) { ss := c.newSSHSession(s) c.mu.Lock() - ss.logf("handling new SSH connection from %v (%v) to ssh-user %q", c.info.uprof.LoginName, c.info.src.IP(), c.localUser.Username) + ss.logf("handling new SSH connection from %v (%v) to ssh-user %q", c.info.uprof.LoginName, c.info.src.Addr(), c.localUser.Username) ss.logf("access granted to %v as ssh-user %q", c.info.uprof.LoginName, c.localUser.Username) c.mu.Unlock() ss.run() @@ -721,9 +721,9 @@ func (c *conn) expandDelegateURL(actionURL string) string { dstNodeID = fmt.Sprint(int64(nm.SelfNode.ID)) } return strings.NewReplacer( - "$SRC_NODE_IP", url.QueryEscape(ci.src.IP().String()), + "$SRC_NODE_IP", url.QueryEscape(ci.src.Addr().String()), "$SRC_NODE_ID", fmt.Sprint(int64(ci.node.ID)), - "$DST_NODE_IP", url.QueryEscape(ci.dst.IP().String()), + "$DST_NODE_IP", url.QueryEscape(ci.dst.Addr().String()), "$DST_NODE_ID", dstNodeID, "$SSH_USER", url.QueryEscape(ci.sshUser), "$LOCAL_USER", url.QueryEscape(lu.Username), @@ -871,7 +871,7 @@ func (ss *sshSession) killProcessOnContextDone() { io.WriteString(ss.Stderr(), "\r\n\r\n"+msg+"\r\n\r\n") } } - ss.logf("terminating SSH session from %v: %v", ss.conn.info.src.IP(), err) + ss.logf("terminating SSH session from %v: %v", ss.conn.info.src.Addr(), err) // We don't need to Process.Wait here, sshSession.run() does // the waiting regardless of termination reason. @@ -1227,7 +1227,7 @@ func (c *conn) principalMatchesTailscaleIdentity(p *tailcfg.SSHPrincipal) bool { return true } if p.NodeIP != "" { - if ip, _ := netaddr.ParseIP(p.NodeIP); ip == ci.src.IP() { + if ip, _ := netaddr.ParseIP(p.NodeIP); ip == ci.src.Addr() { return true } } diff --git a/ssh/tailssh/tailssh_test.go b/ssh/tailssh/tailssh_test.go index cabb775c0..ca9e968fe 100644 --- a/ssh/tailssh/tailssh_test.go +++ b/ssh/tailssh/tailssh_test.go @@ -25,9 +25,9 @@ import ( "testing" "time" - "inet.af/netaddr" "tailscale.com/ipn/ipnlocal" "tailscale.com/ipn/store/mem" + "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/tailcfg" "tailscale.com/tempfork/gliderlabs/ssh" diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 78cddf423..ad36c0c77 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -14,7 +14,7 @@ import ( "strings" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/dnstype" "tailscale.com/types/key" "tailscale.com/types/opt" diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 9952fe773..1523f1766 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -7,9 +7,9 @@ package tailcfg import ( + "net/netip" "time" - "inet.af/netaddr" "tailscale.com/types/dnstype" "tailscale.com/types/key" "tailscale.com/types/opt" @@ -76,14 +76,14 @@ var _NodeCloneNeedsRegeneration = Node(struct { KeyExpiry time.Time Machine key.MachinePublic DiscoKey key.DiscoPublic - Addresses []netaddr.IPPrefix - AllowedIPs []netaddr.IPPrefix + Addresses []netip.Prefix + AllowedIPs []netip.Prefix Endpoints []string DERP string Hostinfo HostinfoView Created time.Time Tags []string - PrimaryRoutes []netaddr.IPPrefix + PrimaryRoutes []netip.Prefix LastSeen *time.Time Online *bool KeepAlive bool @@ -124,7 +124,7 @@ var _HostinfoCloneNeedsRegeneration = Hostinfo(struct { ShieldsUp bool ShareeNode bool GoArch string - RoutableIPs []netaddr.IPPrefix + RoutableIPs []netip.Prefix RequestTags []string Services []Service NetInfo *NetInfo @@ -224,7 +224,7 @@ var _DNSConfigCloneNeedsRegeneration = DNSConfig(struct { FallbackResolvers []*dnstype.Resolver Domains []string Proxied bool - Nameservers []netaddr.IP + Nameservers []netip.Addr PerDomain bool CertDomains []string ExtraRecords []DNSRecord diff --git a/tailcfg/tailcfg_test.go b/tailcfg/tailcfg_test.go index 4e20bc670..af1747de0 100644 --- a/tailcfg/tailcfg_test.go +++ b/tailcfg/tailcfg_test.go @@ -12,7 +12,7 @@ import ( "testing" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/types/key" "tailscale.com/version" diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go index 1834a4992..d8c3e21a5 100644 --- a/tailcfg/tailcfg_view.go +++ b/tailcfg/tailcfg_view.go @@ -9,9 +9,9 @@ package tailcfg import ( "encoding/json" "errors" + "net/netip" "time" - "inet.af/netaddr" "tailscale.com/types/dnstype" "tailscale.com/types/key" "tailscale.com/types/opt" @@ -183,14 +183,14 @@ var _NodeViewNeedsRegeneration = Node(struct { KeyExpiry time.Time Machine key.MachinePublic DiscoKey key.DiscoPublic - Addresses []netaddr.IPPrefix - AllowedIPs []netaddr.IPPrefix + Addresses []netip.Prefix + AllowedIPs []netip.Prefix Endpoints []string DERP string Hostinfo HostinfoView Created time.Time Tags []string - PrimaryRoutes []netaddr.IPPrefix + PrimaryRoutes []netip.Prefix LastSeen *time.Time Online *bool KeepAlive bool @@ -282,7 +282,7 @@ var _HostinfoViewNeedsRegeneration = Hostinfo(struct { ShieldsUp bool ShareeNode bool GoArch string - RoutableIPs []netaddr.IPPrefix + RoutableIPs []netip.Prefix RequestTags []string Services []Service NetInfo *NetInfo @@ -488,7 +488,7 @@ func (v DNSConfigView) FallbackResolvers() views.SliceView[*dnstype.Resolver, dn } func (v DNSConfigView) Domains() views.Slice[string] { return views.SliceOf(v.ΠΆ.Domains) } func (v DNSConfigView) Proxied() bool { return v.ΠΆ.Proxied } -func (v DNSConfigView) Nameservers() views.Slice[netaddr.IP] { return views.SliceOf(v.ΠΆ.Nameservers) } +func (v DNSConfigView) Nameservers() views.Slice[netip.Addr] { return views.SliceOf(v.ΠΆ.Nameservers) } func (v DNSConfigView) PerDomain() bool { return v.ΠΆ.PerDomain } func (v DNSConfigView) CertDomains() views.Slice[string] { return views.SliceOf(v.ΠΆ.CertDomains) } func (v DNSConfigView) ExtraRecords() views.Slice[DNSRecord] { return views.SliceOf(v.ΠΆ.ExtraRecords) } @@ -503,7 +503,7 @@ var _DNSConfigViewNeedsRegeneration = DNSConfig(struct { FallbackResolvers []*dnstype.Resolver Domains []string Proxied bool - Nameservers []netaddr.IP + Nameservers []netip.Addr PerDomain bool CertDomains []string ExtraRecords []DNSRecord diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 4990c208d..62071c56f 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -20,7 +20,6 @@ import ( "sync" "time" - "inet.af/netaddr" "tailscale.com/client/tailscale" "tailscale.com/control/controlclient" "tailscale.com/envknob" @@ -33,6 +32,7 @@ import ( "tailscale.com/logpolicy" "tailscale.com/logtail" "tailscale.com/logtail/filch" + "tailscale.com/net/netaddr" "tailscale.com/net/nettest" "tailscale.com/net/tsdial" "tailscale.com/smallzstd" diff --git a/tstest/integration/integration_test.go b/tstest/integration/integration_test.go index 09c705133..c4ad2700e 100644 --- a/tstest/integration/integration_test.go +++ b/tstest/integration/integration_test.go @@ -30,10 +30,10 @@ import ( "time" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" "tailscale.com/ipn/store" + "tailscale.com/net/netaddr" "tailscale.com/safesocket" "tailscale.com/tailcfg" "tailscale.com/tstest" diff --git a/tstest/integration/tailscaled_deps_test_darwin.go b/tstest/integration/tailscaled_deps_test_darwin.go index daf5b92fa..60ee07949 100644 --- a/tstest/integration/tailscaled_deps_test_darwin.go +++ b/tstest/integration/tailscaled_deps_test_darwin.go @@ -11,7 +11,6 @@ import ( // Otherwise cmd/go never sees that we depend on these packages' // transitive deps when we run "go install tailscaled" in a child // process and can cache a prior success when a dependency changes. - _ "inet.af/netaddr" _ "tailscale.com/chirp" _ "tailscale.com/cmd/tailscaled/childproc" _ "tailscale.com/control/controlclient" @@ -24,6 +23,7 @@ import ( _ "tailscale.com/logtail" _ "tailscale.com/net/dns" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netaddr" _ "tailscale.com/net/netns" _ "tailscale.com/net/portmapper" _ "tailscale.com/net/proxymux" diff --git a/tstest/integration/tailscaled_deps_test_freebsd.go b/tstest/integration/tailscaled_deps_test_freebsd.go index 947a4e2f1..abf79d8cb 100644 --- a/tstest/integration/tailscaled_deps_test_freebsd.go +++ b/tstest/integration/tailscaled_deps_test_freebsd.go @@ -11,7 +11,6 @@ import ( // Otherwise cmd/go never sees that we depend on these packages' // transitive deps when we run "go install tailscaled" in a child // process and can cache a prior success when a dependency changes. - _ "inet.af/netaddr" _ "tailscale.com/chirp" _ "tailscale.com/cmd/tailscaled/childproc" _ "tailscale.com/control/controlclient" @@ -24,6 +23,7 @@ import ( _ "tailscale.com/logtail" _ "tailscale.com/net/dns" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netaddr" _ "tailscale.com/net/netns" _ "tailscale.com/net/portmapper" _ "tailscale.com/net/proxymux" diff --git a/tstest/integration/tailscaled_deps_test_linux.go b/tstest/integration/tailscaled_deps_test_linux.go index daf5b92fa..60ee07949 100644 --- a/tstest/integration/tailscaled_deps_test_linux.go +++ b/tstest/integration/tailscaled_deps_test_linux.go @@ -11,7 +11,6 @@ import ( // Otherwise cmd/go never sees that we depend on these packages' // transitive deps when we run "go install tailscaled" in a child // process and can cache a prior success when a dependency changes. - _ "inet.af/netaddr" _ "tailscale.com/chirp" _ "tailscale.com/cmd/tailscaled/childproc" _ "tailscale.com/control/controlclient" @@ -24,6 +23,7 @@ import ( _ "tailscale.com/logtail" _ "tailscale.com/net/dns" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netaddr" _ "tailscale.com/net/netns" _ "tailscale.com/net/portmapper" _ "tailscale.com/net/proxymux" diff --git a/tstest/integration/tailscaled_deps_test_openbsd.go b/tstest/integration/tailscaled_deps_test_openbsd.go index 947a4e2f1..abf79d8cb 100644 --- a/tstest/integration/tailscaled_deps_test_openbsd.go +++ b/tstest/integration/tailscaled_deps_test_openbsd.go @@ -11,7 +11,6 @@ import ( // Otherwise cmd/go never sees that we depend on these packages' // transitive deps when we run "go install tailscaled" in a child // process and can cache a prior success when a dependency changes. - _ "inet.af/netaddr" _ "tailscale.com/chirp" _ "tailscale.com/cmd/tailscaled/childproc" _ "tailscale.com/control/controlclient" @@ -24,6 +23,7 @@ import ( _ "tailscale.com/logtail" _ "tailscale.com/net/dns" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netaddr" _ "tailscale.com/net/netns" _ "tailscale.com/net/portmapper" _ "tailscale.com/net/proxymux" diff --git a/tstest/integration/tailscaled_deps_test_windows.go b/tstest/integration/tailscaled_deps_test_windows.go index c2f6e67b8..a82637ac5 100644 --- a/tstest/integration/tailscaled_deps_test_windows.go +++ b/tstest/integration/tailscaled_deps_test_windows.go @@ -16,7 +16,6 @@ import ( _ "golang.org/x/sys/windows/svc/eventlog" _ "golang.org/x/sys/windows/svc/mgr" _ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" - _ "inet.af/netaddr" _ "tailscale.com/cmd/tailscaled/childproc" _ "tailscale.com/control/controlclient" _ "tailscale.com/derp/derphttp" @@ -29,6 +28,7 @@ import ( _ "tailscale.com/logtail/backoff" _ "tailscale.com/net/dns" _ "tailscale.com/net/interfaces" + _ "tailscale.com/net/netaddr" _ "tailscale.com/net/netns" _ "tailscale.com/net/portmapper" _ "tailscale.com/net/proxymux" diff --git a/tstest/integration/testcontrol/testcontrol.go b/tstest/integration/testcontrol/testcontrol.go index ce6af5aa8..03ce51aec 100644 --- a/tstest/integration/testcontrol/testcontrol.go +++ b/tstest/integration/testcontrol/testcontrol.go @@ -27,7 +27,7 @@ import ( "github.com/klauspost/compress/zstd" "go4.org/mem" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/smallzstd" "tailscale.com/tailcfg" @@ -475,7 +475,7 @@ func (s *Server) serveRegister(w http.ResponseWriter, r *http.Request, mkey key. machineAuthorized := true // TODO: add Server.RequireMachineAuth v4Prefix := netaddr.IPPrefixFrom(netaddr.IPv4(100, 64, uint8(tailcfg.NodeID(user.ID)>>8), uint8(tailcfg.NodeID(user.ID))), 32) - v6Prefix := netaddr.IPPrefixFrom(tsaddr.Tailscale4To6(v4Prefix.IP()), 128) + v6Prefix := netaddr.IPPrefixFrom(tsaddr.Tailscale4To6(v4Prefix.Addr()), 128) allowedIPs := []netaddr.IPPrefix{ v4Prefix, @@ -761,7 +761,7 @@ func (s *Server) MapResponse(req *tailcfg.MapRequest) (res *tailcfg.MapResponse, }) v4Prefix := netaddr.IPPrefixFrom(netaddr.IPv4(100, 64, uint8(tailcfg.NodeID(user.ID)>>8), uint8(tailcfg.NodeID(user.ID))), 32) - v6Prefix := netaddr.IPPrefixFrom(tsaddr.Tailscale4To6(v4Prefix.IP()), 128) + v6Prefix := netaddr.IPPrefixFrom(tsaddr.Tailscale4To6(v4Prefix.Addr()), 128) res.Node.Addresses = []netaddr.IPPrefix{ v4Prefix, @@ -865,7 +865,7 @@ func keepClientEndpoint(ep string) bool { // the incoming JSON response. return false } - ip := ipp.IP() + ip := ipp.Addr() if ip.Zone() != "" { return false } diff --git a/tstest/integration/vms/derive_bindhost_test.go b/tstest/integration/vms/derive_bindhost_test.go index 7f75e3117..eeac158f4 100644 --- a/tstest/integration/vms/derive_bindhost_test.go +++ b/tstest/integration/vms/derive_bindhost_test.go @@ -9,8 +9,8 @@ import ( "runtime" "testing" - "inet.af/netaddr" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" ) func deriveBindhost(t *testing.T) string { @@ -26,7 +26,7 @@ func deriveBindhost(t *testing.T) string { if ret != "" || i.Name != ifName { return } - ret = prefix.IP().String() + ret = prefix.Addr().String() }) if ret != "" { return ret diff --git a/tstest/integration/vms/harness_test.go b/tstest/integration/vms/harness_test.go index ea4623c9c..975c7fa3b 100644 --- a/tstest/integration/vms/harness_test.go +++ b/tstest/integration/vms/harness_test.go @@ -25,7 +25,7 @@ import ( "golang.org/x/crypto/ssh" "golang.org/x/net/proxy" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstest/integration" "tailscale.com/tstest/integration/testcontrol" diff --git a/tstest/integration/vms/vms_steps_test.go b/tstest/integration/vms/vms_steps_test.go index 20eb520b5..684ceb3d2 100644 --- a/tstest/integration/vms/vms_steps_test.go +++ b/tstest/integration/vms/vms_steps_test.go @@ -18,7 +18,7 @@ import ( "time" "golang.org/x/crypto/ssh" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) const timeout = 15 * time.Second diff --git a/tstest/integration/vms/vms_test.go b/tstest/integration/vms/vms_test.go index d51fc6669..fa617ea21 100644 --- a/tstest/integration/vms/vms_test.go +++ b/tstest/integration/vms/vms_test.go @@ -28,7 +28,7 @@ import ( expect "github.com/tailscale/goexpect" "golang.org/x/crypto/ssh" "golang.org/x/sync/semaphore" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/tstest/integration" "tailscale.com/types/logger" diff --git a/tstest/iosdeps/iosdeps.go b/tstest/iosdeps/iosdeps.go index 1776391fa..5d51ed771 100644 --- a/tstest/iosdeps/iosdeps.go +++ b/tstest/iosdeps/iosdeps.go @@ -39,7 +39,6 @@ import ( _ "golang.org/x/sys/unix" _ "golang.zx2c4.com/wireguard/device" _ "golang.zx2c4.com/wireguard/tun" - _ "inet.af/netaddr" _ "tailscale.com/hostinfo" _ "tailscale.com/ipn" _ "tailscale.com/ipn/ipnlocal" @@ -48,6 +47,7 @@ import ( _ "tailscale.com/logtail" _ "tailscale.com/logtail/filch" _ "tailscale.com/net/dns" + _ "tailscale.com/net/netaddr" _ "tailscale.com/net/tsdial" _ "tailscale.com/net/tstun" _ "tailscale.com/paths" diff --git a/tstest/jsdeps/jsdeps.go b/tstest/jsdeps/jsdeps.go index 3eea9b81d..3b46ad60e 100644 --- a/tstest/jsdeps/jsdeps.go +++ b/tstest/jsdeps/jsdeps.go @@ -21,10 +21,10 @@ import ( _ "time" _ "golang.org/x/crypto/ssh" - _ "inet.af/netaddr" _ "tailscale.com/control/controlclient" _ "tailscale.com/ipn" _ "tailscale.com/ipn/ipnserver" + _ "tailscale.com/net/netaddr" _ "tailscale.com/net/netns" _ "tailscale.com/net/tsdial" _ "tailscale.com/safesocket" diff --git a/tstest/natlab/firewall.go b/tstest/natlab/firewall.go index 7f94cf66e..2fc458d40 100644 --- a/tstest/natlab/firewall.go +++ b/tstest/natlab/firewall.go @@ -6,10 +6,11 @@ package natlab import ( "fmt" + "net/netip" "sync" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) // FirewallType is the type of filtering a stateful firewall @@ -52,7 +53,7 @@ func (s FirewallType) key(src, dst netaddr.IPPort) fwKey { switch s { case EndpointIndependentFirewall: case AddressDependentFirewall: - k.dst = k.dst.WithIP(dst.IP()) + k.dst = netip.AddrPortFrom(dst.Addr(), k.dst.Port()) case AddressAndPortDependentFirewall: k.dst = dst default: diff --git a/tstest/natlab/nat.go b/tstest/natlab/nat.go index 85c88e894..f6b8f46fb 100644 --- a/tstest/natlab/nat.go +++ b/tstest/natlab/nat.go @@ -8,10 +8,11 @@ import ( "context" "fmt" "net" + "net/netip" "sync" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) // mapping is the state of an allocated NAT session. @@ -62,7 +63,7 @@ func (t NATType) key(src, dst netaddr.IPPort) natKey { switch t { case EndpointIndependentNAT: case AddressDependentNAT: - k.dst = k.dst.WithIP(dst.IP()) + k.dst = netip.AddrPortFrom(dst.Addr(), k.dst.Port()) case AddressAndPortDependentNAT: k.dst = dst default: @@ -171,7 +172,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.Addr() == oif.V4() { // Packet already NATed and is just retraversing Forward, // don't touch it again. return p diff --git a/tstest/natlab/natlab.go b/tstest/natlab/natlab.go index 71479159c..639da47ad 100644 --- a/tstest/natlab/natlab.go +++ b/tstest/natlab/natlab.go @@ -17,13 +17,14 @@ import ( "fmt" "math/rand" "net" + "net/netip" "os" "sort" "strconv" "sync" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) var traceOn, _ = strconv.ParseBool(os.Getenv("NATLAB_TRACE")) @@ -131,11 +132,11 @@ func (n *Network) addMachineLocked(ip netaddr.IP, iface *Interface) { func (n *Network) allocIPv4(iface *Interface) netaddr.IP { n.mu.Lock() defer n.mu.Unlock() - if n.Prefix4.IsZero() { + if !n.Prefix4.IsValid() { return netaddr.IP{} } - if n.lastV4.IsZero() { - n.lastV4 = n.Prefix4.IP() + if !n.lastV4.IsValid() { + n.lastV4 = n.Prefix4.Addr() } a := n.lastV4.As16() addOne(&a, 15) @@ -150,11 +151,11 @@ func (n *Network) allocIPv4(iface *Interface) netaddr.IP { func (n *Network) allocIPv6(iface *Interface) netaddr.IP { n.mu.Lock() defer n.mu.Unlock() - if n.Prefix6.IsZero() { + if !n.Prefix6.IsValid() { return netaddr.IP{} } - if n.lastV6.IsZero() { - n.lastV6 = n.Prefix6.IP() + if !n.lastV6.IsValid() { + n.lastV6 = n.Prefix6.Addr() } a := n.lastV6.As16() addOne(&a, 15) @@ -180,21 +181,21 @@ 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.Addr()] 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()) { - p.Trace("no route to %v", p.Dst.IP) + if p.Dst.Addr().Is4() && n.Prefix4.Contains(p.Dst.Addr()) { + p.Trace("no route to %v", p.Dst.Addr()) return len(p.Payload), nil } - if p.Dst.IP().Is6() && n.Prefix6.Contains(p.Dst.IP()) { - p.Trace("no route to %v", p.Dst.IP) + if p.Dst.Addr().Is6() && n.Prefix6.Contains(p.Dst.Addr()) { + p.Trace("no route to %v", p.Dst.Addr()) return len(p.Payload), nil } if n.defaultGW == nil { - p.Trace("no route to %v", p.Dst.IP) + p.Trace("no route to %v", p.Dst.Addr()) return len(p.Payload), nil } iface = n.defaultGW @@ -360,7 +361,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.Addr()) { m.deliverLocalPacket(p, iface) } else { m.forwardPacket(p, iface) @@ -388,7 +389,7 @@ func (m *Machine) deliverLocalPacket(p *Packet, iface *Interface) { defer m.mu.Unlock() conns := m.conns4 - if p.Dst.IP().Is6() { + if p.Dst.Addr().Is6() { conns = m.conns6 } possibleDsts := []netaddr.IPPort{ @@ -414,7 +415,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.Addr()) if err != nil { p.Trace("%v", err) return @@ -462,10 +463,10 @@ func (m *Machine) Attach(interfaceName string, n *Network) *Interface { net: n, name: interfaceName, } - if ip := n.allocIPv4(f); !ip.IsZero() { + if ip := n.allocIPv4(f); ip.IsValid() { f.ips = append(f.ips, ip) } - if ip := n.allocIPv6(f); !ip.IsZero() { + if ip := n.allocIPv6(f); ip.IsValid() { f.ips = append(f.ips, ip) } @@ -484,13 +485,13 @@ func (m *Machine) Attach(interfaceName string, n *Network) *Interface { iface: f, }) } else { - if !n.Prefix4.IsZero() { + if n.Prefix4.IsValid() { m.routes = append(m.routes, routeEntry{ prefix: n.Prefix4, iface: f, }) } - if !n.Prefix6.IsZero() { + if n.Prefix6.IsValid() { m.routes = append(m.routes, routeEntry{ prefix: n.Prefix6, iface: f, @@ -506,39 +507,39 @@ func (m *Machine) Attach(interfaceName string, n *Network) *Interface { var ( v4unspec = netaddr.IPv4(0, 0, 0, 0) - v6unspec = netaddr.IPv6Unspecified() + v6unspec = netip.IPv6Unspecified() ) 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.Addr()) if err != nil { p.Trace("%v", err) return 0, err } - origSrcIP := p.Src.IP() + origSrcIP := p.Src.Addr() switch { - case p.Src.IP() == v4unspec: + case p.Src.Addr() == v4unspec: p.Trace("assigning srcIP=%s", iface.V4()) - p.Src = p.Src.WithIP(iface.V4()) - case p.Src.IP() == v6unspec: + p.Src = netip.AddrPortFrom(iface.V4(), p.Src.Port()) + case p.Src.Addr() == v6unspec: // v6unspec in Go means "any src, but match address families" - if p.Dst.IP().Is6() { + if p.Dst.Addr().Is6() { p.Trace("assigning srcIP=%s", iface.V6()) - p.Src = p.Src.WithIP(iface.V6()) - } else if p.Dst.IP().Is4() { + p.Src = netip.AddrPortFrom(iface.V6(), p.Src.Port()) + } else if p.Dst.Addr().Is4() { p.Trace("assigning srcIP=%s", iface.V4()) - p.Src = p.Src.WithIP(iface.V4()) + p.Src = netip.AddrPortFrom(iface.V4(), p.Src.Port()) } 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.Addr()) { + err := fmt.Errorf("can't send to %v with src %v on interface %v", p.Dst.Addr(), p.Src.Addr(), iface) p.Trace("%v", err) return 0, err } } - if p.Src.IP().IsZero() { + if !p.Src.Addr().IsValid() { err := fmt.Errorf("no matching address for address family for %v", origSrcIP) p.Trace("%v", err) return 0, err @@ -614,7 +615,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.Addr().Is6() && c.ipp.Addr() != v6unspec { return fmt.Errorf("registerConn4 got IPv6 %s", c.ipp) } return registerConn(&m.conns4, c) @@ -629,7 +630,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.Addr().Is4() { return fmt.Errorf("registerConn6 got IPv4 %s", c.ipp) } return registerConn(&m.conns6, c) @@ -804,7 +805,11 @@ func (c *conn) breakActiveReadsLocked() { } func (c *conn) LocalAddr() net.Addr { - return c.ipp.UDPAddr() + return &net.UDPAddr{ + IP: c.ipp.Addr().AsSlice(), + Port: int(c.ipp.Port()), + Zone: c.ipp.Addr().Zone(), + } } func (c *conn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { @@ -824,7 +829,12 @@ func (c *conn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { case pkt := <-c.in: n = copy(p, pkt.Payload) pkt.Trace("PacketConn.ReadFrom") - return n, pkt.Src.UDPAddr(), nil + ua := &net.UDPAddr{ + IP: pkt.Src.Addr().AsSlice(), + Port: int(pkt.Src.Port()), + Zone: pkt.Src.Addr().Zone(), + } + return n, ua, nil case <-ctx.Done(): return 0, nil, context.DeadlineExceeded } @@ -835,6 +845,10 @@ func (c *conn) WriteTo(p []byte, addr net.Addr) (n int, err error) { if err != nil { return 0, fmt.Errorf("bogus addr %T %q", addr, addr.String()) } + return c.WriteToUDPAddrPort(p, ipp) +} + +func (c *conn) WriteToUDPAddrPort(p []byte, ipp netip.AddrPort) (n int, err error) { pkt := &Packet{ Src: c.ipp, Dst: ipp, diff --git a/tstest/natlab/natlab_test.go b/tstest/natlab/natlab_test.go index e7f8b6e70..269cff448 100644 --- a/tstest/natlab/natlab_test.go +++ b/tstest/natlab/natlab_test.go @@ -7,10 +7,12 @@ package natlab import ( "context" "fmt" + "net" + "net/netip" "testing" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tstest" ) @@ -63,7 +65,7 @@ func TestSendPacket(t *testing.T) { } const msg = "some message" - if _, err := fooPC.WriteTo([]byte(msg), barAddr.UDPAddr()); err != nil { + if _, err := fooPC.WriteTo([]byte(msg), net.UDPAddrFromAddrPort(barAddr)); err != nil { t.Fatal(err) } @@ -117,10 +119,10 @@ func TestMultiNetwork(t *testing.T) { serverAddr := netaddr.IPPortFrom(ifServer.V4(), 789) const msg1, msg2 = "hello", "world" - if _, err := natPC.WriteTo([]byte(msg1), clientAddr.UDPAddr()); err != nil { + if _, err := natPC.WriteTo([]byte(msg1), net.UDPAddrFromAddrPort(clientAddr)); err != nil { t.Fatal(err) } - if _, err := natPC.WriteTo([]byte(msg2), serverAddr.UDPAddr()); err != nil { + if _, err := natPC.WriteTo([]byte(msg2), net.UDPAddrFromAddrPort(serverAddr)); err != nil { t.Fatal(err) } @@ -154,8 +156,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 = p.Dst.WithIP(n.clientIP) + if iface == n.wanIf && p.Dst.Addr() == n.wanIf.V4() { + p.Dst = netip.AddrPortFrom(n.clientIP, p.Dst.Port()) } return p } @@ -167,13 +169,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 = p.Src.WithIP(n.wanIf.V4()) + if p.Src.Addr() == n.clientIP { + p.Src = netip.AddrPortFrom(n.wanIf.V4(), p.Src.Port()) } 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.Addr() == n.clientIP { return p } // Else drop. @@ -217,7 +219,7 @@ func TestPacketHandler(t *testing.T) { const msg = "some message" serverAddr := netaddr.IPPortFrom(ifServer.V4(), 456) - if _, err := clientPC.WriteTo([]byte(msg), serverAddr.UDPAddr()); err != nil { + if _, err := clientPC.WriteTo([]byte(msg), net.UDPAddrFromAddrPort(serverAddr)); err != nil { t.Fatal(err) } diff --git a/tsweb/tsweb.go b/tsweb/tsweb.go index c834f280b..0967e18f3 100644 --- a/tsweb/tsweb.go +++ b/tsweb/tsweb.go @@ -27,9 +27,9 @@ import ( "time" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/envknob" "tailscale.com/metrics" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" "tailscale.com/version" diff --git a/types/dnstype/dnstype.go b/types/dnstype/dnstype.go index 4b740443d..d78e81617 100644 --- a/types/dnstype/dnstype.go +++ b/types/dnstype/dnstype.go @@ -7,7 +7,7 @@ package dnstype //go:generate go run tailscale.com/cmd/cloner --type=Resolver --clonefunc=true -import "inet.af/netaddr" +import "tailscale.com/net/netaddr" // Resolver is the configuration for one DNS resolver. type Resolver struct { diff --git a/types/dnstype/dnstype_clone.go b/types/dnstype/dnstype_clone.go index 71b4e72e6..1ea760c4a 100644 --- a/types/dnstype/dnstype_clone.go +++ b/types/dnstype/dnstype_clone.go @@ -7,7 +7,7 @@ package dnstype import ( - "inet.af/netaddr" + "net/netip" ) // Clone makes a deep copy of Resolver. @@ -25,7 +25,7 @@ func (src *Resolver) Clone() *Resolver { // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _ResolverCloneNeedsRegeneration = Resolver(struct { Addr string - BootstrapResolution []netaddr.IP + BootstrapResolution []netip.Addr }{}) // Clone duplicates src into dst and reports whether it succeeded. diff --git a/types/dnstype/dnstype_view.go b/types/dnstype/dnstype_view.go index dcc196603..6c3345c5b 100644 --- a/types/dnstype/dnstype_view.go +++ b/types/dnstype/dnstype_view.go @@ -10,7 +10,7 @@ import ( "encoding/json" "errors" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/views" ) diff --git a/types/key/node.go b/types/key/node.go index 862233270..af812c918 100644 --- a/types/key/node.go +++ b/types/key/node.go @@ -156,7 +156,7 @@ func (p NodePublic) Shard() uint8 { // good-enough-for-sharding random, so we haphazardly // combine raw values of the key to give us something sufficient. s := uint8(p.k[31]) + uint8(p.k[30]) + uint8(p.k[20]) - return s ^ uint8(p.k[2] + p.k[12]) + return s ^ uint8(p.k[2]+p.k[12]) } // ParseNodePublicUntyped parses an untyped 64-character hex value diff --git a/types/netmap/netmap.go b/types/netmap/netmap.go index 51f14ac28..d56304544 100644 --- a/types/netmap/netmap.go +++ b/types/netmap/netmap.go @@ -12,7 +12,7 @@ import ( "strings" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/wgengine/filter" @@ -81,7 +81,7 @@ func (nm *NetworkMap) PeerByTailscaleIP(ip netaddr.IP) (peer *tailcfg.Node, ok b } for _, n := range nm.Peers { for _, a := range n.Addresses { - if a.IP() == ip { + if a.Addr() == ip { return n, true } } diff --git a/types/netmap/netmap_test.go b/types/netmap/netmap_test.go index adf29e8e4..41f0e12df 100644 --- a/types/netmap/netmap_test.go +++ b/types/netmap/netmap_test.go @@ -9,7 +9,7 @@ import ( "testing" "go4.org/mem" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" ) diff --git a/types/nettype/nettype.go b/types/nettype/nettype.go index c7827ef6a..a1506e115 100644 --- a/types/nettype/nettype.go +++ b/types/nettype/nettype.go @@ -8,6 +8,7 @@ package nettype import ( "context" "net" + "net/netip" ) // PacketListener defines the ListenPacket method as implemented @@ -16,6 +17,10 @@ type PacketListener interface { ListenPacket(ctx context.Context, network, address string) (net.PacketConn, error) } +type PacketListenerWithNetIP interface { + ListenPacket(ctx context.Context, network, address string) (PacketConn, error) +} + // Std implements PacketListener using the Go net package's ListenPacket func. type Std struct{} @@ -23,3 +28,24 @@ func (Std) ListenPacket(ctx context.Context, network, address string) (net.Packe var conf net.ListenConfig return conf.ListenPacket(ctx, network, address) } + +type PacketConn interface { + net.PacketConn + WriteToUDPAddrPort([]byte, netip.AddrPort) (int, error) +} + +func MakePacketListenerWithNetIP(ln PacketListener) PacketListenerWithNetIP { + return packetListenerAdapter{ln} +} + +type packetListenerAdapter struct { + PacketListener +} + +func (a packetListenerAdapter) ListenPacket(ctx context.Context, network, address string) (PacketConn, error) { + pc, err := a.PacketListener.ListenPacket(ctx, network, address) + if err != nil { + return nil, err + } + return pc.(PacketConn), nil +} diff --git a/types/views/views.go b/types/views/views.go index e14ddcbdb..c0e20bb99 100644 --- a/types/views/views.go +++ b/types/views/views.go @@ -10,7 +10,7 @@ import ( "encoding/json" "errors" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" ) diff --git a/types/views/views_test.go b/types/views/views_test.go index b6e91e825..73f295acc 100644 --- a/types/views/views_test.go +++ b/types/views/views_test.go @@ -12,7 +12,7 @@ import ( "testing" qt "github.com/frankban/quicktest" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func TestViewsJSON(t *testing.T) { diff --git a/util/codegen/codegen.go b/util/codegen/codegen.go index 48c7e0803..3c8151d68 100644 --- a/util/codegen/codegen.go +++ b/util/codegen/codegen.go @@ -226,7 +226,7 @@ func ContainsPointers(typ types.Type) bool { case "time.Time": // time.Time contains a pointer that does not need copying return false - case "inet.af/netaddr.IP": + case "inet.af/netaddr.IP", "net/netip.Addr", "net/netip.Prefix", "net/netip.AddrPort": return false } switch ft := typ.Underlying().(type) { diff --git a/util/deephash/deephash_test.go b/util/deephash/deephash_test.go index b30d69584..ea97e11a0 100644 --- a/util/deephash/deephash_test.go +++ b/util/deephash/deephash_test.go @@ -21,7 +21,7 @@ import ( "unsafe" "go4.org/mem" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/dnstype" "tailscale.com/types/ipproto" diff --git a/util/netconv/netconv.go b/util/netconv/netconv.go deleted file mode 100644 index 04b5760fb..000000000 --- a/util/netconv/netconv.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package netconv provides utilities to convert between netaddr and netip. -// To convert from a net.IP, use the netaddr/netip API. -package netconv - -import ( - "net/netip" - - "inet.af/netaddr" -) - -// AsIP returns a as a netaddr.IP. -func AsIP(a netip.Addr) netaddr.IP { - switch { - case a.Is4(): - return netaddr.IPFrom4(a.As4()) - case a.Is6(): - return netaddr.IPv6Raw(a.As16()).WithZone(a.Zone()) - } - return netaddr.IP{} -} - -// AsAddr returns a as a netip.IP. -func AsAddr(a netaddr.IP) netip.Addr { - switch { - case a.Is4(): - return netip.AddrFrom4(a.As4()) - case a.Is6(): - return netip.AddrFrom16(a.As16()).WithZone(a.Zone()) - } - return netip.Addr{} -} - -// AsIPPrefix returns a as a netaddr.IPPrefix. -// If a has Bits of -1, indicating an invalid bits, -// the returned IPPrefix will have Bits of 255. -// AsIPPrefix and AsPrefix do not -// round trip for invalid Bits values. -func AsIPPrefix(a netip.Prefix) netaddr.IPPrefix { - return netaddr.IPPrefixFrom(AsIP(a.Addr()), uint8(a.Bits())) -} - -// AsPrefix returns a as a netip.Prefix. -// If a has an invalid Bits value, -// the returned Prefix will have Bits of -1. -// AsIPPrefix and AsPrefix do not -// round trip for invalid Bits values. -func AsPrefix(a netaddr.IPPrefix) netip.Prefix { - return netip.PrefixFrom(AsAddr(a.IP()), int(a.Bits())) -} - -// AsIPPort returns a as a netaddr.IPPort. -func AsIPPort(a netip.AddrPort) netaddr.IPPort { - return netaddr.IPPortFrom(AsIP(a.Addr()), a.Port()) -} - -// AsAddrPort returns a as a netip.AddrPort. -func AsAddrPort(a netaddr.IPPort) netip.AddrPort { - return netip.AddrPortFrom(AsAddr(a.IP()), a.Port()) -} diff --git a/util/netconv/netconv_test.go b/util/netconv/netconv_test.go deleted file mode 100644 index 376cc4cd3..000000000 --- a/util/netconv/netconv_test.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package netconv - -import ( - "net/netip" - "testing" - - qt "github.com/frankban/quicktest" - "inet.af/netaddr" -) - -func TestAddr(t *testing.T) { - c := qt.New(t) - - c.Assert(netip.Addr{}, qt.Equals, AsAddr(netaddr.IP{})) - c.Assert(netaddr.IP{}, qt.Equals, AsIP(netip.Addr{})) - - // Cover IPv4, IPv6, 4in6, and zones. - addrStrs := []string{ - "0.0.0.0", - "123.45.67.89", - "::", - "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b", - "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b%eth0", - "::ffff:192.0.2.128", - "::ffff:192.0.2.128%eth0", - } - for _, s := range addrStrs { - ip := netaddr.MustParseIP(s) - addr := netip.MustParseAddr(s) - c.Assert(addr, qt.Equals, AsAddr(ip)) - c.Assert(ip, qt.Equals, AsIP(addr)) - } -} - -func TestAddrPort(t *testing.T) { - c := qt.New(t) - - c.Assert(netip.AddrPort{}, qt.Equals, AsAddrPort(netaddr.IPPort{})) - c.Assert(netaddr.IPPort{}, qt.Equals, AsIPPort(netip.AddrPort{})) - - // Test just a single AddrPort conversion; - // there's almost nothing happening in the code. - portStr := "1.2.4.5:8" - ipPort := netaddr.MustParseIPPort(portStr) - ap := netip.MustParseAddrPort(portStr) - c.Assert(ipPort, qt.Equals, AsIPPort(ap)) - c.Assert(ap, qt.Equals, AsAddrPort(ipPort)) -} - -func TestPrefix(t *testing.T) { - c := qt.New(t) - - // The interesting Prefix cases are invalid bits. - addr := netip.MustParseAddr("1.2.3.4") - ip := AsIP(addr) - - tests := []struct { - ipp netaddr.IPPrefix // input IPPrefix, output from converting pfx - pfx netip.Prefix // input Prefix, output from converting ipp - out netaddr.IPPrefix // output from converting pfx - }{ - {netaddr.IPPrefix{}, netip.Prefix{}, netaddr.IPPrefix{}}, - {netaddr.IPPrefixFrom(ip, 24), netip.PrefixFrom(addr, 24), netaddr.IPPrefixFrom(ip, 24)}, - {netaddr.IPPrefixFrom(ip, 255), netip.PrefixFrom(addr, -1), netaddr.IPPrefixFrom(ip, 255)}, - {netaddr.IPPrefixFrom(ip, 204), netip.PrefixFrom(addr, -1), netaddr.IPPrefixFrom(ip, 255)}, - } - - for _, test := range tests { - c.Assert(test.out, qt.Equals, AsIPPrefix(test.pfx)) - c.Assert(test.pfx, qt.Equals, AsPrefix(test.ipp)) - } -} diff --git a/wf/firewall.go b/wf/firewall.go index 100ac39fc..e37570574 100644 --- a/wf/firewall.go +++ b/wf/firewall.go @@ -12,8 +12,8 @@ import ( "os" "golang.org/x/sys/windows" - "inet.af/netaddr" "inet.af/wf" + "tailscale.com/net/netaddr" ) // Known addresses. @@ -219,7 +219,7 @@ func (f *Firewall) UpdatePermittedRoutes(newRoutes []netaddr.IPPrefix) error { }, } var p protocol - if r.IP().Is4() { + if r.Addr().Is4() { p = protocolV4 } else { p = protocolV6 diff --git a/wgengine/bench/bench.go b/wgengine/bench/bench.go index a86e26782..9bf640d54 100644 --- a/wgengine/bench/bench.go +++ b/wgengine/bench/bench.go @@ -17,7 +17,7 @@ import ( "strconv" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" ) @@ -87,7 +87,7 @@ func main() { } logf("initialized ok.") - traf.Start(Addr1.IP(), Addr2.IP(), PayloadSize+ICMPMinSize, 0) + traf.Start(Addr1.Addr(), Addr2.Addr(), 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 20c09664d..f9a3a0310 100644 --- a/wgengine/bench/bench_test.go +++ b/wgengine/bench/bench_test.go @@ -79,7 +79,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.Addr(), Addr2.Addr(), payload, int64(b.N)) var cur, prev Snapshot var pps int64 diff --git a/wgengine/bench/trafficgen.go b/wgengine/bench/trafficgen.go index f2314dc9b..00de0b1f4 100644 --- a/wgengine/bench/trafficgen.go +++ b/wgengine/bench/trafficgen.go @@ -11,7 +11,7 @@ import ( "sync" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/types/ipproto" ) diff --git a/wgengine/bench/wg.go b/wgengine/bench/wg.go index 6216afc52..410ff45c7 100644 --- a/wgengine/bench/wg.go +++ b/wgengine/bench/wg.go @@ -13,7 +13,7 @@ import ( "testing" "golang.zx2c4.com/wireguard/tun" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/dns" "tailscale.com/tailcfg" diff --git a/wgengine/filter/filter.go b/wgengine/filter/filter.go index cda28eb30..483642fea 100644 --- a/wgengine/filter/filter.go +++ b/wgengine/filter/filter.go @@ -10,9 +10,10 @@ import ( "sync" "time" - "inet.af/netaddr" + "go4.org/netipx" "tailscale.com/envknob" "tailscale.com/net/flowtrack" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/tstime/rate" "tailscale.com/types/ipproto" @@ -26,12 +27,12 @@ type Filter struct { // this node. All packets coming in over tailscale must have a // destination within local, regardless of the policy filter // below. - local *netaddr.IPSet + local *netipx.IPSet // logIPs is the set of IPs that are allowed to appear in flow // logs. If a packet is to or from an IP not in logIPs, it will // never be logged. - logIPs *netaddr.IPSet + logIPs *netipx.IPSet // matches4 and matches6 are lists of match->action rules // applied to all packets arriving over tailscale @@ -137,7 +138,7 @@ func NewAllowAllForTest(logf logger.Logf) *Filter { }, } - var sb netaddr.IPSetBuilder + var sb netipx.IPSetBuilder sb.AddPrefix(any4) sb.AddPrefix(any6) ipSet, _ := sb.IPSet() @@ -145,15 +146,15 @@ func NewAllowAllForTest(logf logger.Logf) *Filter { } // NewAllowNone returns a packet filter that rejects everything. -func NewAllowNone(logf logger.Logf, logIPs *netaddr.IPSet) *Filter { - return New(nil, &netaddr.IPSet{}, logIPs, nil, logf) +func NewAllowNone(logf logger.Logf, logIPs *netipx.IPSet) *Filter { + return New(nil, &netipx.IPSet{}, logIPs, nil, logf) } // NewShieldsUpFilter returns a packet filter that rejects incoming connections. // // If shareStateWith is non-nil, the returned filter shares state with the previous one, // as long as the previous one was also a shields up filter. -func NewShieldsUpFilter(localNets *netaddr.IPSet, logIPs *netaddr.IPSet, shareStateWith *Filter, logf logger.Logf) *Filter { +func NewShieldsUpFilter(localNets *netipx.IPSet, logIPs *netipx.IPSet, shareStateWith *Filter, logf logger.Logf) *Filter { // Don't permit sharing state with a prior filter that wasn't a shields-up filter. if shareStateWith != nil && !shareStateWith.shieldsUp { shareStateWith = nil @@ -168,7 +169,7 @@ func NewShieldsUpFilter(localNets *netaddr.IPSet, logIPs *netaddr.IPSet, shareSt // by matches. If shareStateWith is non-nil, the returned filter // shares state with the previous one, to enable changing rules at // runtime without breaking existing stateful flows. -func New(matches []Match, localNets *netaddr.IPSet, logIPs *netaddr.IPSet, shareStateWith *Filter, logf logger.Logf) *Filter { +func New(matches []Match, localNets *netipx.IPSet, logIPs *netipx.IPSet, shareStateWith *Filter, logf logger.Logf) *Filter { var state *filterState if shareStateWith != nil { state = shareStateWith.state @@ -198,12 +199,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.Addr()) { retm.Srcs = append(retm.Srcs, src) } } for _, dst := range m.Dsts { - if keep(dst.Net.IP()) { + if keep(dst.Net.Addr()) { retm.Dsts = append(retm.Dsts, dst) } } @@ -224,7 +225,7 @@ func capMatchesFunc(ms matches, keep func(netaddr.IP) bool) matches { } retm := Match{Caps: m.Caps} for _, src := range m.Srcs { - if keep(src.IP()) { + if keep(src.Addr()) { retm.Srcs = append(retm.Srcs, src) } } @@ -390,7 +391,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.Addr()) { return Drop, "destination not allowed" } @@ -450,7 +451,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.Addr()) { return Drop, "destination not allowed" } @@ -555,11 +556,11 @@ func (f *Filter) pre(q *packet.Parsed, rf RunFlags, dir direction) Response { return Drop } - if q.Dst.IP().IsMulticast() { + if q.Dst.Addr().IsMulticast() { f.logRateLimit(rf, q, dir, Drop, "multicast") return Drop } - if q.Dst.IP().IsLinkLocalUnicast() && q.Dst.IP() != gcpDNSAddr { + if q.Dst.Addr().IsLinkLocalUnicast() && q.Dst.Addr() != gcpDNSAddr { f.logRateLimit(rf, q, dir, Drop, "link-local-unicast") return Drop } @@ -581,7 +582,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.Addr()) && f.logIPs.Contains(p.Dst.Addr()) } // omitDropLogging reports whether packet p, which has already been @@ -593,5 +594,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.Addr().IsMulticast() || (p.Dst.Addr().IsLinkLocalUnicast() && p.Dst.Addr() != gcpDNSAddr) || p.IPProto == ipproto.IGMP } diff --git a/wgengine/filter/filter_clone.go b/wgengine/filter/filter_clone.go index e63e2a4d8..bbae3c451 100644 --- a/wgengine/filter/filter_clone.go +++ b/wgengine/filter/filter_clone.go @@ -7,7 +7,8 @@ package filter import ( - "inet.af/netaddr" + "net/netip" + "tailscale.com/types/ipproto" ) @@ -29,7 +30,7 @@ func (src *Match) Clone() *Match { // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _MatchCloneNeedsRegeneration = Match(struct { IPProto []ipproto.Proto - Srcs []netaddr.IPPrefix + Srcs []netip.Prefix Dsts []NetPortRange Caps []CapMatch }{}) diff --git a/wgengine/filter/filter_test.go b/wgengine/filter/filter_test.go index 55fd98554..4ed02d859 100644 --- a/wgengine/filter/filter_test.go +++ b/wgengine/filter/filter_test.go @@ -13,7 +13,8 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "inet.af/netaddr" + "go4.org/netipx" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" @@ -58,12 +59,12 @@ func newFilter(logf logger.Logf) *Filter { // Expects traffic to 100.122.98.50, 1.2.3.4, 5.6.7.8, // 102.102.102.102, 119.119.119.119, 8.1.0.0/16 - var localNets netaddr.IPSetBuilder + var localNets netipx.IPSetBuilder for _, n := range nets("100.122.98.50", "1.2.3.4", "5.6.7.8", "102.102.102.102", "119.119.119.119", "8.1.0.0/16", "2001::/16") { localNets.AddPrefix(n) } - var logB netaddr.IPSetBuilder + var logB netipx.IPSetBuilder logB.Complement() localNetsSet, _ := localNets.IPSet() logBSet, _ := logB.IPSet() @@ -140,9 +141,9 @@ func TestFilter(t *testing.T) { 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.Addr(), test.p.Dst.Addr(), 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.Addr(), test.p.Dst.Addr(), test.p.Dst.Port()) } if test.want != got { t.Errorf("#%d CheckTCP got=%v want=%v packet:%v", i, got, test.want, test.p) @@ -340,7 +341,7 @@ func TestPreFilter(t *testing.T) { {"udp", noVerdict, raw4default(ipproto.UDP, 0)}, {"icmp", noVerdict, raw4default(ipproto.ICMPv4, 0)}, } - f := NewAllowNone(t.Logf, &netaddr.IPSet{}) + f := NewAllowNone(t.Logf, &netipx.IPSet{}) for _, testPacket := range packets { p := &packet.Parsed{} p.Decode(testPacket.b) @@ -437,16 +438,16 @@ func TestLoggingPrivacy(t *testing.T) { logged = true } - var logB netaddr.IPSetBuilder + var logB netipx.IPSetBuilder logB.AddPrefix(netaddr.MustParseIPPrefix("100.64.0.0/10")) logB.AddPrefix(tsaddr.TailscaleULARange()) f := newFilter(logf) f.logIPs, _ = logB.IPSet() var ( - ts4 = netaddr.IPPortFrom(tsaddr.CGNATRange().IP().Next(), 1234) + ts4 = netaddr.IPPortFrom(tsaddr.CGNATRange().Addr().Next(), 1234) internet4 = netaddr.IPPortFrom(netaddr.MustParseIP("8.8.8.8"), 1234) - ts6 = netaddr.IPPortFrom(tsaddr.TailscaleULARange().IP().Next(), 1234) + ts6 = netaddr.IPPortFrom(tsaddr.TailscaleULARange().Addr().Next(), 1234) internet6 = netaddr.IPPortFrom(netaddr.MustParseIP("2001::1"), 1234) ) diff --git a/wgengine/filter/match.go b/wgengine/filter/match.go index 5f2a1fa44..a045163a9 100644 --- a/wgengine/filter/match.go +++ b/wgengine/filter/match.go @@ -8,7 +8,7 @@ import ( "fmt" "strings" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/types/ipproto" ) @@ -99,11 +99,11 @@ 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.Addr(), m.Srcs) { continue } for _, dst := range m.Dsts { - if !dst.Net.Contains(q.Dst.IP()) { + if !dst.Net.Contains(q.Dst.Addr()) { continue } if !dst.Ports.contains(q.Dst.Port()) { @@ -117,11 +117,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.Addr(), m.Srcs) { continue } for _, dst := range m.Dsts { - if dst.Net.Contains(q.Dst.IP()) { + if dst.Net.Contains(q.Dst.Addr()) { return true } } @@ -137,14 +137,14 @@ func (ms matches) matchProtoAndIPsOnlyIfAllPorts(q *packet.Parsed) bool { if !protoInList(q.IPProto, m.IPProto) { continue } - if !ipInList(q.Src.IP(), m.Srcs) { + if !ipInList(q.Src.Addr(), m.Srcs) { continue } for _, dst := range m.Dsts { if dst.Ports != allPorts { continue } - if dst.Net.Contains(q.Dst.IP()) { + if dst.Net.Contains(q.Dst.Addr()) { return true } } diff --git a/wgengine/filter/tailcfg.go b/wgengine/filter/tailcfg.go index d5f63dbd1..f1969cecf 100644 --- a/wgengine/filter/tailcfg.go +++ b/wgengine/filter/tailcfg.go @@ -8,7 +8,8 @@ import ( "fmt" "strings" - "inet.af/netaddr" + "go4.org/netipx" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/ipproto" ) @@ -140,7 +141,7 @@ func parseIPSet(arg string, bits *int) ([]netaddr.IPPrefix, error) { if err != nil { return nil, err } - r := netaddr.IPRangeFrom(ip1, ip2) + r := netipx.IPRangeFrom(ip1, ip2) if !r.Valid() { return nil, fmt.Errorf("invalid IP range %q", arg) } @@ -150,7 +151,7 @@ func parseIPSet(arg string, bits *int) ([]netaddr.IPPrefix, error) { if err != nil { return nil, fmt.Errorf("invalid IP address %q", arg) } - bits8 := ip.BitLen() + bits8 := uint8(ip.BitLen()) if bits != nil { if *bits < 0 || *bits > int(bits8) { return nil, fmt.Errorf("invalid CIDR size %d for IP %q", *bits, arg) diff --git a/wgengine/magicsock/debughttp.go b/wgengine/magicsock/debughttp.go index 4ec974ab2..4094c6ff5 100644 --- a/wgengine/magicsock/debughttp.go +++ b/wgengine/magicsock/debughttp.go @@ -13,7 +13,7 @@ import ( "strings" "time" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstime/mono" "tailscale.com/types/key" @@ -195,7 +195,7 @@ func peerDebugName(p *tailcfg.Node) string { } func ipPortLess(a, b netaddr.IPPort) bool { - if v := a.IP().Compare(b.IP()); v != 0 { + if v := a.Addr().Compare(b.Addr()); v != 0 { return v < 0 } return a.Port() < b.Port() diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index a1ad3b017..2c3b900af 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -29,7 +29,6 @@ import ( "go4.org/mem" "golang.zx2c4.com/wireguard/conn" - "inet.af/netaddr" "tailscale.com/control/controlclient" "tailscale.com/derp" "tailscale.com/derp/derphttp" @@ -39,6 +38,7 @@ import ( "tailscale.com/logtail/backoff" "tailscale.com/net/dnscache" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/netcheck" "tailscale.com/net/neterror" "tailscale.com/net/netns" @@ -55,7 +55,6 @@ import ( "tailscale.com/types/nettype" "tailscale.com/util/clientmetric" "tailscale.com/util/mak" - "tailscale.com/util/netconv" "tailscale.com/util/uniq" "tailscale.com/version" "tailscale.com/wgengine/monitor" @@ -890,7 +889,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].Addr().String() } res.NodeName = peer.Name // prefer DNS name if res.NodeName == "" { @@ -911,7 +910,7 @@ 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.Addr() != derpMagicIPAddr { res.Endpoint = ep.String() return } @@ -1049,7 +1048,7 @@ func (c *Conn) determineEndpoints(ctx context.Context) ([]tailcfg.Endpoint, erro return } addAddr := func(ipp netaddr.IPPort, et tailcfg.EndpointType) { - if ipp.IsZero() || (debugOmitLocalAddresses && et == tailcfg.EndpointLocal) { + if !ipp.IsValid() || (debugOmitLocalAddresses && et == tailcfg.EndpointLocal) { return } if _, ok := already[ipp]; !ok { @@ -1185,23 +1184,16 @@ var errDropDerpPacket = errors.New("too many DERP packets queued; dropping") var errNoUDP = errors.New("no UDP available on platform") -var udpAddrPool = &sync.Pool{ - New: func() any { return new(net.UDPAddr) }, -} - // sendUDP sends UDP packet b to ipp. // See sendAddr's docs on the return value meanings. func (c *Conn) sendUDP(ipp netaddr.IPPort, b []byte) (sent bool, err error) { if runtime.GOOS == "js" { return false, errNoUDP } - ua := udpAddrPool.Get().(*net.UDPAddr) - sent, err = c.sendUDPStd(ipp.UDPAddrAt(ua), b) + sent, err = c.sendUDPStd(ipp, b) if err != nil { metricSendUDPError.Add(1) } else { - // Only return it to the pool on success; Issue 3122. - udpAddrPool.Put(ua) if sent { metricSendUDP.Add(1) } @@ -1211,19 +1203,19 @@ func (c *Conn) sendUDP(ipp netaddr.IPPort, b []byte) (sent bool, err error) { // sendUDP sends UDP packet b to addr. // See sendAddr's docs on the return value meanings. -func (c *Conn) sendUDPStd(addr *net.UDPAddr, b []byte) (sent bool, err error) { +func (c *Conn) sendUDPStd(addr netip.AddrPort, b []byte) (sent bool, err error) { switch { - case addr.IP.To4() != nil: - _, err = c.pconn4.WriteTo(b, addr) + case addr.Addr().Is4(): + _, err = c.pconn4.WriteToUDPAddrPort(b, addr) if err != nil && (c.noV4.Get() || neterror.TreatAsLostUDP(err)) { return false, nil } - case len(addr.IP) == net.IPv6len: + case addr.Addr().Is6(): if c.pconn6 == nil { // ignore IPv6 dest if we don't have an IPv6 address. return false, nil } - _, err = c.pconn6.WriteTo(b, addr) + _, err = c.pconn6.WriteToUDPAddrPort(b, addr) if err != nil && (c.noV6.Get() || neterror.TreatAsLostUDP(err)) { return false, nil } @@ -1244,7 +1236,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.NodePublic, b []byte) (sent bool, err error) { - if addr.IP() != derpMagicIPAddr { + if addr.Addr() != derpMagicIPAddr { return c.sendUDP(addr, b) } @@ -1290,7 +1282,7 @@ const bufferedDerpWritesBeforeDrop = 32 // 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.NodePublic) chan<- derpWriteRequest { - if addr.IP() != derpMagicIPAddr { + if addr.Addr() != derpMagicIPAddr { return nil } regionID := int(addr.Port()) @@ -1795,7 +1787,7 @@ func (c *Conn) sendDiscoMessage(dst netaddr.IPPort, dstKey key.NodePublic, dstDi di := c.discoInfoLocked(dstDisco) c.mu.Unlock() - isDERP := dst.IP() == derpMagicIPAddr + isDERP := dst.Addr() == derpMagicIPAddr if isDERP { metricSendDiscoDERP.Add(1) } else { @@ -1846,7 +1838,7 @@ func (c *Conn) sendDiscoMessage(dst netaddr.IPPort, dstKey key.NodePublic, dstDi // * nonce [24]byte // * naclbox of payload (see tailscale.com/disco package for inner payload format) // -// For messages received over DERP, the src.IP() will be derpMagicIP (with +// For messages received over DERP, the src.Addr() will be derpMagicIP (with // src.Port() being the region ID) and the derpNodeSrc will be the node key // it was received from at the DERP layer. derpNodeSrc is zero when received // over UDP. @@ -1932,7 +1924,7 @@ func (c *Conn) handleDiscoMessage(msg []byte, src netaddr.IPPort, derpNodeSrc ke return } - isDERP := src.IP() == derpMagicIPAddr + isDERP := src.Addr() == derpMagicIPAddr if isDERP { metricRecvDiscoDERP.Add(1) } else { @@ -2024,7 +2016,7 @@ func (c *Conn) handlePingLocked(dm *disco.Ping, src netaddr.IPPort, di *discoInf likelyHeartBeat := src == di.lastPingFrom && time.Since(di.lastPingTime) < 5*time.Second di.lastPingFrom = src di.lastPingTime = time.Now() - isDerp := src.IP() == derpMagicIPAddr + isDerp := src.Addr() == derpMagicIPAddr // If we can figure out with certainty which node key this disco // message is for, eagerly update our IP<>node and disco<>node @@ -2378,7 +2370,7 @@ func (c *Conn) SetNetworkMap(nm *netmap.NetworkMap) { for _, a := range n.AllowedIPs { if a.IsSingleIP() { - fmt.Fprintf(w, "aip=%v ", a.IP()) + fmt.Fprintf(w, "aip=%v ", a.Addr()) } else { fmt.Fprintf(w, "aip=%v ", a) } @@ -2442,7 +2434,7 @@ func (c *Conn) maybeCloseDERPsOnRebind(okayLocalIPs []netaddr.IPPrefix) { c.closeOrReconectDERPLocked(regionID, "rebind-no-localaddr") continue } - if !tsaddr.PrefixesContainsIP(okayLocalIPs, la.IP()) { + if !tsaddr.PrefixesContainsIP(okayLocalIPs, la.Addr()) { c.closeOrReconectDERPLocked(regionID, "rebind-default-route-change") continue } @@ -2806,13 +2798,13 @@ func (c *Conn) initialBind() error { // listenPacket opens a packet listener. // The network must be "udp4" or "udp6". -func (c *Conn) listenPacket(network string, port uint16) (net.PacketConn, error) { +func (c *Conn) listenPacket(network string, port uint16) (nettype.PacketConn, error) { ctx := context.Background() // unused without DNS name to resolve addr := net.JoinHostPort("", fmt.Sprint(port)) if c.testOnlyPacketListener != nil { - return c.testOnlyPacketListener.ListenPacket(ctx, network, addr) + return nettype.MakePacketListenerWithNetIP(c.testOnlyPacketListener).ListenPacket(ctx, network, addr) } - return netns.Listener(c.logf).ListenPacket(ctx, network, addr) + return nettype.MakePacketListenerWithNetIP(netns.Listener(c.logf)).ListenPacket(ctx, network, addr) } // bindSocket initializes rucPtr if necessary and binds a UDP socket to it. @@ -2854,7 +2846,7 @@ func (c *Conn) bindSocket(rucPtr **RebindingUDPConn, network string, curPortFate // Remove duplicates. (All duplicates are consecutive.) uniq.ModifySlice(&ports, func(i, j int) bool { return ports[i] == ports[j] }) - var pconn net.PacketConn + var pconn nettype.PacketConn for _, port := range ports { // Close the existing conn, in case it is sitting on the port we want. err := ruc.closeLocked() @@ -2943,7 +2935,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.Addr().Unmap() a := ip.As16() ipb := a[:] if ip.Is4() { @@ -2983,11 +2975,11 @@ func (c *Conn) ParseEndpoint(nodeKeyStr string) (conn.Endpoint, error) { // Unix has no notion of re-binding a socket, so we swap it out for a new one. type RebindingUDPConn struct { mu sync.Mutex - pconn net.PacketConn + pconn nettype.PacketConn } // currentConn returns c's current pconn. -func (c *RebindingUDPConn) currentConn() net.PacketConn { +func (c *RebindingUDPConn) currentConn() nettype.PacketConn { c.mu.Lock() defer c.mu.Unlock() return c.pconn @@ -3021,9 +3013,7 @@ func (c *RebindingUDPConn) ReadFromNetaddr(b []byte) (n int, ipp netaddr.IPPort, // This lets us avoid allocations by calling ReadFromUDPAddrPort. // The non-*net.UDPConn case works, but it allocates. if udpConn, ok := pconn.(*net.UDPConn); ok { - var ap netip.AddrPort - n, ap, err = udpConn.ReadFromUDPAddrPort(b) - ipp = netconv.AsIPPort(ap) + n, ipp, err = udpConn.ReadFromUDPAddrPort(b) } else { var addr net.Addr n, addr, err = pconn.ReadFrom(b) @@ -3094,6 +3084,26 @@ func (c *RebindingUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) { } } +func (c *RebindingUDPConn) WriteToUDPAddrPort(b []byte, addr netip.AddrPort) (int, error) { + for { + c.mu.Lock() + pconn := c.pconn + c.mu.Unlock() + + n, err := pconn.WriteToUDPAddrPort(b, addr) + if err != nil { + c.mu.Lock() + pconn2 := c.pconn + c.mu.Unlock() + + if pconn != pconn2 { + continue + } + } + return n, err + } +} + func newBlockForeverConn() *blockForeverConn { c := new(blockForeverConn) c.cond = sync.NewCond(&c.mu) @@ -3121,6 +3131,11 @@ func (c *blockForeverConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { return len(p), nil } +func (c *blockForeverConn) WriteToUDPAddrPort(p []byte, addr netip.AddrPort) (int, error) { + // Silently drop writes. + return len(p), nil +} + func (c *blockForeverConn) LocalAddr() net.Addr { // Return a *net.UDPAddr because lots of code assumes that it will. return new(net.UDPAddr) @@ -3153,11 +3168,11 @@ func simpleDur(d time.Duration) time.Duration { } func sbPrintAddr(sb *strings.Builder, a netaddr.IPPort) { - is6 := a.IP().Is6() + is6 := a.Addr().Is6() if is6 { sb.WriteByte('[') } - fmt.Fprintf(sb, "%s", a.IP()) + fmt.Fprintf(sb, "%s", a.Addr()) if is6 { sb.WriteByte(']') } @@ -3197,8 +3212,8 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { if !addr.IsSingleIP() { continue } - sb.AddTailscaleIP(addr.IP()) - tailscaleIPs = append(tailscaleIPs, addr.IP()) + sb.AddTailscaleIP(addr.Addr()) + tailscaleIPs = append(tailscaleIPs, addr.Addr()) } } @@ -3236,7 +3251,7 @@ func (c *Conn) UpdateStatus(sb *ipnstate.StatusBuilder) { } func ippDebugString(ua netaddr.IPPort) string { - if ua.IP() == derpMagicIPAddr { + if ua.Addr() == derpMagicIPAddr { return fmt.Sprintf("derp-%d", ua.Port()) } return ua.String() @@ -3454,7 +3469,7 @@ func (de *endpoint) canP2P() bool { // de.mu must be held. func (de *endpoint) addrForSendLocked(now mono.Time) (udpAddr, derpAddr netaddr.IPPort) { udpAddr = de.bestAddr.IPPort - if udpAddr.IsZero() || now.After(de.trustBestAddrUntil) { + if !udpAddr.IsValid() || now.After(de.trustBestAddrUntil) { // We had a bestAddr but it expired so send both to it // and DERP. derpAddr = de.derpAddr @@ -3488,7 +3503,7 @@ func (de *endpoint) heartbeat() { now := mono.Now() udpAddr, _ := de.addrForSendLocked(now) - if !udpAddr.IsZero() { + if udpAddr.IsValid() { // We have a preferred path. Ping that every 2 seconds. de.startPingLocked(udpAddr, now, pingHeartbeat) } @@ -3511,7 +3526,7 @@ func (de *endpoint) wantFullPingLocked(now mono.Time) bool { if !de.canP2P() { return false } - if de.bestAddr.IsZero() || de.lastFullPing.IsZero() { + if !de.bestAddr.IsValid() || de.lastFullPing.IsZero() { return true } if now.After(de.trustBestAddrUntil) { @@ -3543,10 +3558,10 @@ func (de *endpoint) cliPing(res *ipnstate.PingResult, cb func(*ipnstate.PingResu now := mono.Now() udpAddr, derpAddr := de.addrForSendLocked(now) - if !derpAddr.IsZero() { + if derpAddr.IsValid() { de.startPingLocked(derpAddr, now, pingCLI) } - if !udpAddr.IsZero() && now.Before(de.trustBestAddrUntil) { + if udpAddr.IsValid() && now.Before(de.trustBestAddrUntil) { // Already have an active session, so just ping the address we're using. // Otherwise "tailscale ping" results to a node on the local network // can look like they're bouncing between, say 10.0.0.0/9 and the peer's @@ -3565,20 +3580,20 @@ func (de *endpoint) send(b []byte) error { de.mu.Lock() udpAddr, derpAddr := de.addrForSendLocked(now) - if de.canP2P() && (udpAddr.IsZero() || now.After(de.trustBestAddrUntil)) { + if de.canP2P() && (!udpAddr.IsValid() || now.After(de.trustBestAddrUntil)) { de.sendPingsLocked(now, true) } de.noteActiveLocked() de.mu.Unlock() - if udpAddr.IsZero() && derpAddr.IsZero() { + if !udpAddr.IsValid() && !derpAddr.IsValid() { return errors.New("no UDP or DERP addr") } var err error - if !udpAddr.IsZero() { + if udpAddr.IsValid() { _, err = de.c.sendAddr(udpAddr, de.publicKey, b) } - if !derpAddr.IsZero() { + if derpAddr.IsValid() { if ok, _ := de.c.sendAddr(derpAddr, de.publicKey, b); ok && err != nil { // UDP failed but DERP worked, so good enough: return nil @@ -3594,7 +3609,7 @@ func (de *endpoint) pingTimeout(txid stun.TxID) { if !ok { return } - if debugDisco || de.bestAddr.IsZero() || mono.Now().After(de.trustBestAddrUntil) { + if debugDisco || !de.bestAddr.IsValid() || mono.Now().After(de.trustBestAddrUntil) { de.c.logf("[v1] magicsock: disco: timeout waiting for pong %x from %v (%v, %v)", txid[:6], sp.to, de.publicKey.ShortString(), de.discoShort) } de.removeSentPingLocked(txid, sp) @@ -3710,7 +3725,7 @@ func (de *endpoint) sendPingsLocked(now mono.Time, sendCallMeMaybe bool) { de.startPingLocked(ep, now, pingDiscovery) } derpAddr := de.derpAddr - if sentAny && sendCallMeMaybe && !derpAddr.IsZero() { + if sentAny && sendCallMeMaybe && derpAddr.IsValid() { // Have our magicsock.Conn figure out its STUN endpoint (if // it doesn't know already) and then send a CallMeMaybe // message to our peer via DERP informing them that we've @@ -3822,7 +3837,7 @@ func (de *endpoint) handlePongConnLocked(m *disco.Pong, di *discoInfo, src netad de.mu.Lock() defer de.mu.Unlock() - isDerp := src.IP() == derpMagicIPAddr + isDerp := src.Addr() == derpMagicIPAddr sp, ok := de.sentPing[m.TxID] if !ok { @@ -3895,19 +3910,19 @@ func betterAddr(a, b addrLatency) bool { if a.IPPort == b.IPPort { return false } - if b.IsZero() { + if !b.IsValid() { return true } - if a.IsZero() { + if !a.IsValid() { return false } - if a.IP().Is6() && b.IP().Is4() { + if a.Addr().Is6() && b.Addr().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.Addr().Is4() && b.Addr().Is6() { if betterAddr(b, a) { return false } @@ -3952,7 +3967,7 @@ func (de *endpoint) handleCallMeMaybe(m *disco.CallMeMaybe) { } var newEPs []netaddr.IPPort for _, ep := range m.MyNumber { - if ep.IP().Is6() && ep.IP().IsLinkLocalUnicast() { + if ep.Addr().Is6() && ep.Addr().IsLinkLocalUnicast() { // We send these out, but ignore them for now. // TODO: teach the ping code to ping on all interfaces // for these. @@ -4010,7 +4025,7 @@ func (de *endpoint) populatePeerStatus(ps *ipnstate.PeerStatus) { ps.LastWrite = de.lastSend.WallTime() ps.Active = now.Sub(de.lastSend) < sessionActiveTimeout - if udpAddr, derpAddr := de.addrForSendLocked(now); !udpAddr.IsZero() && derpAddr.IsZero() { + if udpAddr, derpAddr := de.addrForSendLocked(now); udpAddr.IsValid() && !derpAddr.IsValid() { ps.CurAddr = udpAddr.String() } } diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index c0ffd07cf..2302dd019 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -30,10 +30,10 @@ import ( "go4.org/mem" "golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/tun/tuntest" - "inet.af/netaddr" "tailscale.com/derp" "tailscale.com/derp/derphttp" "tailscale.com/ipn/ipnstate" + "tailscale.com/net/netaddr" "tailscale.com/net/stun/stuntest" "tailscale.com/net/tstun" "tailscale.com/tailcfg" @@ -44,7 +44,6 @@ import ( "tailscale.com/types/netmap" "tailscale.com/types/nettype" "tailscale.com/util/cibuild" - "tailscale.com/util/netconv" "tailscale.com/util/racebuild" "tailscale.com/wgengine/filter" "tailscale.com/wgengine/wgcfg" @@ -511,7 +510,7 @@ func TestConnClosed(t *testing.T) { cleanup = meshStacks(t.Logf, nil, ms1, ms2) defer cleanup() - pkt := tuntest.Ping(netconv.AsAddr(ms2.IP()), netconv.AsAddr(ms1.IP())) + pkt := tuntest.Ping(ms2.IP(), ms1.IP()) if len(ms1.conn.activeDerp) == 0 { t.Errorf("unexpected DERP empty got: %v want: >0", len(ms1.conn.activeDerp)) @@ -643,7 +642,7 @@ func TestNoDiscoKey(t *testing.T) { break } - pkt := tuntest.Ping(netconv.AsAddr(m2.IP()), netconv.AsAddr(m1.IP())) + pkt := tuntest.Ping(m2.IP(), m1.IP()) m1.tun.Outbound <- pkt select { case <-m2.tun.Inbound: @@ -856,7 +855,7 @@ func newPinger(t *testing.T, logf logger.Logf, src, dst *magicStack) (cleanup fu // failure). Figure out what kind of thing would be // acceptable to test instead of "every ping must // transit". - pkt := tuntest.Ping(netconv.AsAddr(dst.IP()), netconv.AsAddr(src.IP())) + pkt := tuntest.Ping(dst.IP(), src.IP()) select { case src.tun.Outbound <- pkt: case <-ctx.Done(): diff --git a/wgengine/monitor/monitor.go b/wgengine/monitor/monitor.go index 914e73a00..c57dd368d 100644 --- a/wgengine/monitor/monitor.go +++ b/wgengine/monitor/monitor.go @@ -14,8 +14,8 @@ import ( "sync" "time" - "inet.af/netaddr" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" ) diff --git a/wgengine/monitor/monitor_darwin.go b/wgengine/monitor/monitor_darwin.go index 7fda2fa42..be99a7f2d 100644 --- a/wgengine/monitor/monitor_darwin.go +++ b/wgengine/monitor/monitor_darwin.go @@ -11,7 +11,7 @@ import ( "golang.org/x/net/route" "golang.org/x/sys/unix" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" ) @@ -190,7 +190,7 @@ func fmtAddr(a route.Addr) any { if a == nil { return nil } - if ip := ipOfAddr(a); !ip.IsZero() { + if ip := ipOfAddr(a); ip.IsValid() { return ip } switch a := a.(type) { diff --git a/wgengine/monitor/monitor_linux.go b/wgengine/monitor/monitor_linux.go index 1537ec13b..db12595f4 100644 --- a/wgengine/monitor/monitor_linux.go +++ b/wgengine/monitor/monitor_linux.go @@ -14,8 +14,8 @@ import ( "github.com/jsimonetti/rtnetlink" "github.com/mdlayher/netlink" "golang.org/x/sys/unix" - "inet.af/netaddr" "tailscale.com/envknob" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" ) @@ -167,7 +167,7 @@ func (c *nlConn) Receive() (message, error) { if msg.Header.Type == unix.RTM_NEWROUTE && (rmsg.Attributes.Table == 255 || rmsg.Attributes.Table == 254) && - (dst.IP().IsMulticast() || dst.IP().IsLinkLocalUnicast()) { + (dst.Addr().IsMulticast() || dst.Addr().IsLinkLocalUnicast()) { if debugNetlinkMessages { c.logf("%s ignored", typeStr) @@ -180,7 +180,7 @@ func (c *nlConn) Receive() (message, error) { if rmsg.Table == tsTable && dst.IsSingleIP() { // Don't log. Spammy and normal to see a bunch of these on start-up, // which we make ourselves. - } else if tsaddr.IsTailscaleIP(dst.IP()) { + } else if tsaddr.IsTailscaleIP(dst.Addr()) { // Verbose only. c.logf("%s: [v1] src=%v, dst=%v, gw=%v, outif=%v, table=%v", typeStr, condNetAddrPrefix(src), condNetAddrPrefix(dst), condNetAddrIP(gw), @@ -246,14 +246,14 @@ func netaddrIPPrefix(std net.IP, bits uint8) netaddr.IPPrefix { } func condNetAddrPrefix(ipp netaddr.IPPrefix) string { - if ipp.IP().IsZero() { + if !ipp.Addr().IsValid() { return "" } return ipp.String() } func condNetAddrIP(ip netaddr.IP) string { - if ip.IsZero() { + if !ip.IsValid() { return "" } return ip.String() @@ -269,7 +269,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.Addr()) } // newAddrMessage is a message for a new address being added. diff --git a/wgengine/monitor/monitor_linux_test.go b/wgengine/monitor/monitor_linux_test.go index 25bad943f..61d2846c4 100644 --- a/wgengine/monitor/monitor_linux_test.go +++ b/wgengine/monitor/monitor_linux_test.go @@ -11,7 +11,7 @@ import ( "github.com/jsimonetti/rtnetlink" "github.com/mdlayher/netlink" "golang.org/x/sys/unix" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func newAddrMsg(iface uint32, addr string, typ netlink.HeaderType) netlink.Message { diff --git a/wgengine/monitor/monitor_windows.go b/wgengine/monitor/monitor_windows.go index 13eca8d2c..4a9bbbae1 100644 --- a/wgengine/monitor/monitor_windows.go +++ b/wgengine/monitor/monitor_windows.go @@ -12,7 +12,7 @@ import ( "time" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" ) @@ -144,7 +144,7 @@ func (m *winMon) unicastAddressChanged(_ winipcfg.MibNotificationType, row *wini func (m *winMon) routeChanged(_ winipcfg.MibNotificationType, row *winipcfg.MibIPforwardRow2) { what := "route" ipn := row.DestinationPrefix.IPNet() - if cidr, ok := netaddr.FromStdIPNet(&ipn); ok && tsaddr.IsTailscaleIP(cidr.IP()) { + if cidr, ok := netaddr.FromStdIPNet(&ipn); ok && tsaddr.IsTailscaleIP(cidr.Addr()) { what = "tsroute" } // start a goroutine to finish our work, to return to Windows out of this callback diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go index 4b9882258..07263187a 100644 --- a/wgengine/netstack/netstack.go +++ b/wgengine/netstack/netstack.go @@ -34,10 +34,10 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" "gvisor.dev/gvisor/pkg/tcpip/transport/udp" "gvisor.dev/gvisor/pkg/waiter" - "inet.af/netaddr" "tailscale.com/envknob" "tailscale.com/ipn/ipnlocal" "tailscale.com/net/dns" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" @@ -255,7 +255,7 @@ func (ns *Impl) addSubnetAddress(ip netaddr.IP) { if needAdd { pa := tcpip.ProtocolAddress{ AddressWithPrefix: tcpip.AddressWithPrefix{ - Address: tcpip.Address(ip.IPAddr().IP), + Address: tcpip.Address(ip.AsSlice()), PrefixLen: int(ip.BitLen()), }, } @@ -277,14 +277,14 @@ func (ns *Impl) removeSubnetAddress(ip netaddr.IP) { ns.connsOpenBySubnetIP[ip]-- // Only unregister address from netstack after last concurrent connection. if ns.connsOpenBySubnetIP[ip] == 0 { - ns.ipstack.RemoveAddress(nicID, tcpip.Address(ip.IPAddr().IP)) + ns.ipstack.RemoveAddress(nicID, tcpip.Address(ip.AsSlice())) delete(ns.connsOpenBySubnetIP, ip) } } func ipPrefixToAddressWithPrefix(ipp netaddr.IPPrefix) tcpip.AddressWithPrefix { return tcpip.AddressWithPrefix{ - Address: tcpip.Address(ipp.IP().IPAddr().IP), + Address: tcpip.Address(ipp.Addr().AsSlice()), PrefixLen: int(ipp.Bits()), } } @@ -335,7 +335,7 @@ func (ns *Impl) updateIPs(nm *netmap.NetworkMap) { } ns.mu.Lock() for ip := range ns.connsOpenBySubnetIP { - ipp := tcpip.Address(ip.IPAddr().IP).WithPrefix() + ipp := tcpip.Address(ip.AsSlice()).WithPrefix() delete(ipsToBeRemoved, ipp) } ns.mu.Unlock() @@ -376,7 +376,7 @@ func (ns *Impl) updateIPs(nm *netmap.NetworkMap) { func (ns *Impl) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper) filter.Response { // If it's not traffic to the service IP (i.e. magicDNS) we don't // care; resume processing. - if dst := p.Dst.IP(); dst != magicDNSIP && dst != magicDNSIPv6 { + if dst := p.Dst.Addr(); dst != magicDNSIP && dst != magicDNSIPv6 { return filter.Accept } // Of traffic to the service IP, we only care about UDP 53, and TCP @@ -414,11 +414,11 @@ func (ns *Impl) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper) filter.Re func (ns *Impl) DialContextTCP(ctx context.Context, ipp netaddr.IPPort) (*gonet.TCPConn, error) { remoteAddress := tcpip.FullAddress{ NIC: nicID, - Addr: tcpip.Address(ipp.IP().IPAddr().IP), + Addr: tcpip.Address(ipp.Addr().AsSlice()), Port: ipp.Port(), } var ipType tcpip.NetworkProtocolNumber - if ipp.IP().Is4() { + if ipp.Addr().Is4() { ipType = ipv4.ProtocolNumber } else { ipType = ipv6.ProtocolNumber @@ -430,11 +430,11 @@ func (ns *Impl) DialContextTCP(ctx context.Context, ipp netaddr.IPPort) (*gonet. func (ns *Impl) DialContextUDP(ctx context.Context, ipp netaddr.IPPort) (*gonet.UDPConn, error) { remoteAddress := &tcpip.FullAddress{ NIC: nicID, - Addr: tcpip.Address(ipp.IP().IPAddr().IP), + Addr: tcpip.Address(ipp.Addr().AsSlice()), Port: ipp.Port(), } var ipType tcpip.NetworkProtocolNumber - if ipp.IP().Is4() { + if ipp.Addr().Is4() { ipType = ipv4.ProtocolNumber } else { ipType = ipv6.ProtocolNumber @@ -534,9 +534,9 @@ func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool { // Handle incoming peerapi connections in netstack. if ns.lb != nil && p.IPProto == ipproto.TCP { var peerAPIPort uint16 - dstIP := p.Dst.IP() + dstIP := p.Dst.Addr() if p.TCPFlags&packet.TCPSynAck == packet.TCPSyn && ns.isLocalIP(dstIP) { - if port, ok := ns.lb.GetPeerAPIPort(p.Dst.IP()); ok { + if port, ok := ns.lb.GetPeerAPIPort(p.Dst.Addr()); ok { peerAPIPort = port atomic.StoreUint32(ns.peerAPIPortAtomic(dstIP), uint32(port)) } @@ -550,15 +550,15 @@ func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool { if ns.isInboundTSSH(p) && ns.processSSH() { return true } - if p.IPVersion == 6 && viaRange.Contains(p.Dst.IP()) { - return ns.lb != nil && ns.lb.ShouldHandleViaIP(p.Dst.IP()) + if p.IPVersion == 6 && viaRange.Contains(p.Dst.Addr()) { + return ns.lb != nil && ns.lb.ShouldHandleViaIP(p.Dst.Addr()) } if !ns.ProcessLocalIPs && !ns.ProcessSubnets { // Fast path for common case (e.g. Linux server in TUN mode) where // netstack isn't used at all; don't even do an isLocalIP lookup. return false } - isLocal := ns.isLocalIP(p.Dst.IP()) + isLocal := ns.isLocalIP(p.Dst.Addr()) if ns.ProcessLocalIPs && isLocal { return true } @@ -647,7 +647,7 @@ func (ns *Impl) userPing(dstIP netaddr.IP, pingResPkt []byte) { func (ns *Impl) isInboundTSSH(p *packet.Parsed) bool { return p.IPProto == ipproto.TCP && p.Dst.Port() == 22 && - ns.isLocalIP(p.Dst.IP()) + ns.isLocalIP(p.Dst.Addr()) } // injectInbound is installed as a packet hook on the 'inbound' (from a @@ -661,7 +661,7 @@ func (ns *Impl) injectInbound(p *packet.Parsed, t *tstun.Wrapper) filter.Respons return filter.Accept } - destIP := p.Dst.IP() + destIP := p.Dst.Addr() if p.IsEchoRequest() && ns.ProcessSubnets && !tsaddr.IsTailscaleIP(destIP) { var pong []byte // the reply to the ping, if our relayed ping works if destIP.Is4() { @@ -886,7 +886,7 @@ func (ns *Impl) acceptUDP(r *udp.ForwarderRequest) { } // Handle magicDNS traffic (via UDP) here. - if dst := dstAddr.IP(); dst == magicDNSIP || dst == magicDNSIPv6 { + if dst := dstAddr.Addr(); dst == magicDNSIP || dst == magicDNSIPv6 { if dstAddr.Port() != 53 { return // Only MagicDNS traffic runs on the service IPs for now. } @@ -949,16 +949,16 @@ func (ns *Impl) forwardUDP(client *gonet.UDPConn, wq *waiter.Queue, clientAddr, var backendListenAddr *net.UDPAddr var backendRemoteAddr *net.UDPAddr - isLocal := ns.isLocalIP(dstAddr.IP()) + isLocal := ns.isLocalIP(dstAddr.Addr()) if isLocal { backendRemoteAddr = &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: int(port)} backendListenAddr = &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: int(srcPort)} } else { - if dstIP := dstAddr.IP(); viaRange.Contains(dstIP) { + if dstIP := dstAddr.Addr(); viaRange.Contains(dstIP) { dstAddr = netaddr.IPPortFrom(tsaddr.UnmapVia(dstIP), dstAddr.Port()) } - backendRemoteAddr = dstAddr.UDPAddr() - if dstAddr.IP().Is4() { + backendRemoteAddr = net.UDPAddrFromAddrPort(dstAddr) + if dstAddr.Addr().Is4() { backendListenAddr = &net.UDPAddr{IP: net.ParseIP("0.0.0.0"), Port: int(srcPort)} } else { backendListenAddr = &net.UDPAddr{IP: net.ParseIP("::"), Port: int(srcPort)} @@ -981,7 +981,7 @@ func (ns *Impl) forwardUDP(client *gonet.UDPConn, wq *waiter.Queue, clientAddr, ns.logf("could not get backend local IP:port from %v:%v", backendLocalAddr.IP, backendLocalAddr.Port) } if isLocal { - ns.e.RegisterIPPortIdentity(backendLocalIPPort, dstAddr.IP()) + ns.e.RegisterIPPortIdentity(backendLocalIPPort, dstAddr.Addr()) } ctx, cancel := context.WithCancel(context.Background()) @@ -1007,13 +1007,13 @@ func (ns *Impl) forwardUDP(client *gonet.UDPConn, wq *waiter.Queue, clientAddr, extend := func() { timer.Reset(idleTimeout) } - startPacketCopy(ctx, cancel, client, clientAddr.UDPAddr(), backendConn, ns.logf, extend) + startPacketCopy(ctx, cancel, client, net.UDPAddrFromAddrPort(clientAddr), backendConn, ns.logf, extend) startPacketCopy(ctx, cancel, backendConn, backendRemoteAddr, client, ns.logf, extend) if isLocal { // Wait for the copies to be done before decrementing the // subnet address count to potentially remove the route. <-ctx.Done() - ns.removeSubnetAddress(dstAddr.IP()) + ns.removeSubnetAddress(dstAddr.Addr()) } } diff --git a/wgengine/netstack/netstack_test.go b/wgengine/netstack/netstack_test.go index 12dbe567e..1bfb7a543 100644 --- a/wgengine/netstack/netstack_test.go +++ b/wgengine/netstack/netstack_test.go @@ -9,7 +9,7 @@ import ( "testing" "gvisor.dev/gvisor/pkg/refs" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsdial" "tailscale.com/net/tstun" diff --git a/wgengine/pendopen.go b/wgengine/pendopen.go index c96252e0b..c614faf80 100644 --- a/wgengine/pendopen.go +++ b/wgengine/pendopen.go @@ -104,8 +104,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 _, ok := e.PeerForIP(flow.Dst.IP()); !ok { + if runtime.GOOS == "ios" && flow.Dst.Port() == 443 && !tsaddr.IsTailscaleIP(flow.Dst.Addr()) { + if _, ok := e.PeerForIP(flow.Dst.Addr()); !ok { return } } @@ -142,7 +142,7 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) { } // Diagnose why it might've timed out. - pip, ok := e.PeerForIP(flow.Dst.IP()) + pip, ok := e.PeerForIP(flow.Dst.Addr()) if !ok { e.logf("open-conn-track: timeout opening %v; no associated peer node", flow) return @@ -172,7 +172,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.Addr()) { onlyZeroRoute = false break } diff --git a/wgengine/router/ifconfig_windows.go b/wgengine/router/ifconfig_windows.go index 6e5c23907..e81c8d3ab 100644 --- a/wgengine/router/ifconfig_windows.go +++ b/wgengine/router/ifconfig_windows.go @@ -11,17 +11,19 @@ import ( "fmt" "log" "net" + "net/netip" "runtime" "sort" "time" ole "github.com/go-ole/go-ole" + "go4.org/netipx" "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" - "inet.af/netaddr" "tailscale.com/health" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/util/multierr" "tailscale.com/wgengine/winnet" @@ -326,16 +328,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.Addr().Is4() && ipif4 == nil) || (addr.Addr().Is6() && ipif6 == nil) { // Can't program addresses for disabled protocol. continue } - ipnet := addr.IPNet() + ipnet := netipx.PrefixIPNet(addr) addresses = append(addresses, ipnet) gateway := ipnet.IP - if addr.IP().Is4() && firstGateway4 == nil { + if addr.Addr().Is4() && firstGateway4 == nil { firstGateway4 = &gateway - } else if addr.IP().Is6() && firstGateway6 == nil { + } else if addr.Addr().Is6() && firstGateway6 == nil { firstGateway6 = &gateway } } @@ -344,31 +346,31 @@ 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.Addr().Is4() && ipif4 == nil) || (route.Addr().Is6() && ipif6 == nil) { // Can't program routes for disabled protocol. continue } - if route.IP().Is6() && firstGateway6 == nil { + if route.Addr().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 // even if the v6 overlay network isn't configured. To do // that, we add a dummy local IPv6 address to serve as a // route source. - ipnet := &net.IPNet{tsaddr.Tailscale4To6Placeholder().IPAddr().IP, net.CIDRMask(128, 128)} + ipnet := &net.IPNet{tsaddr.Tailscale4To6Placeholder().AsSlice(), net.CIDRMask(128, 128)} addresses = append(addresses, ipnet) firstGateway6 = &ipnet.IP - } else if route.IP().Is4() && firstGateway4 == nil { + } else if route.Addr().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() + ipn := netipx.PrefixIPNet(route) var gateway net.IP - if route.IP().Is4() { + if route.Addr().Is4() { gateway = *firstGateway4 - } else if route.IP().Is6() { + } else if route.Addr().Is6() { gateway = *firstGateway6 } r := winipcfg.RouteData{ @@ -387,12 +389,12 @@ 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.Addr().Is4() { if route.Bits() == 0 { foundDefault4 = true } r.NextHop = *firstGateway4 - } else if route.IP().Is6() { + } else if route.Addr().Is6() { if route.Bits() == 0 { foundDefault6 = true } @@ -782,8 +784,8 @@ func filterRoutes(routes []*winipcfg.RouteData, dontDelete []netaddr.IPPrefix) [ if nr.IsSingleIP() { continue } - lastIP := nr.Range().To() - ddm[netaddr.IPPrefixFrom(lastIP, lastIP.BitLen())] = true + lastIP := netipx.RangeOfPrefix(nr).To() + ddm[netip.PrefixFrom(lastIP, lastIP.BitLen())] = true } filtered := make([]*winipcfg.RouteData, 0, len(routes)) for _, r := range routes { diff --git a/wgengine/router/ifconfig_windows_test.go b/wgengine/router/ifconfig_windows_test.go index d6d8cc8ff..bf38c80e8 100644 --- a/wgengine/router/ifconfig_windows_test.go +++ b/wgengine/router/ifconfig_windows_test.go @@ -11,8 +11,9 @@ import ( "strings" "testing" + "go4.org/netipx" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" - "inet.af/netaddr" + "tailscale.com/net/netaddr" ) func randIP() net.IP { @@ -38,7 +39,7 @@ func TestRouteLess(t *testing.T) { if err != nil { t.Fatalf("error parsing test data %q: %v", s, err) } - return *ipp.IPNet() + return *netipx.PrefixIPNet(ipp) } tests := []struct { diff --git a/wgengine/router/router.go b/wgengine/router/router.go index b71ae839e..0e2acf146 100644 --- a/wgengine/router/router.go +++ b/wgengine/router/router.go @@ -10,7 +10,7 @@ import ( "reflect" "golang.zx2c4.com/wireguard/tun" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" "tailscale.com/types/preftype" "tailscale.com/wgengine/monitor" diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index 8925aae16..51c210bcc 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -18,11 +18,12 @@ import ( "github.com/coreos/go-iptables/iptables" "github.com/tailscale/netlink" + "go4.org/netipx" "golang.org/x/sys/unix" "golang.org/x/time/rate" "golang.zx2c4.com/wireguard/tun" - "inet.af/netaddr" "tailscale.com/envknob" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/syncs" "tailscale.com/types/logger" @@ -439,7 +440,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.Addr()); err != nil { return err } } @@ -451,7 +452,7 @@ 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.Addr().Is6() { return nil } if r.useIPCommand() { @@ -467,7 +468,7 @@ func (r *linuxRouter) addAddress(addr netaddr.IPPrefix) error { return fmt.Errorf("adding address %v from tunnel interface: %w", addr, err) } } - if err := r.addLoopbackRule(addr.IP()); err != nil { + if err := r.addLoopbackRule(addr.Addr()); err != nil { return err } return nil @@ -477,10 +478,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.Addr().Is6() { return nil } - if err := r.delLoopbackRule(addr.IP()); err != nil { + if err := r.delLoopbackRule(addr.Addr()); err != nil { return err } if r.useIPCommand() { @@ -547,7 +548,7 @@ func (r *linuxRouter) delLoopbackRule(addr netaddr.IP) error { // interface. Fails if the route already exists, or if adding the // route fails. func (r *linuxRouter) addRoute(cidr netaddr.IPPrefix) error { - if !r.v6Available && cidr.IP().Is6() { + if !r.v6Available && cidr.Addr().Is6() { return nil } if r.useIPCommand() { @@ -559,7 +560,7 @@ func (r *linuxRouter) addRoute(cidr netaddr.IPPrefix) error { } return netlink.RouteReplace(&netlink.Route{ LinkIndex: linkIndex, - Dst: cidr.Masked().IPNet(), + Dst: netipx.PrefixIPNet(cidr.Masked()), Table: r.routeTable(), }) } @@ -572,14 +573,14 @@ func (r *linuxRouter) addThrowRoute(cidr netaddr.IPPrefix) error { if !r.ipRuleAvailable { return nil } - if !r.v6Available && cidr.IP().Is6() { + if !r.v6Available && cidr.Addr().Is6() { return nil } if r.useIPCommand() { return r.addRouteDef([]string{"throw", normalizeCIDR(cidr)}, cidr) } err := netlink.RouteReplace(&netlink.Route{ - Dst: cidr.Masked().IPNet(), + Dst: netipx.PrefixIPNet(cidr.Masked()), Table: tailscaleRouteTable.num, Type: unix.RTN_THROW, }) @@ -590,7 +591,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.Addr().Is6() { return nil } args := append([]string{"ip", "route", "add"}, routeDef...) @@ -624,7 +625,7 @@ var ( // interface. Fails if the route doesn't exist, or if removing the // route fails. func (r *linuxRouter) delRoute(cidr netaddr.IPPrefix) error { - if !r.v6Available && cidr.IP().Is6() { + if !r.v6Available && cidr.Addr().Is6() { return nil } if r.useIPCommand() { @@ -636,7 +637,7 @@ func (r *linuxRouter) delRoute(cidr netaddr.IPPrefix) error { } err = netlink.RouteDel(&netlink.Route{ LinkIndex: linkIndex, - Dst: cidr.Masked().IPNet(), + Dst: netipx.PrefixIPNet(cidr.Masked()), Table: r.routeTable(), }) if errors.Is(err, errESRCH) { @@ -652,14 +653,14 @@ func (r *linuxRouter) delThrowRoute(cidr netaddr.IPPrefix) error { if !r.ipRuleAvailable { return nil } - if !r.v6Available && cidr.IP().Is6() { + if !r.v6Available && cidr.Addr().Is6() { return nil } if r.useIPCommand() { return r.delRouteDef([]string{"throw", normalizeCIDR(cidr)}, cidr) } err := netlink.RouteDel(&netlink.Route{ - Dst: cidr.Masked().IPNet(), + Dst: netipx.PrefixIPNet(cidr.Masked()), Table: r.routeTable(), Type: unix.RTN_THROW, }) @@ -671,7 +672,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.Addr().Is6() { return nil } args := append([]string{"ip", "route", "del"}, routeDef...) @@ -701,7 +702,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.Addr()), "route", "show"}, routeDef...) if r.ipRuleAvailable { args = append(args, "table", tailscaleRouteTable.ipCmdArg()) } @@ -1549,6 +1550,6 @@ func checkIPRuleSupportsV6(logf logger.Logf) error { func nlAddrOfPrefix(p netaddr.IPPrefix) *netlink.Addr { return &netlink.Addr{ - IPNet: p.IPNet(), + IPNet: netipx.PrefixIPNet(p), } } diff --git a/wgengine/router/router_linux_test.go b/wgengine/router/router_linux_test.go index d78b314f7..0e6718639 100644 --- a/wgengine/router/router_linux_test.go +++ b/wgengine/router/router_linux_test.go @@ -17,7 +17,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/vishvananda/netlink" "golang.zx2c4.com/wireguard/tun" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/types/logger" "tailscale.com/wgengine/monitor" diff --git a/wgengine/router/router_openbsd.go b/wgengine/router/router_openbsd.go index 995125564..561e3783a 100644 --- a/wgengine/router/router_openbsd.go +++ b/wgengine/router/router_openbsd.go @@ -10,8 +10,9 @@ import ( "log" "os/exec" + "go4.org/netipx" "golang.zx2c4.com/wireguard/tun" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" "tailscale.com/wgengine/monitor" ) @@ -59,7 +60,7 @@ func (r *openbsdRouter) Up() error { } func inet(p netaddr.IPPrefix) string { - if p.IP().Is6() { + if p.Addr().Is6() { return "inet6" } return "inet" @@ -79,11 +80,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.Addr().Is4() { numIPv4++ localAddr4 = addr } - if addr.IP().Is6() { + if addr.Addr().Is6() { numIPv6++ localAddr6 = addr } @@ -95,7 +96,7 @@ func (r *openbsdRouter) Set(cfg *Config) error { var errq error if localAddr4 != r.local4 { - if !r.local4.IsZero() { + if r.local4.IsValid() { addrdel := []string{"ifconfig", r.tunname, "inet", r.local4.String(), "-alias"} out, err := cmd(addrdel...).CombinedOutput() @@ -108,7 +109,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.Addr().String()} if out, err := cmd(routedel...).CombinedOutput(); err != nil { r.logf("route del failed: %v: %v\n%s", routedel, err, out) if errq == nil { @@ -117,7 +118,7 @@ func (r *openbsdRouter) Set(cfg *Config) error { } } - if !localAddr4.IsZero() { + if localAddr4.IsValid() { addradd := []string{"ifconfig", r.tunname, "inet", localAddr4.String(), "alias"} out, err := cmd(addradd...).CombinedOutput() @@ -130,7 +131,7 @@ func (r *openbsdRouter) Set(cfg *Config) error { routeadd := []string{"route", "-q", "-n", "add", "-inet", localAddr4.String(), - "-iface", localAddr4.IP().String()} + "-iface", localAddr4.Addr().String()} if out, err := cmd(routeadd...).CombinedOutput(); err != nil { r.logf("route add failed: %v: %v\n%s", routeadd, err, out) if errq == nil { @@ -140,15 +141,15 @@ func (r *openbsdRouter) Set(cfg *Config) error { } } - if !localAddr6.IsZero() { + if localAddr6.IsValid() { // 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.IPPrefixFrom(localAddr6.IP(), 48) + localAddr6 = netaddr.IPPrefixFrom(localAddr6.Addr(), 48) } if localAddr6 != r.local6 { - if !r.local6.IsZero() { + if r.local6.IsValid() { addrdel := []string{"ifconfig", r.tunname, "inet6", r.local6.String(), "delete"} out, err := cmd(addrdel...).CombinedOutput() @@ -160,7 +161,7 @@ func (r *openbsdRouter) Set(cfg *Config) error { } } - if !localAddr6.IsZero() { + if localAddr6.IsValid() { addradd := []string{"ifconfig", r.tunname, "inet6", localAddr6.String()} out, err := cmd(addradd...).CombinedOutput() @@ -179,12 +180,12 @@ func (r *openbsdRouter) Set(cfg *Config) error { } for route := range r.routes { if _, keep := newRoutes[route]; !keep { - net := route.IPNet() + net := netipx.PrefixIPNet(route) nip := net.IP.Mask(net.Mask) nstr := fmt.Sprintf("%v/%d", nip, route.Bits()) - dst := localAddr4.IP().String() - if route.IP().Is6() { - dst = localAddr6.IP().String() + dst := localAddr4.Addr().String() + if route.Addr().Is6() { + dst = localAddr6.Addr().String() } routedel := []string{"route", "-q", "-n", "del", "-" + inet(route), nstr, @@ -200,12 +201,12 @@ func (r *openbsdRouter) Set(cfg *Config) error { } for route := range newRoutes { if _, exists := r.routes[route]; !exists { - net := route.IPNet() + net := netipx.PrefixIPNet(route) nip := net.IP.Mask(net.Mask) nstr := fmt.Sprintf("%v/%d", nip, route.Bits()) - dst := localAddr4.IP().String() - if route.IP().Is6() { - dst = localAddr6.IP().String() + dst := localAddr4.Addr().String() + if route.Addr().Is6() { + dst = localAddr6.Addr().String() } routeadd := []string{"route", "-q", "-n", "add", "-" + inet(route), nstr, diff --git a/wgengine/router/router_test.go b/wgengine/router/router_test.go index fe068602c..e57049c06 100644 --- a/wgengine/router/router_test.go +++ b/wgengine/router/router_test.go @@ -8,7 +8,7 @@ import ( "reflect" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/preftype" ) diff --git a/wgengine/router/router_userspace_bsd.go b/wgengine/router/router_userspace_bsd.go index 93cbdadc7..5e374b3f5 100644 --- a/wgengine/router/router_userspace_bsd.go +++ b/wgengine/router/router_userspace_bsd.go @@ -13,8 +13,9 @@ import ( "os/exec" "runtime" + "go4.org/netipx" "golang.zx2c4.com/wireguard/tun" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" "tailscale.com/version" @@ -91,7 +92,7 @@ func (r *userspaceBSDRouter) Up() error { } func inet(p netaddr.IPPrefix) string { - if p.IP().Is6() { + if p.Addr().Is6() { return "inet6" } return "inet" @@ -120,15 +121,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.Addr().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.IPPrefixFrom(addr.IP(), 48) + tmp := netaddr.IPPrefixFrom(addr.Addr(), 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.Addr().String()} } out, err := cmd(arg...).CombinedOutput() if err != nil { @@ -150,7 +151,7 @@ func (r *userspaceBSDRouter) Set(cfg *Config) (reterr error) { // Delete any pre-existing routes. for route := range r.routes { if _, keep := newRoutes[route]; !keep { - net := route.IPNet() + net := netipx.PrefixIPNet(route) nip := net.IP.Mask(net.Mask) nstr := fmt.Sprintf("%v/%d", nip, route.Bits()) del := "del" @@ -170,7 +171,7 @@ func (r *userspaceBSDRouter) Set(cfg *Config) (reterr error) { // Add the routes. for route := range newRoutes { if _, exists := r.routes[route]; !exists { - net := route.IPNet() + net := netipx.PrefixIPNet(route) nip := net.IP.Mask(net.Mask) nstr := fmt.Sprintf("%v/%d", nip, route.Bits()) routeadd := []string{"route", "-q", "-n", diff --git a/wgengine/router/router_windows.go b/wgengine/router/router_windows.go index f9cf66269..58ab7fc1d 100644 --- a/wgengine/router/router_windows.go +++ b/wgengine/router/router_windows.go @@ -20,9 +20,9 @@ import ( "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" - "inet.af/netaddr" "tailscale.com/logtail/backoff" "tailscale.com/net/dns" + "tailscale.com/net/netaddr" "tailscale.com/types/logger" "tailscale.com/wgengine/monitor" ) diff --git a/wgengine/userspace.go b/wgengine/userspace.go index d589eabae..4ee52ea1d 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -12,6 +12,7 @@ import ( "fmt" "io" "net" + "net/netip" "reflect" "runtime" "strings" @@ -22,7 +23,6 @@ import ( "go4.org/mem" "golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/tun" - "inet.af/netaddr" "tailscale.com/control/controlclient" "tailscale.com/envknob" "tailscale.com/health" @@ -31,6 +31,7 @@ import ( "tailscale.com/net/dns/resolver" "tailscale.com/net/flowtrack" "tailscale.com/net/interfaces" + "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" @@ -486,7 +487,7 @@ func (e *userspaceEngine) handleLocalPackets(p *packet.Parsed, t *tstun.Wrapper) // Handle traffic to the service IP. // TODO(tom): Netstack handles this when it is installed. Rip all // this out once netstack is used on all platforms. - switch p.Dst.IP() { + switch p.Dst.Addr() { case magicDNSIP, magicDNSIPv6: err := e.dns.EnqueuePacket(append([]byte(nil), p.Payload()...), p.IPProto, p.Src, p.Dst) if err != nil { @@ -500,7 +501,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.Addr()) { // 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 @@ -690,8 +691,8 @@ func (e *userspaceEngine) maybeReconfigWireguardLocked(discoChanged map[key.Node trackNodes = append(trackNodes, nk) recentlyActive := false for _, cidr := range p.AllowedIPs { - trackIPs = append(trackIPs, cidr.IP()) - recentlyActive = recentlyActive || e.isActiveSinceLocked(nk, cidr.IP(), activeCutoff) + trackIPs = append(trackIPs, cidr.Addr()) + recentlyActive = recentlyActive || e.isActiveSinceLocked(nk, cidr.Addr(), activeCutoff) } if recentlyActive { min.Peers = append(min.Peers, *p) @@ -1324,8 +1325,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.Addr().BitLen() == dst.BitLen() { + return a.Addr(), nil } } if len(e.netMap.Addresses) == 0 { @@ -1518,13 +1519,13 @@ func (e *userspaceEngine) PeerForIP(ip netaddr.IP) (ret PeerForIP, ok bool) { // TODO(bradfitz): add maps for these. on NetworkMap? for _, p := range nm.Peers { for _, a := range p.Addresses { - if a.IP() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) { + if a.Addr() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) { return PeerForIP{Node: p, Route: a}, true } } } for _, a := range nm.Addresses { - if a.IP() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) { + if a.Addr() == ip && a.IsSingleIP() && tsaddr.IsTailscaleIP(ip) { return PeerForIP{Node: nm.SelfNode, IsSelf: true, Route: a}, true } } @@ -1540,7 +1541,7 @@ func (e *userspaceEngine) PeerForIP(ip netaddr.IP) (ret PeerForIP, ok bool) { if !cidr.Contains(ip) { continue } - if best.IsZero() || cidr.Bits() > best.Bits() { + if !best.IsValid() || cidr.Bits() > best.Bits() { best = cidr bestKey = p.PublicKey } @@ -1591,7 +1592,7 @@ func dnsIPsOverTailscale(dnsCfg *dns.Config, routerCfg *router.Config) (ret []ne ip, err := netaddr.ParseIP(r.Addr) if err != nil { if ipp, err := netaddr.ParseIPPort(r.Addr); err == nil { - ip = ipp.IP() + ip = ipp.Addr() } else { continue } @@ -1609,7 +1610,7 @@ func dnsIPsOverTailscale(dnsCfg *dns.Config, routerCfg *router.Config) (ret []ne ret = make([]netaddr.IPPrefix, 0, len(m)) for ip := range m { - ret = append(ret, netaddr.IPPrefixFrom(ip, ip.BitLen())) + ret = append(ret, netip.PrefixFrom(ip, ip.BitLen())) } return ret } diff --git a/wgengine/userspace_test.go b/wgengine/userspace_test.go index 825645d0e..8314c7cc0 100644 --- a/wgengine/userspace_test.go +++ b/wgengine/userspace_test.go @@ -10,8 +10,8 @@ import ( "testing" "go4.org/mem" - "inet.af/netaddr" "tailscale.com/net/dns" + "tailscale.com/net/netaddr" "tailscale.com/net/tstun" "tailscale.com/tailcfg" "tailscale.com/tstest" diff --git a/wgengine/watchdog.go b/wgengine/watchdog.go index a0c94797c..2248535d3 100644 --- a/wgengine/watchdog.go +++ b/wgengine/watchdog.go @@ -13,11 +13,11 @@ import ( "strings" "time" - "inet.af/netaddr" "tailscale.com/envknob" "tailscale.com/ipn/ipnstate" "tailscale.com/net/dns" "tailscale.com/net/dns/resolver" + "tailscale.com/net/netaddr" "tailscale.com/net/tstun" "tailscale.com/tailcfg" "tailscale.com/types/key" diff --git a/wgengine/wgcfg/config.go b/wgengine/wgcfg/config.go index 1733d7335..e086aaf1c 100644 --- a/wgengine/wgcfg/config.go +++ b/wgengine/wgcfg/config.go @@ -6,7 +6,7 @@ package wgcfg import ( - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/key" ) diff --git a/wgengine/wgcfg/device_test.go b/wgengine/wgcfg/device_test.go index f78898af3..af07c75e9 100644 --- a/wgengine/wgcfg/device_test.go +++ b/wgengine/wgcfg/device_test.go @@ -19,7 +19,7 @@ import ( "golang.zx2c4.com/wireguard/conn" "golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/tun" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/key" ) diff --git a/wgengine/wgcfg/nmcfg/nmcfg.go b/wgengine/wgcfg/nmcfg/nmcfg.go index fbd4cba69..00c1aed08 100644 --- a/wgengine/wgcfg/nmcfg/nmcfg.go +++ b/wgengine/wgcfg/nmcfg/nmcfg.go @@ -10,7 +10,7 @@ import ( "fmt" "strings" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/logger" @@ -92,11 +92,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.Addr()) && (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.Addr(), nodeDebugName(peer), peer.Key.ShortString()) continue } else if cidrIsSubnet(peer, allowedIP) { if (flags & netmap.AllowSubnetRoutes) == 0 { diff --git a/wgengine/wgcfg/parser.go b/wgengine/wgcfg/parser.go index e112f4f70..2cbd83b4e 100644 --- a/wgengine/wgcfg/parser.go +++ b/wgengine/wgcfg/parser.go @@ -13,7 +13,7 @@ import ( "strings" "go4.org/mem" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/key" ) diff --git a/wgengine/wgcfg/parser_test.go b/wgengine/wgcfg/parser_test.go index a3331ec6e..145070104 100644 --- a/wgengine/wgcfg/parser_test.go +++ b/wgengine/wgcfg/parser_test.go @@ -12,7 +12,7 @@ import ( "runtime" "testing" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/key" ) diff --git a/wgengine/wgcfg/wgcfg_clone.go b/wgengine/wgcfg/wgcfg_clone.go index 373a94660..6b4d0dbad 100644 --- a/wgengine/wgcfg/wgcfg_clone.go +++ b/wgengine/wgcfg/wgcfg_clone.go @@ -7,7 +7,8 @@ package wgcfg import ( - "inet.af/netaddr" + "net/netip" + "tailscale.com/types/key" ) @@ -32,9 +33,9 @@ func (src *Config) Clone() *Config { var _ConfigCloneNeedsRegeneration = Config(struct { Name string PrivateKey key.NodePrivate - Addresses []netaddr.IPPrefix + Addresses []netip.Prefix MTU uint16 - DNS []netaddr.IP + DNS []netip.Addr Peers []Peer }{}) @@ -54,7 +55,7 @@ func (src *Peer) Clone() *Peer { var _PeerCloneNeedsRegeneration = Peer(struct { PublicKey key.NodePublic DiscoKey key.DiscoPublic - AllowedIPs []netaddr.IPPrefix + AllowedIPs []netip.Prefix PersistentKeepalive uint16 WGEndpoint key.NodePublic }{}) diff --git a/wgengine/wgcfg/writer.go b/wgengine/wgcfg/writer.go index ce26d794a..9ad123800 100644 --- a/wgengine/wgcfg/writer.go +++ b/wgengine/wgcfg/writer.go @@ -9,7 +9,7 @@ import ( "io" "strconv" - "inet.af/netaddr" + "tailscale.com/net/netaddr" "tailscale.com/types/key" "tailscale.com/types/logger" ) diff --git a/wgengine/wgengine.go b/wgengine/wgengine.go index 773c9bf13..2923a3cb0 100644 --- a/wgengine/wgengine.go +++ b/wgengine/wgengine.go @@ -8,9 +8,9 @@ import ( "errors" "time" - "inet.af/netaddr" "tailscale.com/ipn/ipnstate" "tailscale.com/net/dns" + "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/netmap"