diff --git a/client/tailscale/acl.go b/client/tailscale/acl.go index 53274c9d0..dd28ef401 100644 --- a/client/tailscale/acl.go +++ b/client/tailscale/acl.go @@ -13,8 +13,7 @@ "encoding/json" "fmt" "net/http" - - "tailscale.com/net/netaddr" + "net/netip" ) // ACLRow defines a rule that grants access by a set of users or groups to a set @@ -354,7 +353,7 @@ func (c *Client) PreviewACLForUser(ctx context.Context, acl ACL, user string) (r // Returns ACLPreview on success with matches in a slice. If there are no matches, // the call is still successful but Matches will be an empty slice. // Returns error if the provided ACL is invalid. -func (c *Client) PreviewACLForIPPort(ctx context.Context, acl ACL, ipport netaddr.IPPort) (res *ACLPreview, err error) { +func (c *Client) PreviewACLForIPPort(ctx context.Context, acl ACL, ipport netip.AddrPort) (res *ACLPreview, err error) { // Format return errors to be descriptive. defer func() { if err != nil { diff --git a/client/tailscale/localclient.go b/client/tailscale/localclient.go index da7ce2430..27289b6d0 100644 --- a/client/tailscale/localclient.go +++ b/client/tailscale/localclient.go @@ -19,6 +19,7 @@ "net" "net/http" "net/http/httptrace" + "net/netip" "net/url" "os/exec" "runtime" @@ -31,7 +32,6 @@ "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" @@ -665,7 +665,7 @@ func (lc *LocalClient) ExpandSNIName(ctx context.Context, name string) (fqdn str // Ping sends a ping of the provided type to the provided IP and waits // for its response. -func (lc *LocalClient) Ping(ctx context.Context, ip netaddr.IP, pingtype tailcfg.PingType) (*ipnstate.PingResult, error) { +func (lc *LocalClient) Ping(ctx context.Context, ip netip.Addr, pingtype tailcfg.PingType) (*ipnstate.PingResult, error) { v := url.Values{} v.Set("ip", ip.String()) v.Set("type", string(pingtype)) diff --git a/client/tailscale/routes.go b/client/tailscale/routes.go index 70e10aa1e..067fb2e20 100644 --- a/client/tailscale/routes.go +++ b/client/tailscale/routes.go @@ -13,15 +13,14 @@ "encoding/json" "fmt" "net/http" - - "tailscale.com/net/netaddr" + "net/netip" ) // Routes contains the lists of subnet routes that are currently advertised by a device, // as well as the subnets that are enabled to be routed by the device. type Routes struct { - AdvertisedRoutes []netaddr.IPPrefix `json:"advertisedRoutes"` - EnabledRoutes []netaddr.IPPrefix `json:"enabledRoutes"` + AdvertisedRoutes []netip.Prefix `json:"advertisedRoutes"` + EnabledRoutes []netip.Prefix `json:"enabledRoutes"` } // Routes retrieves the list of subnet routes that have been enabled for a device. @@ -56,14 +55,14 @@ func (c *Client) Routes(ctx context.Context, deviceID string) (routes *Routes, e } type postRoutesParams struct { - Routes []netaddr.IPPrefix `json:"routes"` + Routes []netip.Prefix `json:"routes"` } // SetRoutes updates the list of subnets that are enabled for a device. // Subnets must be parsable by net/netip.ParsePrefix. // 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) { +func (c *Client) SetRoutes(ctx context.Context, deviceID string, subnets []netip.Prefix) (routes *Routes, err error) { defer func() { if err != nil { err = fmt.Errorf("tailscale.SetRoutes: %w", err) diff --git a/cmd/tailscale/cli/cli_test.go b/cmd/tailscale/cli/cli_test.go index 3bb35e178..736f19058 100644 --- a/cmd/tailscale/cli/cli_test.go +++ b/cmd/tailscale/cli/cli_test.go @@ -18,7 +18,6 @@ "github.com/google/go-cmp/cmp" "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" - "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/types/persist" "tailscale.com/types/preftype" @@ -57,7 +56,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { flags []string // argv to be parsed by FlagSet curPrefs *ipn.Prefs - curExitNodeIP netaddr.IP + curExitNodeIP netip.Addr curUser string // os.Getenv("USER") on the client side goos string // empty means "linux" distro distro.Distro @@ -153,7 +152,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { AllowSingleHosts: true, CorpDNS: true, NetfilterMode: preftype.NetfilterOn, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("10.0.42.0/24"), netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), @@ -169,7 +168,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { AllowSingleHosts: true, CorpDNS: true, NetfilterMode: preftype.NetfilterOn, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("10.0.42.0/24"), netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), @@ -185,7 +184,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { AllowSingleHosts: true, CorpDNS: true, NetfilterMode: preftype.NetfilterOn, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("10.0.42.0/24"), netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), @@ -213,7 +212,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { CorpDNS: true, NetfilterMode: preftype.NetfilterOn, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("1.2.0.0/16"), }, }, @@ -227,7 +226,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { AllowSingleHosts: true, CorpDNS: true, NetfilterMode: preftype.NetfilterOn, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), netip.MustParsePrefix("1.2.0.0/16"), @@ -262,7 +261,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { AdvertiseTags: []string{"tag:foo", "tag:bar"}, Hostname: "myhostname", ForceDaemon: true, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("10.0.0.0/16"), netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), @@ -287,7 +286,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { AdvertiseTags: []string{"tag:foo", "tag:bar"}, Hostname: "myhostname", ForceDaemon: true, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("10.0.0.0/16"), }, NetfilterMode: preftype.NetfilterNoDivert, @@ -345,7 +344,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { AllowSingleHosts: true, CorpDNS: true, NetfilterMode: preftype.NetfilterOn, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), netip.MustParsePrefix("1.2.0.0/16"), @@ -361,7 +360,7 @@ func TestCheckForAccidentalSettingReverts(t *testing.T) { AllowSingleHosts: true, CorpDNS: true, NetfilterMode: preftype.NetfilterOn, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), netip.MustParsePrefix("1.2.0.0/16"), @@ -563,7 +562,7 @@ func TestPrefsFromUpArgs(t *testing.T) { WantRunning: true, AllowSingleHosts: true, CorpDNS: true, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), }, @@ -632,7 +631,7 @@ func TestPrefsFromUpArgs(t *testing.T) { exitNodeIP: "100.105.106.107", }, st: &ipnstate.Status{ - TailscaleIPs: []netaddr.IP{netip.MustParseAddr("100.105.106.107")}, + TailscaleIPs: []netip.Addr{netip.MustParseAddr("100.105.106.107")}, }, wantErr: `cannot use 100.105.106.107 as an exit node as it is a local IP address to this machine; did you mean --advertise-exit-node?`, }, @@ -672,7 +671,7 @@ func TestPrefsFromUpArgs(t *testing.T) { want: &ipn.Prefs{ WantRunning: true, NoSNAT: true, - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("fd7a:115c:a1e0:b1a::bb:10.0.0.0/112"), }, }, @@ -957,7 +956,7 @@ func TestUpdatePrefs(t *testing.T) { } } -var cmpIP = cmp.Comparer(func(a, b netaddr.IP) bool { +var cmpIP = cmp.Comparer(func(a, b netip.Addr) bool { return a == b }) diff --git a/cmd/tailscale/cli/file.go b/cmd/tailscale/cli/file.go index 9cbe2534e..4b29ddbc7 100644 --- a/cmd/tailscale/cli/file.go +++ b/cmd/tailscale/cli/file.go @@ -27,7 +27,6 @@ "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" @@ -192,7 +191,7 @@ func getTargetStableID(ctx context.Context, ipStr string) (id tailcfg.StableNode // fileTargetErrorDetail returns a non-nil error saying why ip is an // invalid file sharing target. -func fileTargetErrorDetail(ctx context.Context, ip netaddr.IP) error { +func fileTargetErrorDetail(ctx context.Context, ip netip.Addr) error { found := false if st, err := localClient.Status(ctx); err == nil && st.Self != nil { for _, peer := range st.Peer { diff --git a/cmd/tailscale/cli/status.go b/cmd/tailscale/cli/status.go index 34f83ccd3..830b2f000 100644 --- a/cmd/tailscale/cli/status.go +++ b/cmd/tailscale/cli/status.go @@ -13,6 +13,7 @@ "fmt" "net" "net/http" + "net/netip" "os" "strings" @@ -21,7 +22,6 @@ "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" "tailscale.com/net/interfaces" - "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) @@ -260,7 +260,7 @@ func ownerLogin(st *ipnstate.Status, ps *ipnstate.PeerStatus) string { return u.LoginName } -func firstIPString(v []netaddr.IP) string { +func firstIPString(v []netip.Addr) string { if len(v) == 0 { return "" } diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index 683b90ed9..36dcf4d86 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -27,7 +27,6 @@ qrcode "github.com/skip2/go-qrcode" "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" - "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/safesocket" "tailscale.com/tailcfg" @@ -204,7 +203,7 @@ func warnf(format string, args ...any) { ipv6default = netip.MustParsePrefix("::/0") ) -func validateViaPrefix(ipp netaddr.IPPrefix) error { +func validateViaPrefix(ipp netip.Prefix) error { if !tsaddr.IsViaPrefix(ipp) { return fmt.Errorf("%v is not a 4-in-6 prefix", ipp) } @@ -224,8 +223,8 @@ func validateViaPrefix(ipp netaddr.IPPrefix) error { return nil } -func calcAdvertiseRoutes(advertiseRoutes string, advertiseDefaultRoute bool) ([]netaddr.IPPrefix, error) { - routeMap := map[netaddr.IPPrefix]bool{} +func calcAdvertiseRoutes(advertiseRoutes string, advertiseDefaultRoute bool) ([]netip.Prefix, error) { + routeMap := map[netip.Prefix]bool{} if advertiseRoutes != "" { var default4, default6 bool advroutes := strings.Split(advertiseRoutes, ",") @@ -259,7 +258,7 @@ func calcAdvertiseRoutes(advertiseRoutes string, advertiseDefaultRoute bool) ([] routeMap[netip.MustParsePrefix("0.0.0.0/0")] = true routeMap[netip.MustParsePrefix("::/0")] = true } - routes := make([]netaddr.IPPrefix, 0, len(routeMap)) + routes := make([]netip.Prefix, 0, len(routeMap)) for r := range routeMap { routes = append(routes, r) } @@ -791,7 +790,7 @@ type upCheckEnv struct { flagSet *flag.FlagSet upArgs upArgsT backendState string - curExitNodeIP netaddr.IP + curExitNodeIP netip.Addr distro distro.Distro } @@ -992,7 +991,7 @@ func fmtFlagValueArg(flagName string, val any) string { return fmt.Sprintf("--%s=%v", flagName, shellquote.Join(fmt.Sprint(val))) } -func hasExitNodeRoutes(rr []netaddr.IPPrefix) bool { +func hasExitNodeRoutes(rr []netip.Prefix) bool { var v4, v6 bool for _, r := range rr { if r.Bits() == 0 { @@ -1009,11 +1008,11 @@ func hasExitNodeRoutes(rr []netaddr.IPPrefix) bool { // withoutExitNodes returns rr unchanged if it has only 1 or 0 /0 // routes. If it has both IPv4 and IPv6 /0 routes, then it returns // a copy with all /0 routes removed. -func withoutExitNodes(rr []netaddr.IPPrefix) []netaddr.IPPrefix { +func withoutExitNodes(rr []netip.Prefix) []netip.Prefix { if !hasExitNodeRoutes(rr) { return rr } - var out []netaddr.IPPrefix + var out []netip.Prefix for _, r := range rr { if r.Bits() > 0 { out = append(out, r) @@ -1024,7 +1023,7 @@ func withoutExitNodes(rr []netaddr.IPPrefix) []netaddr.IPPrefix { // exitNodeIP returns the exit node IP from p, using st to map // it from its ID form to an IP address if needed. -func exitNodeIP(p *ipn.Prefs, st *ipnstate.Status) (ip netaddr.IP) { +func exitNodeIP(p *ipn.Prefs, st *ipnstate.Status) (ip netip.Addr) { if p == nil { return } diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 31eb00d46..dfc96ab0a 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -52,7 +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/netaddr from tailscale.com/disco+ 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 diff --git a/cmd/tailscaled/debug.go b/cmd/tailscaled/debug.go index e0b963fd8..b269d8e2b 100644 --- a/cmd/tailscaled/debug.go +++ b/cmd/tailscaled/debug.go @@ -30,7 +30,6 @@ "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" @@ -267,7 +266,7 @@ func debugPortmap(ctx context.Context) error { return err } - gatewayAndSelfIP := func() (gw, self netaddr.IP, ok bool) { + gatewayAndSelfIP := func() (gw, self netip.Addr, ok bool) { if v := os.Getenv("TS_DEBUG_GW_SELF"); strings.Contains(v, "/") { i := strings.Index(v, "/") gw = netip.MustParseAddr(v[:i]) diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index b24546552..e2576892e 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -217,7 +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/netaddr from tailscale.com/disco+ 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+ diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index fd8c32e86..160ec1677 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -21,6 +21,7 @@ "net" "net/http" "net/http/pprof" + "net/netip" "os" "os/signal" "path/filepath" @@ -38,7 +39,6 @@ "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" @@ -366,11 +366,11 @@ func run() error { ns.ProcessSubnets = useNetstack || wrapNetstack if useNetstack { - dialer.UseNetstackForIP = func(ip netaddr.IP) bool { + dialer.UseNetstackForIP = func(ip netip.Addr) bool { _, ok := e.PeerForIP(ip) return ok } - dialer.NetstackDialTCP = func(ctx context.Context, dst netaddr.IPPort) (net.Conn, error) { + dialer.NetstackDialTCP = func(ctx context.Context, dst netip.AddrPort) (net.Conn, error) { return ns.DialContextTCP(ctx, dst) } } diff --git a/cmd/tailscaled/tailscaled_windows.go b/cmd/tailscaled/tailscaled_windows.go index 8910c2855..085c5ca0a 100644 --- a/cmd/tailscaled/tailscaled_windows.go +++ b/cmd/tailscaled/tailscaled_windows.go @@ -25,6 +25,7 @@ "encoding/json" "fmt" "log" + "net/netip" "os" "time" @@ -37,7 +38,6 @@ "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" @@ -245,7 +245,7 @@ func beFirewallKillswitch() bool { // is passed in via stdin encoded in json. dcd := json.NewDecoder(os.Stdin) for { - var routes []netaddr.IPPrefix + var routes []netip.Prefix if err := dcd.Decode(&routes); err != nil { log.Fatalf("parent process died or requested exit, exiting (%v)", err) } diff --git a/cmd/tsconnect/wasm/wasm_js.go b/cmd/tsconnect/wasm/wasm_js.go index 4adc6e654..b28b618c6 100644 --- a/cmd/tsconnect/wasm/wasm_js.go +++ b/cmd/tsconnect/wasm/wasm_js.go @@ -19,6 +19,7 @@ "log" "math/rand" "net" + "net/netip" "strings" "syscall/js" "time" @@ -29,7 +30,6 @@ "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" @@ -78,10 +78,10 @@ func newIPN(jsConfig js.Value) map[string]any { if err := ns.Start(); err != nil { log.Fatalf("failed to start netstack: %v", err) } - dialer.UseNetstackForIP = func(ip netaddr.IP) bool { + dialer.UseNetstackForIP = func(ip netip.Addr) bool { return true } - dialer.NetstackDialTCP = func(ctx context.Context, dst netaddr.IPPort) (net.Conn, error) { + dialer.NetstackDialTCP = func(ctx context.Context, dst netip.AddrPort) (net.Conn, error) { return ns.DialContextTCP(ctx, dst) } @@ -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.Addr().String() }), + Addresses: mapSlice(nm.Addresses, func(a netip.Prefix) 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.Addr().String() }), + Addresses: mapSlice(p.Addresses, func(a netip.Prefix) 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 0d3eb2bfd..b2f704c5f 100644 --- a/cmd/viewer/tests/tests.go +++ b/cmd/viewer/tests/tests.go @@ -7,15 +7,14 @@ import ( "fmt" - - "tailscale.com/net/netaddr" + "net/netip" ) //go:generate go run tailscale.com/cmd/viewer --type=StructWithPtrs,StructWithoutPtrs,Map,StructWithSlices type StructWithoutPtrs struct { Int int - Pfx netaddr.IPPrefix + Pfx netip.Prefix } type Map struct { @@ -54,6 +53,6 @@ type StructWithSlices struct { 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 c63a16e2b..99c6c21c5 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", "net/netip.Prefix": + case "inet.af/netip.Prefix", "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 e0e8528f2..39387549a 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -16,6 +16,7 @@ "io/ioutil" "log" "net/http" + "net/netip" "net/url" "os" "reflect" @@ -36,7 +37,6 @@ "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" @@ -129,7 +129,7 @@ type Options struct { // Pinger is the LocalBackend.Ping method. type Pinger interface { // Ping is a request to do a ping with the peer handling the given IP. - Ping(ctx context.Context, ip netaddr.IP, pingType tailcfg.PingType) (*ipnstate.PingResult, error) + Ping(ctx context.Context, ip netip.Addr, pingType tailcfg.PingType) (*ipnstate.PingResult, error) } type Decompressor interface { @@ -1167,8 +1167,8 @@ func TrimWGConfig() opt.Bool { // It should not return false positives. // // TODO(bradfitz): Change controlclient.Options.SkipIPForwardingCheck into a -// func([]netaddr.IPPrefix) error signature instead. -func ipForwardingBroken(routes []netaddr.IPPrefix, state *interfaces.State) bool { +// func([]netip.Prefix) error signature instead. +func ipForwardingBroken(routes []netip.Prefix, state *interfaces.State) bool { warn, err := netutil.CheckIPForwarding(routes, state) if err != nil { // Oh well, we tried. This is just for debugging. diff --git a/control/controlclient/direct_test.go b/control/controlclient/direct_test.go index eef98e610..54a33c1cf 100644 --- a/control/controlclient/direct_test.go +++ b/control/controlclient/direct_test.go @@ -8,12 +8,12 @@ "encoding/json" "net/http" "net/http/httptest" + "net/netip" "testing" "time" "tailscale.com/hostinfo" "tailscale.com/ipn/ipnstate" - "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/tailcfg" "tailscale.com/types/key" @@ -86,7 +86,7 @@ func TestNewDirect(t *testing.T) { func fakeEndpoints(ports ...uint16) (ret []tailcfg.Endpoint) { for _, port := range ports { ret = append(ret, tailcfg.Endpoint{ - Addr: netaddr.IPPortFrom(netaddr.IP{}, port), + Addr: netip.AddrPortFrom(netip.Addr{}, port), }) } return diff --git a/control/controlclient/map.go b/control/controlclient/map.go index 30e892e63..a96876407 100644 --- a/control/controlclient/map.go +++ b/control/controlclient/map.go @@ -7,10 +7,10 @@ import ( "fmt" "log" + "net/netip" "sort" "tailscale.com/envknob" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/logger" @@ -303,7 +303,7 @@ func cloneNodes(v1 []*tailcfg.Node) []*tailcfg.Node { var debugSelfIPv6Only = envknob.Bool("TS_DEBUG_SELF_V6_ONLY") -func filterSelfAddresses(in []netaddr.IPPrefix) (ret []netaddr.IPPrefix) { +func filterSelfAddresses(in []netip.Prefix) (ret []netip.Prefix) { switch { default: return in diff --git a/derp/derp_client.go b/derp/derp_client.go index 3d7eef603..f7282f646 100644 --- a/derp/derp_client.go +++ b/derp/derp_client.go @@ -18,7 +18,6 @@ "go4.org/mem" "golang.org/x/time/rate" - "tailscale.com/net/netaddr" "tailscale.com/types/key" "tailscale.com/types/logger" ) @@ -598,17 +597,17 @@ func (c *Client) setSendRateLimiter(sm ServerInfoMessage) { // // If the client is broken in some previously detectable way, it // returns an error. -func (c *Client) LocalAddr() (netaddr.IPPort, error) { +func (c *Client) LocalAddr() (netip.AddrPort, error) { readErr, _ := c.readErr.Load().(error) if readErr != nil { - return netaddr.IPPort{}, readErr + return netip.AddrPort{}, readErr } if c.nc == nil { - return netaddr.IPPort{}, errors.New("nil conn") + return netip.AddrPort{}, errors.New("nil conn") } a := c.nc.LocalAddr() if a == nil { - return netaddr.IPPort{}, errors.New("nil addr") + return netip.AddrPort{}, errors.New("nil addr") } return netip.ParseAddrPort(a.String()) } diff --git a/derp/derp_server.go b/derp/derp_server.go index 593dd1110..337568fc2 100644 --- a/derp/derp_server.go +++ b/derp/derp_server.go @@ -41,7 +41,6 @@ "tailscale.com/disco" "tailscale.com/envknob" "tailscale.com/metrics" - "tailscale.com/net/netaddr" "tailscale.com/syncs" "tailscale.com/types/key" "tailscale.com/types/logger" @@ -163,8 +162,8 @@ type Server struct { // src. sentTo map[key.NodePublic]map[key.NodePublic]int64 // src => dst => dst's latest sclient.connNum - // maps from netaddr.IPPort to a client's public key - keyOfAddr map[netaddr.IPPort]key.NodePublic + // maps from netip.AddrPort to a client's public key + keyOfAddr map[netip.AddrPort]key.NodePublic } // clientSet represents 1 or more *sclients. @@ -315,7 +314,7 @@ func NewServer(privateKey key.NodePrivate, logf logger.Logf) *Server { watchers: map[*sclient]bool{}, sentTo: map[key.NodePublic]map[key.NodePublic]int64{}, avgQueueDuration: new(uint64), - keyOfAddr: map[netaddr.IPPort]key.NodePublic{}, + keyOfAddr: map[netip.AddrPort]key.NodePublic{}, } s.initMetacert() s.packetsRecvDisco = s.packetsRecvByKind.Get("disco") @@ -1247,7 +1246,7 @@ type sclient struct { logf logger.Logf done <-chan struct{} // closed when connection closes remoteAddr string // usually ip:port from net.Conn.RemoteAddr().String() - remoteIPPort netaddr.IPPort // zero if remoteAddr is not ip:port. + remoteIPPort netip.AddrPort // zero if remoteAddr is not ip:port. sendQueue chan pkt // packets queued to this client; never closed discoSendQueue chan pkt // important packets queued to this client; never closed sendPongCh chan [8]byte // pong replies to send to the client; never closed @@ -1760,8 +1759,8 @@ type BytesSentRecv struct { // parseSSOutput parses the output from the specific call to ss in ServeDebugTraffic. // Separated out for ease of testing. -func parseSSOutput(raw string) map[netaddr.IPPort]BytesSentRecv { - newState := map[netaddr.IPPort]BytesSentRecv{} +func parseSSOutput(raw string) map[netip.AddrPort]BytesSentRecv { + newState := map[netip.AddrPort]BytesSentRecv{} // parse every 2 lines and get src and dst ips, and kv pairs lines := strings.Split(raw, "\n") for i := 0; i < len(lines); i += 2 { @@ -1794,7 +1793,7 @@ func parseSSOutput(raw string) map[netaddr.IPPort]BytesSentRecv { } func (s *Server) ServeDebugTraffic(w http.ResponseWriter, r *http.Request) { - prevState := map[netaddr.IPPort]BytesSentRecv{} + prevState := map[netip.AddrPort]BytesSentRecv{} enc := json.NewEncoder(w) for r.Context().Err() == nil { output, err := exec.Command("ss", "-i", "-H", "-t").Output() diff --git a/derp/derphttp/derphttp_client.go b/derp/derphttp/derphttp_client.go index 035b35d15..28d990bc4 100644 --- a/derp/derphttp/derphttp_client.go +++ b/derp/derphttp/derphttp_client.go @@ -34,7 +34,6 @@ "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" @@ -580,7 +579,7 @@ func (c *Client) dialContext(ctx context.Context, proto, addr string) (net.Conn, // address (given in s) is valid. An empty value means to dial, but to // use DNS. The predicate function reports whether the non-empty // string s contained a valid IP address of the right family. -func shouldDialProto(s string, pred func(netaddr.IP) bool) bool { +func shouldDialProto(s string, pred func(netip.Addr) bool) bool { if s == "" { return true } @@ -652,10 +651,10 @@ type res struct { } }() } - if shouldDialProto(n.IPv4, netaddr.IP.Is4) { + if shouldDialProto(n.IPv4, netip.Addr.Is4) { startDial(n.IPv4, "tcp4") } - if shouldDialProto(n.IPv6, netaddr.IP.Is6) { + if shouldDialProto(n.IPv6, netip.Addr.Is6) { startDial(n.IPv6, "tcp6") } if nwait == 0 { @@ -840,15 +839,15 @@ func (c *Client) SendPing(data [8]byte) error { // LocalAddr reports c's local TCP address, without any implicit // connect or reconnect. -func (c *Client) LocalAddr() (netaddr.IPPort, error) { +func (c *Client) LocalAddr() (netip.AddrPort, error) { c.mu.Lock() closed, client := c.closed, c.client c.mu.Unlock() if closed { - return netaddr.IPPort{}, ErrClientClosed + return netip.AddrPort{}, ErrClientClosed } if client == nil { - return netaddr.IPPort{}, errors.New("client not connected") + return netip.AddrPort{}, errors.New("client not connected") } return client.LocalAddr() } diff --git a/disco/disco.go b/disco/disco.go index 270b169a3..53ce81361 100644 --- a/disco/disco.go +++ b/disco/disco.go @@ -24,6 +24,7 @@ "errors" "fmt" "net" + "net/netip" "go4.org/mem" "tailscale.com/net/netaddr" @@ -172,7 +173,7 @@ type CallMeMaybe struct { // in this field, but might not yet be in control's endpoints. // (And in the future, control will stop distributing endpoints // when clients are suitably new.) - MyNumber []netaddr.IPPort + MyNumber []netip.AddrPort } const epLength = 16 + 2 // 16 byte IP address + 2 byte port @@ -193,11 +194,11 @@ func parseCallMeMaybe(ver uint8, p []byte) (m *CallMeMaybe, err error) { if len(p)%epLength != 0 || ver != 0 || len(p) == 0 { return m, nil } - m.MyNumber = make([]netaddr.IPPort, 0, len(p)/epLength) + m.MyNumber = make([]netip.AddrPort, 0, len(p)/epLength) for len(p) > 0 { var a [16]byte copy(a[:], p) - m.MyNumber = append(m.MyNumber, netaddr.IPPortFrom( + m.MyNumber = append(m.MyNumber, netip.AddrPortFrom( netaddr.IPFrom16(a), binary.BigEndian.Uint16(p[16:18]))) p = p[epLength:] @@ -211,7 +212,7 @@ func parseCallMeMaybe(ver uint8, p []byte) (m *CallMeMaybe, err error) { // STUN response. type Pong struct { TxID [12]byte - Src netaddr.IPPort // 18 bytes (16+2) on the wire; v4-mapped ipv6 for IPv4 + Src netip.AddrPort // 18 bytes (16+2) on the wire; v4-mapped ipv6 for IPv4 } const pongLen = 12 + 16 + 2 @@ -236,7 +237,7 @@ func parsePong(ver uint8, p []byte) (m *Pong, err error) { srcIP, _ := netaddr.FromStdIP(net.IP(p[:16])) p = p[16:] port := binary.BigEndian.Uint16(p) - m.Src = netaddr.IPPortFrom(srcIP, port) + m.Src = netip.AddrPortFrom(srcIP, port) return m, nil } diff --git a/disco/disco_test.go b/disco/disco_test.go index 354a8e59f..25070d581 100644 --- a/disco/disco_test.go +++ b/disco/disco_test.go @@ -12,7 +12,6 @@ "testing" "go4.org/mem" - "tailscale.com/net/netaddr" "tailscale.com/types/key" ) @@ -61,7 +60,7 @@ func TestMarshalAndParse(t *testing.T) { { name: "call_me_maybe_endpoints", m: &CallMeMaybe{ - MyNumber: []netaddr.IPPort{ + MyNumber: []netip.AddrPort{ netip.MustParseAddrPort("1.2.3.4:567"), netip.MustParseAddrPort("[2001::3456]:789"), }, @@ -94,7 +93,7 @@ func TestMarshalAndParse(t *testing.T) { } } -func mustIPPort(s string) netaddr.IPPort { +func mustIPPort(s string) netip.AddrPort { ipp, err := netip.ParseAddrPort(s) if err != nil { panic(err) diff --git a/ipn/handle.go b/ipn/handle.go index 2080d5dfa..225f1b6ed 100644 --- a/ipn/handle.go +++ b/ipn/handle.go @@ -5,10 +5,10 @@ package ipn import ( + "net/netip" "sync" "time" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/logger" "tailscale.com/types/netmap" @@ -126,7 +126,7 @@ func (h *Handle) EngineStatus() EngineStatus { return h.engineStatusCache } -func (h *Handle) LocalAddrs() []netaddr.IPPrefix { +func (h *Handle) LocalAddrs() []netip.Prefix { h.mu.Lock() defer h.mu.Unlock() @@ -134,7 +134,7 @@ func (h *Handle) LocalAddrs() []netaddr.IPPrefix { if nm != nil { return nm.Addresses } - return []netaddr.IPPrefix{} + return []netip.Prefix{} } func (h *Handle) NetMap() *netmap.NetworkMap { diff --git a/ipn/ipnlocal/dnsconfig_test.go b/ipn/ipnlocal/dnsconfig_test.go index 280162e82..2357f3f97 100644 --- a/ipn/ipnlocal/dnsconfig_test.go +++ b/ipn/ipnlocal/dnsconfig_test.go @@ -12,7 +12,6 @@ "tailscale.com/ipn" "tailscale.com/net/dns" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstest" "tailscale.com/types/dnstype" @@ -21,7 +20,7 @@ "tailscale.com/util/dnsname" ) -func ipps(ippStrs ...string) (ipps []netaddr.IPPrefix) { +func ipps(ippStrs ...string) (ipps []netip.Prefix) { for _, s := range ippStrs { if ip, err := netip.ParseAddr(s); err == nil { ipps = append(ipps, netip.PrefixFrom(ip, ip.BitLen())) @@ -32,7 +31,7 @@ func ipps(ippStrs ...string) (ipps []netaddr.IPPrefix) { return } -func ips(ss ...string) (ips []netaddr.IP) { +func ips(ss ...string) (ips []netip.Addr) { for _, s := range ss { ips = append(ips, netip.MustParseAddr(s)) } @@ -55,7 +54,7 @@ func TestDNSConfigForNetmap(t *testing.T) { prefs: &ipn.Prefs{}, want: &dns.Config{ Routes: map[dnsname.FQDN][]*dnstype.Resolver{}, - Hosts: map[dnsname.FQDN][]netaddr.IP{}, + Hosts: map[dnsname.FQDN][]netip.Addr{}, }, }, { @@ -81,7 +80,7 @@ func TestDNSConfigForNetmap(t *testing.T) { prefs: &ipn.Prefs{}, want: &dns.Config{ Routes: map[dnsname.FQDN][]*dnstype.Resolver{}, - Hosts: map[dnsname.FQDN][]netaddr.IP{ + Hosts: map[dnsname.FQDN][]netip.Addr{ "b.net.": ips("100.102.0.1", "100.102.0.2"), "myname.net.": ips("100.101.101.101"), "peera.net.": ips("100.102.0.1", "100.102.0.2"), @@ -116,7 +115,7 @@ func TestDNSConfigForNetmap(t *testing.T) { want: &dns.Config{ OnlyIPv6: true, Routes: map[dnsname.FQDN][]*dnstype.Resolver{}, - Hosts: map[dnsname.FQDN][]netaddr.IP{ + Hosts: map[dnsname.FQDN][]netip.Addr{ "b.net.": ips("fe75::2"), "myname.net.": ips("fe75::1"), "peera.net.": ips("fe75::1001"), @@ -140,7 +139,7 @@ func TestDNSConfigForNetmap(t *testing.T) { prefs: &ipn.Prefs{}, want: &dns.Config{ Routes: map[dnsname.FQDN][]*dnstype.Resolver{}, - Hosts: map[dnsname.FQDN][]netaddr.IP{ + Hosts: map[dnsname.FQDN][]netip.Addr{ "myname.net.": ips("100.101.101.101"), "foo.com.": ips("1.2.3.4"), "bar.com.": ips("1::6"), @@ -160,7 +159,7 @@ func TestDNSConfigForNetmap(t *testing.T) { CorpDNS: true, }, want: &dns.Config{ - Hosts: map[dnsname.FQDN][]netaddr.IP{}, + Hosts: map[dnsname.FQDN][]netip.Addr{}, Routes: map[dnsname.FQDN][]*dnstype.Resolver{ "0.e.1.a.c.5.1.1.a.7.d.f.ip6.arpa.": nil, "100.100.in-addr.arpa.": nil, @@ -260,7 +259,7 @@ func TestDNSConfigForNetmap(t *testing.T) { CorpDNS: true, }, want: &dns.Config{ - Hosts: map[dnsname.FQDN][]netaddr.IP{}, + Hosts: map[dnsname.FQDN][]netip.Addr{}, DefaultResolvers: []*dnstype.Resolver{ {Addr: "8.8.8.8"}, }, @@ -283,7 +282,7 @@ func TestDNSConfigForNetmap(t *testing.T) { ExitNodeID: "some-id", }, want: &dns.Config{ - Hosts: map[dnsname.FQDN][]netaddr.IP{}, + Hosts: map[dnsname.FQDN][]netip.Addr{}, Routes: map[dnsname.FQDN][]*dnstype.Resolver{}, DefaultResolvers: []*dnstype.Resolver{ {Addr: "8.8.4.4"}, @@ -303,7 +302,7 @@ func TestDNSConfigForNetmap(t *testing.T) { CorpDNS: true, }, want: &dns.Config{ - Hosts: map[dnsname.FQDN][]netaddr.IP{}, + Hosts: map[dnsname.FQDN][]netip.Addr{}, Routes: map[dnsname.FQDN][]*dnstype.Resolver{}, }, }, diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index b9d3de562..ffff19488 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -34,7 +34,6 @@ "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" @@ -130,7 +129,7 @@ type LocalBackend struct { shutdownCalled bool // if Shutdown has been called filterAtomic atomic.Value // of *filter.Filter - containsViaIPFuncAtomic atomic.Value // of func(netaddr.IP) bool + containsViaIPFuncAtomic atomic.Value // of func(netip.Addr) bool // The mutex protects the following elements. mu sync.Mutex @@ -152,7 +151,7 @@ type LocalBackend struct { hostinfo *tailcfg.Hostinfo // netMap is not mutated in-place once set. netMap *netmap.NetworkMap - nodeByAddr map[netaddr.IP]*tailcfg.Node + nodeByAddr map[netip.Addr]*tailcfg.Node activeLogin string // last logged LoginName from netMap engineStatus ipn.EngineStatus endpoints []tailcfg.Endpoint @@ -498,13 +497,13 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) { if p.LastSeen != nil { lastSeen = *p.LastSeen } - var tailscaleIPs = make([]netaddr.IP, 0, len(p.Addresses)) + var tailscaleIPs = make([]netip.Addr, 0, len(p.Addresses)) for _, addr := range p.Addresses { if addr.IsSingleIP() && tsaddr.IsTailscaleIP(addr.Addr()) { tailscaleIPs = append(tailscaleIPs, addr.Addr()) } } - exitNodeOption := tsaddr.PrefixesContainsFunc(p.AllowedIPs, func(r netaddr.IPPrefix) bool { + exitNodeOption := tsaddr.PrefixesContainsFunc(p.AllowedIPs, func(r netip.Prefix) bool { return r.Bits() == 0 }) var tags *views.Slice[string] @@ -542,12 +541,12 @@ func (b *LocalBackend) populatePeerStatusLocked(sb *ipnstate.StatusBuilder) { // WhoIs reports the node and user who owns the node with the given IP:port. // If the IP address is a Tailscale IP, the provided port may be 0. // If ok == true, n and u are valid. -func (b *LocalBackend) WhoIs(ipp netaddr.IPPort) (n *tailcfg.Node, u tailcfg.UserProfile, ok bool) { +func (b *LocalBackend) WhoIs(ipp netip.AddrPort) (n *tailcfg.Node, u tailcfg.UserProfile, ok bool) { b.mu.Lock() defer b.mu.Unlock() n, ok = b.nodeByAddr[ipp.Addr()] if !ok { - var ip netaddr.IP + var ip netip.Addr if ipp.Port() != 0 { ip, ok = b.e.WhoIsIPPort(ipp) } @@ -568,7 +567,7 @@ func (b *LocalBackend) WhoIs(ipp netaddr.IPPort) (n *tailcfg.Node, u tailcfg.Use // PeerCaps returns the capabilities that remote src IP has to // ths current node. -func (b *LocalBackend) PeerCaps(src netaddr.IP) []string { +func (b *LocalBackend) PeerCaps(src netip.Addr) []string { b.mu.Lock() defer b.mu.Unlock() if b.netMap == nil { @@ -770,7 +769,7 @@ func (b *LocalBackend) findExitNodeIDLocked(nm *netmap.NetworkMap) (prefsChanged // Found the node being referenced, upgrade prefs to // reference it directly for next time. b.prefs.ExitNodeID = peer.StableID - b.prefs.ExitNodeIP = netaddr.IP{} + b.prefs.ExitNodeIP = netip.Addr{} return true } } @@ -1123,7 +1122,7 @@ func (b *LocalBackend) updateFilterLocked(netMap *netmap.NetworkMap, prefs *ipn. // quite hard to debug, so save yourself the trouble. var ( haveNetmap = netMap != nil - addrs []netaddr.IPPrefix + addrs []netip.Prefix packetFilter []filter.Match localNetsB netipx.IPSetBuilder logNetsB netipx.IPSetBuilder @@ -1206,7 +1205,7 @@ func (b *LocalBackend) setFilter(f *filter.Filter) { b.e.SetFilter(f) } -var removeFromDefaultRoute = []netaddr.IPPrefix{ +var removeFromDefaultRoute = []netip.Prefix{ // RFC1918 LAN ranges netip.MustParsePrefix("192.168.0.0/16"), netip.MustParsePrefix("172.16.0.0/12"), @@ -1232,7 +1231,7 @@ func (b *LocalBackend) setFilter(f *filter.Filter) { // // Given that "internal" routes don't leave the device, we choose to // trust them more, allowing access to them when an Exit Node is enabled. -func internalAndExternalInterfaces() (internal, external []netaddr.IPPrefix, err error) { +func internalAndExternalInterfaces() (internal, external []netip.Prefix, err error) { il, err := interfaces.GetList() if err != nil { return nil, nil, err @@ -1240,11 +1239,11 @@ func internalAndExternalInterfaces() (internal, external []netaddr.IPPrefix, err return internalAndExternalInterfacesFrom(il, runtime.GOOS) } -func internalAndExternalInterfacesFrom(il interfaces.List, goos string) (internal, external []netaddr.IPPrefix, err error) { +func internalAndExternalInterfacesFrom(il interfaces.List, goos string) (internal, external []netip.Prefix, err error) { // We use an IPSetBuilder here to canonicalize the prefixes // and to remove any duplicate entries. var internalBuilder, externalBuilder netipx.IPSetBuilder - if err := il.ForeachInterfaceAddress(func(iface interfaces.Interface, pfx netaddr.IPPrefix) { + if err := il.ForeachInterfaceAddress(func(iface interfaces.Interface, pfx netip.Prefix) { if tsaddr.IsTailscaleIP(pfx.Addr()) { return } @@ -1286,9 +1285,9 @@ func internalAndExternalInterfacesFrom(il interfaces.List, goos string) (interna return iSet.Prefixes(), eSet.Prefixes(), nil } -func interfaceRoutes() (ips *netipx.IPSet, hostIPs []netaddr.IP, err error) { +func interfaceRoutes() (ips *netipx.IPSet, hostIPs []netip.Addr, err error) { var b netipx.IPSetBuilder - if err := interfaces.ForeachInterfaceAddress(func(_ interfaces.Interface, pfx netaddr.IPPrefix) { + if err := interfaces.ForeachInterfaceAddress(func(_ interfaces.Interface, pfx netip.Prefix) { if tsaddr.IsTailscaleIP(pfx.Addr()) { return } @@ -1308,7 +1307,7 @@ func interfaceRoutes() (ips *netipx.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 *netipx.IPSet, hostIPs []netaddr.IP) (*netipx.IPSet, error) { +func shrinkDefaultRoute(route netip.Prefix, localInterfaceRoutes *netipx.IPSet, hostIPs []netip.Addr) (*netipx.IPSet, error) { var b netipx.IPSetBuilder // Add the default route. b.AddPrefix(route) @@ -1335,7 +1334,7 @@ func shrinkDefaultRoute(route netaddr.IPPrefix, localInterfaceRoutes *netipx.IPS // dnsCIDRsEqual determines whether two CIDR lists are equal // for DNS map construction purposes (that is, only the first entry counts). -func dnsCIDRsEqual(newAddr, oldAddr []netaddr.IPPrefix) bool { +func dnsCIDRsEqual(newAddr, oldAddr []netip.Prefix) bool { if len(newAddr) != len(oldAddr) { return false } @@ -1733,7 +1732,7 @@ func (b *LocalBackend) StartLoginInteractive() { } } -func (b *LocalBackend) Ping(ctx context.Context, ip netaddr.IP, pingType tailcfg.PingType) (*ipnstate.PingResult, error) { +func (b *LocalBackend) Ping(ctx context.Context, ip netip.Addr, pingType tailcfg.PingType) (*ipnstate.PingResult, error) { if pingType == tailcfg.PingPeerAPI { t0 := time.Now() node, base, err := b.pingPeerAPI(ctx, ip) @@ -1770,7 +1769,7 @@ func (b *LocalBackend) Ping(ctx context.Context, ip netaddr.IP, pingType tailcfg } } -func (b *LocalBackend) pingPeerAPI(ctx context.Context, ip netaddr.IP) (peer *tailcfg.Node, peerBase string, err error) { +func (b *LocalBackend) pingPeerAPI(ctx context.Context, ip netip.Addr) (peer *tailcfg.Node, peerBase string, err error) { ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() nm := b.NetMap() @@ -2069,7 +2068,7 @@ func (b *LocalBackend) setPrefsLockedOnEntry(caller string, newp *ipn.Prefs) { // GetPeerAPIPort returns the port number for the peerapi server // running on the provided IP. -func (b *LocalBackend) GetPeerAPIPort(ip netaddr.IP) (port uint16, ok bool) { +func (b *LocalBackend) GetPeerAPIPort(ip netip.Addr) (port uint16, ok bool) { b.mu.Lock() defer b.mu.Unlock() for _, pln := range b.peerAPIListeners { @@ -2087,7 +2086,7 @@ func (b *LocalBackend) GetPeerAPIPort(ip netaddr.IP) (port uint16, ok bool) { // or IPv6 IP and the peerapi port for that address). // // The connection will be closed by ServePeerAPIConnection. -func (b *LocalBackend) ServePeerAPIConnection(remote, local netaddr.IPPort, c net.Conn) { +func (b *LocalBackend) ServePeerAPIConnection(remote, local netip.AddrPort, c net.Conn) { b.mu.Lock() defer b.mu.Unlock() for _, pln := range b.peerAPIListeners { @@ -2289,7 +2288,7 @@ func shouldUseOneCGNATRoute(nm *netmap.NetworkMap, logf logger.Logf, versionOS s func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Logf, versionOS string) *dns.Config { dcfg := &dns.Config{ Routes: map[dnsname.FQDN][]*dnstype.Resolver{}, - Hosts: map[dnsname.FQDN][]netaddr.IP{}, + Hosts: map[dnsname.FQDN][]netip.Addr{}, } // selfV6Only is whether we only have IPv6 addresses ourselves. @@ -2302,7 +2301,7 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Log // isn't configured to make MagicDNS resolution truly // magic. Details in // https://github.com/tailscale/tailscale/issues/1886. - set := func(name string, addrs []netaddr.IPPrefix) { + set := func(name string, addrs []netip.Prefix) { if len(addrs) == 0 || name == "" { return } @@ -2311,7 +2310,7 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Log return // TODO: propagate error? } have4 := tsaddr.PrefixesContainsFunc(addrs, tsaddr.PrefixIs4) - var ips []netaddr.IP + var ips []netip.Addr for _, addr := range addrs { if selfV6Only { if addr.Addr().Is6() { @@ -2629,11 +2628,11 @@ func magicDNSRootDomains(nm *netmap.NetworkMap) []dnsname.FQDN { // peerRoutes returns the routerConfig.Routes to access peers. // If there are over cgnatThreshold CGNAT routes, one big CGNAT route // is used instead. -func peerRoutes(peers []wgcfg.Peer, cgnatThreshold int) (routes []netaddr.IPPrefix) { +func peerRoutes(peers []wgcfg.Peer, cgnatThreshold int) (routes []netip.Prefix) { tsULA := tsaddr.TailscaleULARange() cgNAT := tsaddr.CGNATRange() var didULA bool - var cgNATIPs []netaddr.IPPrefix + var cgNATIPs []netip.Prefix for _, peer := range peers { for _, aip := range peer.AllowedIPs { aip = unmapIPPrefix(aip) @@ -2665,7 +2664,7 @@ func peerRoutes(peers []wgcfg.Peer, cgnatThreshold int) (routes []netaddr.IPPref return routes } -func ipPrefixLess(ri, rj netaddr.IPPrefix) bool { +func ipPrefixLess(ri, rj netip.Prefix) bool { if ri.Addr() == rj.Addr() { return ri.Bits() < rj.Bits() } @@ -2736,17 +2735,17 @@ func (b *LocalBackend) routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs, oneCGNA } if tsaddr.PrefixesContainsFunc(rs.LocalAddrs, tsaddr.PrefixIs4) { - rs.Routes = append(rs.Routes, netaddr.IPPrefixFrom(tsaddr.TailscaleServiceIP(), 32)) + rs.Routes = append(rs.Routes, netip.PrefixFrom(tsaddr.TailscaleServiceIP(), 32)) } return rs } -func unmapIPPrefix(ipp netaddr.IPPrefix) netaddr.IPPrefix { +func unmapIPPrefix(ipp netip.Prefix) netip.Prefix { return netip.PrefixFrom(ipp.Addr().Unmap(), ipp.Bits()) } -func unmapIPPrefixes(ippsList ...[]netaddr.IPPrefix) (ret []netaddr.IPPrefix) { +func unmapIPPrefixes(ippsList ...[]netip.Prefix) (ret []netip.Prefix) { for _, ipps := range ippsList { for _, ipp := range ipps { ret = append(ret, unmapIPPrefix(ipp)) @@ -2989,8 +2988,8 @@ func (b *LocalBackend) ShouldRunSSH() bool { return b.sshAtomicBool.Get() && can // ShouldHandleViaIP reports whether whether ip is an IPv6 address in the // Tailscale ULA's v6 "via" range embedding an IPv4 address to be forwarded to // by Tailscale. -func (b *LocalBackend) ShouldHandleViaIP(ip netaddr.IP) bool { - if f, ok := b.containsViaIPFuncAtomic.Load().(func(netaddr.IP) bool); ok { +func (b *LocalBackend) ShouldHandleViaIP(ip netip.Addr) bool { + if f, ok := b.containsViaIPFuncAtomic.Load().(func(netip.Addr) bool); ok { return f(ip) } return false @@ -3107,7 +3106,7 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) { // Update the nodeByAddr index. if b.nodeByAddr == nil { - b.nodeByAddr = map[netaddr.IP]*tailcfg.Node{} + b.nodeByAddr = map[netip.Addr]*tailcfg.Node{} } // First pass, mark everything unwanted. for k := range b.nodeByAddr { @@ -3313,12 +3312,12 @@ func peerAPIBase(nm *netmap.NetworkMap, peer *tailcfg.Node) string { p6 = s.Port } } - var ipp netaddr.IPPort + var ipp netip.AddrPort switch { case have4 && p4 != 0: - ipp = netaddr.IPPortFrom(nodeIP(peer, netaddr.IP.Is4), p4) + ipp = netip.AddrPortFrom(nodeIP(peer, netip.Addr.Is4), p4) case have6 && p6 != 0: - ipp = netaddr.IPPortFrom(nodeIP(peer, netaddr.IP.Is6), p6) + ipp = netip.AddrPortFrom(nodeIP(peer, netip.Addr.Is6), p6) } if !ipp.Addr().IsValid() { return "" @@ -3326,13 +3325,13 @@ func peerAPIBase(nm *netmap.NetworkMap, peer *tailcfg.Node) string { return fmt.Sprintf("http://%v", ipp) } -func nodeIP(n *tailcfg.Node, pred func(netaddr.IP) bool) netaddr.IP { +func nodeIP(n *tailcfg.Node, pred func(netip.Addr) bool) netip.Addr { for _, a := range n.Addresses { if a.IsSingleIP() && pred(a.Addr()) { return a.Addr() } } - return netaddr.IP{} + return netip.Addr{} } func (b *LocalBackend) CheckIPForwarding() error { diff --git a/ipn/ipnlocal/local_test.go b/ipn/ipnlocal/local_test.go index 26aaf1589..4d8d25c1c 100644 --- a/ipn/ipnlocal/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -17,7 +17,6 @@ "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" @@ -31,13 +30,13 @@ func TestNetworkMapCompare(t *testing.T) { if err != nil { t.Fatal(err) } - node1 := &tailcfg.Node{Addresses: []netaddr.IPPrefix{prefix1}} + node1 := &tailcfg.Node{Addresses: []netip.Prefix{prefix1}} prefix2, err := netip.ParsePrefix("10.0.0.0/8") if err != nil { t.Fatal(err) } - node2 := &tailcfg.Node{Addresses: []netaddr.IPPrefix{prefix2}} + node2 := &tailcfg.Node{Addresses: []netip.Prefix{prefix2}} tests := []struct { name string @@ -133,7 +132,7 @@ func TestNetworkMapCompare(t *testing.T) { } } -func inRemove(ip netaddr.IP) bool { +func inRemove(ip netip.Addr) bool { for _, pfx := range removeFromDefaultRoute { if pfx.Contains(ip) { return true @@ -147,7 +146,7 @@ func TestShrinkDefaultRoute(t *testing.T) { route string in []string out []string - localIPFn func(netaddr.IP) bool // true if this machine's local IP address should be "in" after shrinking. + localIPFn func(netip.Addr) bool // true if this machine's local IP address should be "in" after shrinking. }{ { route: "0.0.0.0/0", @@ -167,7 +166,7 @@ func TestShrinkDefaultRoute(t *testing.T) { "fe80::", "2601::1", }, - localIPFn: func(ip netaddr.IP) bool { return !inRemove(ip) && ip.Is4() }, + localIPFn: func(ip netip.Addr) bool { return !inRemove(ip) && ip.Is4() }, }, { route: "::/0", @@ -177,7 +176,7 @@ func TestShrinkDefaultRoute(t *testing.T) { "ff00::1", tsaddr.TailscaleULARange().Addr().String(), }, - localIPFn: func(ip netaddr.IP) bool { return !inRemove(ip) && ip.Is6() }, + localIPFn: func(ip netip.Addr) bool { return !inRemove(ip) && ip.Is6() }, }, } @@ -193,13 +192,13 @@ func TestShrinkDefaultRoute(t *testing.T) { if err != nil { t.Fatal(err) } - hostIPs := []netaddr.IP{ + hostIPs := []netip.Addr{ netip.MustParseAddr("127.0.0.1"), netip.MustParseAddr("192.168.9.39"), netip.MustParseAddr("fe80::1"), netip.MustParseAddr("fe80::437d:feff:feca:49a7"), } - localAddresses := []netaddr.IP{ + localAddresses := []netip.Addr{ netip.MustParseAddr("192.168.9.39"), } @@ -233,18 +232,18 @@ func TestPeerRoutes(t *testing.T) { tests := []struct { name string peers []wgcfg.Peer - want []netaddr.IPPrefix + want []netip.Prefix }{ { name: "small_v4", peers: []wgcfg.Peer{ { - AllowedIPs: []netaddr.IPPrefix{ + AllowedIPs: []netip.Prefix{ pp("100.101.102.103/32"), }, }, }, - want: []netaddr.IPPrefix{ + want: []netip.Prefix{ pp("100.101.102.103/32"), }, }, @@ -252,14 +251,14 @@ func TestPeerRoutes(t *testing.T) { name: "big_v4", peers: []wgcfg.Peer{ { - AllowedIPs: []netaddr.IPPrefix{ + AllowedIPs: []netip.Prefix{ pp("100.101.102.103/32"), pp("100.101.102.104/32"), pp("100.101.102.105/32"), }, }, }, - want: []netaddr.IPPrefix{ + want: []netip.Prefix{ pp("100.64.0.0/10"), }, }, @@ -267,12 +266,12 @@ func TestPeerRoutes(t *testing.T) { name: "has_1_v6", peers: []wgcfg.Peer{ { - AllowedIPs: []netaddr.IPPrefix{ + AllowedIPs: []netip.Prefix{ pp("fd7a:115c:a1e0:ab12:4843:cd96:6258:b240/128"), }, }, }, - want: []netaddr.IPPrefix{ + want: []netip.Prefix{ pp("fd7a:115c:a1e0::/48"), }, }, @@ -280,13 +279,13 @@ func TestPeerRoutes(t *testing.T) { name: "has_2_v6", peers: []wgcfg.Peer{ { - AllowedIPs: []netaddr.IPPrefix{ + AllowedIPs: []netip.Prefix{ pp("fd7a:115c:a1e0:ab12:4843:cd96:6258:b240/128"), pp("fd7a:115c:a1e0:ab12:4843:cd96:6258:b241/128"), }, }, }, - want: []netaddr.IPPrefix{ + want: []netip.Prefix{ pp("fd7a:115c:a1e0::/48"), }, }, @@ -294,7 +293,7 @@ func TestPeerRoutes(t *testing.T) { name: "big_v4_big_v6", peers: []wgcfg.Peer{ { - AllowedIPs: []netaddr.IPPrefix{ + AllowedIPs: []netip.Prefix{ pp("100.101.102.103/32"), pp("100.101.102.104/32"), pp("100.101.102.105/32"), @@ -303,7 +302,7 @@ func TestPeerRoutes(t *testing.T) { }, }, }, - want: []netaddr.IPPrefix{ + want: []netip.Prefix{ pp("100.64.0.0/10"), pp("fd7a:115c:a1e0::/48"), }, @@ -312,19 +311,19 @@ func TestPeerRoutes(t *testing.T) { name: "output-should-be-sorted", peers: []wgcfg.Peer{ { - AllowedIPs: []netaddr.IPPrefix{ + AllowedIPs: []netip.Prefix{ pp("100.64.0.2/32"), pp("10.0.0.0/16"), }, }, { - AllowedIPs: []netaddr.IPPrefix{ + AllowedIPs: []netip.Prefix{ pp("100.64.0.1/32"), pp("10.0.0.0/8"), }, }, }, - want: []netaddr.IPPrefix{ + want: []netip.Prefix{ pp("10.0.0.0/8"), pp("10.0.0.0/16"), pp("100.64.0.1/32"), @@ -363,12 +362,12 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_only_4_them_both", nm: &netmap.NetworkMap{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.1/32"), }, }, peer: &tailcfg.Node{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.2/32"), netip.MustParsePrefix("fe70::2/128"), }, @@ -384,12 +383,12 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_only_6_them_both", nm: &netmap.NetworkMap{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("fe70::1/128"), }, }, peer: &tailcfg.Node{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.2/32"), netip.MustParsePrefix("fe70::2/128"), }, @@ -405,13 +404,13 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_both_them_only_4", nm: &netmap.NetworkMap{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.1/32"), netip.MustParsePrefix("fe70::1/128"), }, }, peer: &tailcfg.Node{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.2/32"), netip.MustParsePrefix("fe70::2/128"), }, @@ -426,13 +425,13 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_both_them_only_6", nm: &netmap.NetworkMap{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.1/32"), netip.MustParsePrefix("fe70::1/128"), }, }, peer: &tailcfg.Node{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.2/32"), netip.MustParsePrefix("fe70::2/128"), }, @@ -447,13 +446,13 @@ func TestPeerAPIBase(t *testing.T) { { name: "self_both_them_no_peerapi_service", nm: &netmap.NetworkMap{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.1/32"), netip.MustParsePrefix("fe70::1/128"), }, }, peer: &tailcfg.Node{ - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ netip.MustParsePrefix("100.64.1.2/32"), netip.MustParsePrefix("fe70::2/128"), }, @@ -543,10 +542,10 @@ func TestFileTargets(t *testing.T) { func TestInternalAndExternalInterfaces(t *testing.T) { type interfacePrefix struct { i interfaces.Interface - pfx netaddr.IPPrefix + pfx netip.Prefix } - masked := func(ips ...interfacePrefix) (pfxs []netaddr.IPPrefix) { + masked := func(ips ...interfacePrefix) (pfxs []netip.Prefix) { for _, ip := range ips { pfxs = append(pfxs, ip.pfx.Masked()) } @@ -585,8 +584,8 @@ type interfacePrefix struct { name string goos string il interfaces.List - wantInt []netaddr.IPPrefix - wantExt []netaddr.IPPrefix + wantInt []netip.Prefix + wantExt []netip.Prefix }{ { name: "single-interface", diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index 40115971e..4bd935407 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -48,7 +48,7 @@ "tailscale.com/wgengine/filter" ) -var initListenConfig func(*net.ListenConfig, netaddr.IP, *interfaces.State, string) error +var initListenConfig func(*net.ListenConfig, netip.Addr, *interfaces.State, string) error // addH2C is non-nil on platforms where we want to add H2C // ("cleartext" HTTP/2) support to the peerAPI. @@ -387,7 +387,7 @@ func (s *peerAPIServer) OpenFile(baseName string) (rc io.ReadCloser, size int64, return f, fi.Size(), nil } -func (s *peerAPIServer) listen(ip netaddr.IP, ifState *interfaces.State) (ln net.Listener, err error) { +func (s *peerAPIServer) listen(ip netip.Addr, ifState *interfaces.State) (ln net.Listener, err error) { // Android for whatever reason often has problems creating the peerapi listener. // But since we started intercepting it with netstack, it's not even important that // we have a real kernel-level listener. So just create a dummy listener on Android @@ -451,7 +451,7 @@ func (s *peerAPIServer) listen(ip netaddr.IP, ifState *interfaces.State) (ln net type peerAPIListener struct { ps *peerAPIServer - ip netaddr.IP + ip netip.Addr lb *LocalBackend // ln is the Listener. It can be nil in netstack mode if there are more than @@ -503,7 +503,7 @@ func (pln *peerAPIListener) serve() { } } -func (pln *peerAPIListener) ServeConn(src netaddr.IPPort, c net.Conn) { +func (pln *peerAPIListener) ServeConn(src netip.AddrPort, c net.Conn) { logf := pln.lb.logf peerNode, peerUser, ok := pln.lb.WhoIs(src) if !ok { @@ -530,7 +530,7 @@ func (pln *peerAPIListener) ServeConn(src netaddr.IPPort, c net.Conn) { // peerAPIHandler serves the Peer API for a source specific client. type peerAPIHandler struct { ps *peerAPIServer - remoteAddr netaddr.IPPort + remoteAddr netip.AddrPort isSelf bool // whether peerNode is owned by same user as this node peerNode *tailcfg.Node // peerNode is who's making the request peerUser tailcfg.UserProfile // profile of peerNode @@ -609,7 +609,7 @@ func (h *peerAPIHandler) handleServeInterfaces(w http.ResponseWriter, r *http.Re fmt.Fprintf(w, "%v ", v) } fmt.Fprint(w, "\n") - i.ForeachInterface(func(iface interfaces.Interface, ipps []netaddr.IPPrefix) { + i.ForeachInterface(func(iface interfaces.Interface, ipps []netip.Prefix) { fmt.Fprint(w, "") for _, v := range []any{iface.Index, iface.Name, iface.MTU, iface.Flags, ipps} { fmt.Fprintf(w, "%v ", v) @@ -1169,9 +1169,9 @@ func writePrettyDNSReply(w io.Writer, res []byte) (err error) { // it's listening on the provided IP address and on TCP port 1. // // See docs on fakePeerAPIListener. -func newFakePeerAPIListener(ip netaddr.IP) net.Listener { +func newFakePeerAPIListener(ip netip.Addr) net.Listener { return &fakePeerAPIListener{ - addr: net.TCPAddrFromAddrPort(netaddr.IPPortFrom(ip, 1)), + addr: net.TCPAddrFromAddrPort(netip.AddrPortFrom(ip, 1)), closed: make(chan struct{}), } } diff --git a/ipn/ipnlocal/peerapi_macios_ext.go b/ipn/ipnlocal/peerapi_macios_ext.go index 315df1e4f..b10e999aa 100644 --- a/ipn/ipnlocal/peerapi_macios_ext.go +++ b/ipn/ipnlocal/peerapi_macios_ext.go @@ -11,9 +11,9 @@ import ( "fmt" "net" + "net/netip" "tailscale.com/net/interfaces" - "tailscale.com/net/netaddr" "tailscale.com/net/netns" ) @@ -24,7 +24,7 @@ func init() { // initListenConfigNetworkExtension configures nc for listening on IP // through the iOS/macOS Network/System Extension (Packet Tunnel // Provider) sandbox. -func initListenConfigNetworkExtension(nc *net.ListenConfig, ip netaddr.IP, st *interfaces.State, tunIfName string) error { +func initListenConfigNetworkExtension(nc *net.ListenConfig, ip netip.Addr, st *interfaces.State, tunIfName string) error { tunIf, ok := st.Interface[tunIfName] if !ok { return fmt.Errorf("no interface with name %q", tunIfName) diff --git a/ipn/ipnlocal/peerapi_test.go b/ipn/ipnlocal/peerapi_test.go index e4bd3ccb4..bcfb44ac9 100644 --- a/ipn/ipnlocal/peerapi_test.go +++ b/ipn/ipnlocal/peerapi_test.go @@ -22,7 +22,6 @@ "go4.org/netipx" "tailscale.com/ipn" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstest" "tailscale.com/types/logger" @@ -596,7 +595,7 @@ func TestPeerAPIReplyToDNSQueries(t *testing.T) { t.Fatal("unexpectedly offering exit node") } h.ps.b.prefs = &ipn.Prefs{ - AdvertiseRoutes: []netaddr.IPPrefix{ + AdvertiseRoutes: []netip.Prefix{ netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0"), }, diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index f04b135e3..42cccbeaa 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -37,7 +37,6 @@ "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" @@ -1066,7 +1065,7 @@ func (s *Server) ServeHTMLStatus(w http.ResponseWriter, r *http.Request) { st.WriteHTML(w) } -func peerPid(entries []netstat.Entry, la, ra netaddr.IPPort) int { +func peerPid(entries []netstat.Entry, la, ra netip.AddrPort) int { for _, e := range entries { if e.Local == ra && e.Remote == la { return e.Pid diff --git a/ipn/ipnstate/ipnstate.go b/ipn/ipnstate/ipnstate.go index d2c6ff27e..23b19ec9d 100644 --- a/ipn/ipnstate/ipnstate.go +++ b/ipn/ipnstate/ipnstate.go @@ -12,12 +12,12 @@ "html" "io" "log" + "net/netip" "sort" "strings" "sync" "time" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/types/views" @@ -35,7 +35,7 @@ type Status struct { BackendState string AuthURL string // current URL provided by control to authorize client - TailscaleIPs []netaddr.IP // Tailscale IP(s) assigned to this node + TailscaleIPs []netip.Addr // Tailscale IP(s) assigned to this node Self *PeerStatus // ExitNodeStatus describes the current exit node. @@ -94,7 +94,7 @@ type ExitNodeStatus struct { Online bool // TailscaleIPs are the exit node's IP addresses assigned to the node. - TailscaleIPs []netaddr.IPPrefix + TailscaleIPs []netip.Prefix } func (s *Status) Peers() []key.NodePublic { @@ -124,7 +124,7 @@ type PeerStatus struct { DNSName string OS string // HostInfo.OS UserID tailcfg.UserID - TailscaleIPs []netaddr.IP // Tailscale IP(s) assigned to this node + TailscaleIPs []netip.Addr // Tailscale IP(s) assigned to this node // Tags are the list of ACL tags applied to this node. // See tailscale.com/tailcfg#Node.Tags for more information. @@ -240,7 +240,7 @@ func (sb *StatusBuilder) AddUser(id tailcfg.UserID, up tailcfg.UserProfile) { } // AddIP adds a Tailscale IP address to the status. -func (sb *StatusBuilder) AddTailscaleIP(ip netaddr.IP) { +func (sb *StatusBuilder) AddTailscaleIP(ip netip.Addr) { sb.mu.Lock() defer sb.mu.Unlock() if sb.locked { diff --git a/ipn/localapi/localapi.go b/ipn/localapi/localapi.go index ea2d2c384..f5b8ca455 100644 --- a/ipn/localapi/localapi.go +++ b/ipn/localapi/localapi.go @@ -29,7 +29,6 @@ "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" @@ -223,7 +222,7 @@ func (h *Handler) serveWhoIs(w http.ResponseWriter, r *http.Request) { return } b := h.b - var ipp netaddr.IPPort + var ipp netip.AddrPort if v := r.FormValue("addr"); v != "" { var err error ipp, err = netip.ParseAddrPort(v) diff --git a/ipn/prefs.go b/ipn/prefs.go index 8616767dd..b0b9fc250 100644 --- a/ipn/prefs.go +++ b/ipn/prefs.go @@ -99,7 +99,7 @@ type Prefs struct { // blackhole route will be installed on the local system to // prevent any traffic escaping to the local network. ExitNodeID tailcfg.StableNodeID - ExitNodeIP netaddr.IP + ExitNodeIP netip.Addr // ExitNodeAllowLANAccess indicates whether locally accessible subnets should be // routed directly or via the exit node. @@ -168,7 +168,7 @@ type Prefs struct { // AdvertiseRoutes specifies CIDR prefixes to advertise into the // Tailscale network as reachable through the current // node. - AdvertiseRoutes []netaddr.IPPrefix + AdvertiseRoutes []netip.Prefix // NoSNAT specifies whether to source NAT traffic going to // destinations in AdvertiseRoutes. The default is to apply source @@ -383,7 +383,7 @@ func (p *Prefs) Equals(p2 *Prefs) bool { p.Persist.Equals(p2.Persist) } -func compareIPNets(a, b []netaddr.IPPrefix) bool { +func compareIPNets(a, b []netip.Prefix) bool { if len(a) != len(b) { return false } @@ -478,13 +478,13 @@ func (p *Prefs) SetAdvertiseExitNode(runExit bool) { return } p.AdvertiseRoutes = append(p.AdvertiseRoutes, - netaddr.IPPrefixFrom(netaddr.IPv4(0, 0, 0, 0), 0), - netaddr.IPPrefixFrom(netip.IPv6Unspecified(), 0)) + netip.PrefixFrom(netaddr.IPv4(0, 0, 0, 0), 0), + netip.PrefixFrom(netip.IPv6Unspecified(), 0)) } // peerWithTailscaleIP returns the peer in st with the provided // Tailscale IP. -func peerWithTailscaleIP(st *ipnstate.Status, ip netaddr.IP) (ps *ipnstate.PeerStatus, ok bool) { +func peerWithTailscaleIP(st *ipnstate.Status, ip netip.Addr) (ps *ipnstate.PeerStatus, ok bool) { for _, ps := range st.Peer { for _, ip2 := range ps.TailscaleIPs { if ip == ip2 { @@ -495,7 +495,7 @@ func peerWithTailscaleIP(st *ipnstate.Status, ip netaddr.IP) (ps *ipnstate.PeerS return nil, false } -func isRemoteIP(st *ipnstate.Status, ip netaddr.IP) bool { +func isRemoteIP(st *ipnstate.Status, ip netip.Addr) bool { for _, selfIP := range st.TailscaleIPs { if ip == selfIP { return false @@ -507,7 +507,7 @@ func isRemoteIP(st *ipnstate.Status, ip netaddr.IP) bool { // ClearExitNode sets the ExitNodeID and ExitNodeIP to their zero values. func (p *Prefs) ClearExitNode() { p.ExitNodeID = "" - p.ExitNodeIP = netaddr.IP{} + p.ExitNodeIP = netip.Addr{} } // ExitNodeLocalIPError is returned when the requested IP address for an exit @@ -520,7 +520,7 @@ func (e ExitNodeLocalIPError) Error() string { return fmt.Sprintf("cannot use %s as an exit node as it is a local IP address to this machine", e.hostOrIP) } -func exitNodeIPOfArg(s string, st *ipnstate.Status) (ip netaddr.IP, err error) { +func exitNodeIPOfArg(s string, st *ipnstate.Status) (ip netip.Addr, err error) { if s == "" { return ip, os.ErrInvalid } diff --git a/ipn/prefs_test.go b/ipn/prefs_test.go index d95b5c115..ce567aae9 100644 --- a/ipn/prefs_test.go +++ b/ipn/prefs_test.go @@ -63,7 +63,7 @@ func TestPrefsEqual(t *testing.T) { have, prefsHandles) } - nets := func(strs ...string) (ns []netaddr.IPPrefix) { + nets := func(strs ...string) (ns []netip.Prefix) { for _, s := range strs { n, err := netip.ParsePrefix(s) if err != nil { @@ -227,12 +227,12 @@ func TestPrefsEqual(t *testing.T) { { &Prefs{AdvertiseRoutes: nil}, - &Prefs{AdvertiseRoutes: []netaddr.IPPrefix{}}, + &Prefs{AdvertiseRoutes: []netip.Prefix{}}, true, }, { - &Prefs{AdvertiseRoutes: []netaddr.IPPrefix{}}, - &Prefs{AdvertiseRoutes: []netaddr.IPPrefix{}}, + &Prefs{AdvertiseRoutes: []netip.Prefix{}}, + &Prefs{AdvertiseRoutes: []netip.Prefix{}}, true, }, { @@ -659,7 +659,7 @@ func TestPrefsExitNode(t *testing.T) { if p.AdvertisesExitNode() { t.Errorf("default shouldn't advertise exit node") } - p.AdvertiseRoutes = []netaddr.IPPrefix{ + p.AdvertiseRoutes = []netip.Prefix{ netip.MustParsePrefix("10.0.0.0/16"), } p.SetAdvertiseExitNode(true) @@ -688,7 +688,7 @@ func TestExitNodeIPOfArg(t *testing.T) { name string arg string st *ipnstate.Status - want netaddr.IP + want netip.Addr wantErr string }{ { @@ -714,7 +714,7 @@ func TestExitNodeIPOfArg(t *testing.T) { BackendState: "Running", Peer: map[key.NodePublic]*ipnstate.PeerStatus{ key.NewNode().Public(): { - TailscaleIPs: []netaddr.IP{mustIP("1.2.3.4")}, + TailscaleIPs: []netip.Addr{mustIP("1.2.3.4")}, }, }, }, @@ -727,7 +727,7 @@ func TestExitNodeIPOfArg(t *testing.T) { BackendState: "Running", Peer: map[key.NodePublic]*ipnstate.PeerStatus{ key.NewNode().Public(): { - TailscaleIPs: []netaddr.IP{mustIP("1.2.3.4")}, + TailscaleIPs: []netip.Addr{mustIP("1.2.3.4")}, ExitNodeOption: true, }, }, @@ -748,7 +748,7 @@ func TestExitNodeIPOfArg(t *testing.T) { Peer: map[key.NodePublic]*ipnstate.PeerStatus{ key.NewNode().Public(): { DNSName: "skippy.foo.", - TailscaleIPs: []netaddr.IP{mustIP("1.0.0.2")}, + TailscaleIPs: []netip.Addr{mustIP("1.0.0.2")}, ExitNodeOption: true, }, }, @@ -763,7 +763,7 @@ func TestExitNodeIPOfArg(t *testing.T) { Peer: map[key.NodePublic]*ipnstate.PeerStatus{ key.NewNode().Public(): { DNSName: "skippy.foo.", - TailscaleIPs: []netaddr.IP{mustIP("1.0.0.2")}, + TailscaleIPs: []netip.Addr{mustIP("1.0.0.2")}, }, }, }, @@ -777,12 +777,12 @@ func TestExitNodeIPOfArg(t *testing.T) { Peer: map[key.NodePublic]*ipnstate.PeerStatus{ key.NewNode().Public(): { DNSName: "skippy.foo.", - TailscaleIPs: []netaddr.IP{mustIP("1.0.0.2")}, + TailscaleIPs: []netip.Addr{mustIP("1.0.0.2")}, ExitNodeOption: true, }, key.NewNode().Public(): { DNSName: "SKIPPY.foo.", - TailscaleIPs: []netaddr.IP{mustIP("1.0.0.2")}, + TailscaleIPs: []netip.Addr{mustIP("1.0.0.2")}, ExitNodeOption: true, }, }, diff --git a/net/dns/config.go b/net/dns/config.go index 733e08c11..7fb5e5ebd 100644 --- a/net/dns/config.go +++ b/net/dns/config.go @@ -7,10 +7,10 @@ import ( "bufio" "fmt" + "net/netip" "sort" "tailscale.com/net/dns/resolver" - "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/types/dnstype" "tailscale.com/util/dnsname" @@ -40,13 +40,13 @@ type Config struct { // Adding an entry to Hosts merely creates the record. If you want // it to resolve, you also need to add appropriate routes to // Routes. - Hosts map[dnsname.FQDN][]netaddr.IP + Hosts map[dnsname.FQDN][]netip.Addr // OnlyIPv6, if true, uses the IPv6 service IP (for MagicDNS) // instead of the IPv4 version (100.100.100.100). OnlyIPv6 bool } -func (c *Config) serviceIP() netaddr.IP { +func (c *Config) serviceIP() netip.Addr { if c.OnlyIPv6 { return tsaddr.TailscaleServiceIPv6() } @@ -143,7 +143,7 @@ func sameResolverNames(a, b []*dnstype.Resolver) bool { return true } -func sameIPs(a, b []netaddr.IP) bool { +func sameIPs(a, b []netip.Addr) bool { if len(a) != len(b) { return false } diff --git a/net/dns/direct.go b/net/dns/direct.go index c32ce5688..4f698dcf5 100644 --- a/net/dns/direct.go +++ b/net/dns/direct.go @@ -13,6 +13,7 @@ "io" "io/fs" "io/ioutil" + "net/netip" "os" "os/exec" "path/filepath" @@ -21,7 +22,6 @@ "time" "tailscale.com/net/dns/resolvconffile" - "tailscale.com/net/netaddr" "tailscale.com/types/logger" "tailscale.com/util/dnsname" "tailscale.com/version/distro" @@ -33,7 +33,7 @@ ) // writeResolvConf writes DNS configuration in resolv.conf format to the given writer. -func writeResolvConf(w io.Writer, servers []netaddr.IP, domains []dnsname.FQDN) error { +func writeResolvConf(w io.Writer, servers []netip.Addr, domains []dnsname.FQDN) error { c := &resolvconffile.Config{ Nameservers: servers, SearchDomains: domains, diff --git a/net/dns/direct_test.go b/net/dns/direct_test.go index b9784ef5a..78dfd29e4 100644 --- a/net/dns/direct_test.go +++ b/net/dns/direct_test.go @@ -16,7 +16,6 @@ "testing" qt "github.com/frankban/quicktest" - "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) @@ -82,7 +81,7 @@ func testDirect(t *testing.T, fs wholeFileFS) { m := directManager{logf: t.Logf, fs: fs} if err := m.SetDNS(OSConfig{ - Nameservers: []netaddr.IP{netip.MustParseAddr("8.8.8.8"), netip.MustParseAddr("8.8.4.4")}, + Nameservers: []netip.Addr{netip.MustParseAddr("8.8.8.8"), netip.MustParseAddr("8.8.4.4")}, SearchDomains: []dnsname.FQDN{"ts.net.", "ts-dns.test."}, MatchDomains: []dnsname.FQDN{"ignored."}, }); err != nil { @@ -109,7 +108,7 @@ func testDirect(t *testing.T, fs wholeFileFS) { assertBaseState(t) // Test that Close cleans up resolv.conf. - if err := m.SetDNS(OSConfig{Nameservers: []netaddr.IP{netip.MustParseAddr("8.8.8.8")}}); err != nil { + if err := m.SetDNS(OSConfig{Nameservers: []netip.Addr{netip.MustParseAddr("8.8.8.8")}}); err != nil { t.Fatal(err) } if err := m.Close(); err != nil { @@ -150,21 +149,21 @@ func TestReadResolve(t *testing.T) { }{ {in: `nameserver 192.168.0.100`, want: OSConfig{ - Nameservers: []netaddr.IP{ + Nameservers: []netip.Addr{ netip.MustParseAddr("192.168.0.100"), }, }, }, {in: `nameserver 192.168.0.100 # comment`, want: OSConfig{ - Nameservers: []netaddr.IP{ + Nameservers: []netip.Addr{ netip.MustParseAddr("192.168.0.100"), }, }, }, {in: `nameserver 192.168.0.100#`, want: OSConfig{ - Nameservers: []netaddr.IP{ + Nameservers: []netip.Addr{ netip.MustParseAddr("192.168.0.100"), }, }, diff --git a/net/dns/manager.go b/net/dns/manager.go index 1b99c3416..9889408d0 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -11,13 +11,13 @@ "errors" "io" "net" + "net/netip" "runtime" "sync/atomic" "time" "tailscale.com/health" "tailscale.com/net/dns/resolver" - "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/net/tsdial" @@ -67,7 +67,7 @@ func maxActiveQueries() int32 { type response struct { pkt []byte - to netaddr.IPPort // response destination (request source) + to netip.AddrPort // response destination (request source) } // Manager manages system DNS settings. @@ -175,7 +175,7 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig // through quad-100. rcfg.Routes = routes rcfg.Routes["."] = cfg.DefaultResolvers - ocfg.Nameservers = []netaddr.IP{cfg.serviceIP()} + ocfg.Nameservers = []netip.Addr{cfg.serviceIP()} return rcfg, ocfg, nil } @@ -212,7 +212,7 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig // or routes + MagicDNS, or just MagicDNS, or on an OS that cannot // split-DNS. Install a split config pointing at quad-100. rcfg.Routes = routes - ocfg.Nameservers = []netaddr.IP{cfg.serviceIP()} + ocfg.Nameservers = []netip.Addr{cfg.serviceIP()} // If the OS can't do native split-dns, read out the underlying // resolver config and blend it into our config. @@ -239,7 +239,7 @@ func (m *Manager) compileConfig(cfg Config) (rcfg resolver.Config, ocfg OSConfig // toIPsOnly returns only the IP portion of dnstype.Resolver. // Only safe to use if the resolvers slice has been cleared of // DoH or custom-port entries with something like hasDefaultIPResolversOnly. -func toIPsOnly(resolvers []*dnstype.Resolver) (ret []netaddr.IP) { +func toIPsOnly(resolvers []*dnstype.Resolver) (ret []netip.Addr) { for _, r := range resolvers { if ipp, ok := r.IPPort(); ok && ipp.Port() == 53 { ret = append(ret, ipp.Addr()) @@ -252,7 +252,7 @@ func toIPsOnly(resolvers []*dnstype.Resolver) (ret []netaddr.IP) { // called with a DNS request payload. // // TODO(tom): Rip out once all platforms use netstack. -func (m *Manager) EnqueuePacket(bs []byte, proto ipproto.Proto, from, to netaddr.IPPort) error { +func (m *Manager) EnqueuePacket(bs []byte, proto ipproto.Proto, from, to netip.AddrPort) error { if to.Port() != 53 || proto != ipproto.UDP { return nil } @@ -334,7 +334,7 @@ func (m *Manager) NextPacket() ([]byte, error) { // Query executes a DNS query recieved from the given address. The query is // provided in bs as a wire-encoded DNS query without any transport header. // This method is called for requests arriving over UDP and TCP. -func (m *Manager) Query(ctx context.Context, bs []byte, from netaddr.IPPort) ([]byte, error) { +func (m *Manager) Query(ctx context.Context, bs []byte, from netip.AddrPort) ([]byte, error) { select { case <-m.ctx.Done(): return nil, net.ErrClosed @@ -368,7 +368,7 @@ type dnsTCPSession struct { m *Manager conn net.Conn - srcAddr netaddr.IPPort + srcAddr netip.AddrPort readClosing chan struct{} responses chan []byte // DNS replies pending writing @@ -455,7 +455,7 @@ func (s *dnsTCPSession) handleReads() { // HandleTCPConn implements magicDNS over TCP, taking a connection and // servicing DNS requests sent down it. -func (m *Manager) HandleTCPConn(conn net.Conn, srcAddr netaddr.IPPort) { +func (m *Manager) HandleTCPConn(conn net.Conn, srcAddr netip.AddrPort) { s := dnsTCPSession{ m: m, conn: conn, diff --git a/net/dns/manager_tcp_test.go b/net/dns/manager_tcp_test.go index 01ed32e02..5aafb1532 100644 --- a/net/dns/manager_tcp_test.go +++ b/net/dns/manager_tcp_test.go @@ -8,11 +8,11 @@ "encoding/binary" "io" "net" + "net/netip" "testing" "github.com/google/go-cmp/cmp" dns "golang.org/x/net/dns/dnsmessage" - "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/util/dnsname" ) @@ -73,7 +73,7 @@ func TestDNSOverTCP(t *testing.T) { c, s := net.Pipe() defer s.Close() - go m.HandleTCPConn(s, netaddr.IPPort{}) + go m.HandleTCPConn(s, netip.AddrPort{}) defer c.Close() wantResults := map[dnsname.FQDN]string{ diff --git a/net/dns/manager_test.go b/net/dns/manager_test.go index e940ba288..84fb03d2e 100644 --- a/net/dns/manager_test.go +++ b/net/dns/manager_test.go @@ -13,7 +13,6 @@ "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "tailscale.com/net/dns/resolver" - "tailscale.com/net/netaddr" "tailscale.com/net/tsdial" "tailscale.com/types/dnstype" "tailscale.com/util/dnsname" @@ -394,8 +393,8 @@ 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 { + trIP := cmp.Transformer("ipStr", func(ip netip.Addr) string { return ip.String() }) + trIPPort := cmp.Transformer("ippStr", func(ipp netip.AddrPort) string { if ipp.Port() == 53 { return ipp.Addr().String() } @@ -424,14 +423,14 @@ func TestManager(t *testing.T) { } } -func mustIPs(strs ...string) (ret []netaddr.IP) { +func mustIPs(strs ...string) (ret []netip.Addr) { for _, s := range strs { ret = append(ret, netip.MustParseAddr(s)) } return ret } -func mustIPPs(strs ...string) (ret []netaddr.IPPort) { +func mustIPPs(strs ...string) (ret []netip.AddrPort) { for _, s := range strs { ret = append(ret, netip.MustParseAddrPort(s)) } @@ -456,9 +455,9 @@ func fqdns(strs ...string) (ret []dnsname.FQDN) { return ret } -func hosts(strs ...string) (ret map[dnsname.FQDN][]netaddr.IP) { +func hosts(strs ...string) (ret map[dnsname.FQDN][]netip.Addr) { var key dnsname.FQDN - ret = map[dnsname.FQDN][]netaddr.IP{} + ret = map[dnsname.FQDN][]netip.Addr{} for _, s := range strs { if ip, err := netip.ParseAddr(s); err == nil { if key == "" { diff --git a/net/dns/manager_windows.go b/net/dns/manager_windows.go index 1dbca560b..3414fb000 100644 --- a/net/dns/manager_windows.go +++ b/net/dns/manager_windows.go @@ -90,7 +90,7 @@ func delValue(key registry.Key, name string) error { // system's "primary" resolver. // // If no resolvers are provided, the Tailscale NRPT rules are deleted. -func (m windowsManager) setSplitDNS(resolvers []netaddr.IP, domains []dnsname.FQDN) error { +func (m windowsManager) setSplitDNS(resolvers []netip.Addr, domains []dnsname.FQDN) error { if m.nrptDB == nil { if resolvers == nil { // Just a no-op in this case. @@ -118,7 +118,7 @@ func (m windowsManager) setSplitDNS(resolvers []netaddr.IP, domains []dnsname.FQ // "primary" resolvers. // domains can be set without resolvers, which just contributes new // paths to the global DNS search list. -func (m windowsManager) setPrimaryDNS(resolvers []netaddr.IP, domains []dnsname.FQDN) error { +func (m windowsManager) setPrimaryDNS(resolvers []netip.Addr, domains []dnsname.FQDN) error { var ipsv4 []string var ipsv6 []string @@ -347,7 +347,7 @@ func (m windowsManager) GetBaseConfig() (OSConfig, error) { // It's used on Windows 7 to emulate split DNS by trying to figure out // what the "previous" primary resolver was. It might be wrong, or // incomplete. -func (m windowsManager) getBasePrimaryResolver() (resolvers []netaddr.IP, err error) { +func (m windowsManager) getBasePrimaryResolver() (resolvers []netip.Addr, err error) { tsGUID, err := windows.GUIDFromString(m.guid) if err != nil { return nil, err @@ -422,7 +422,7 @@ type candidate struct { return resolvers, nil } -var siteLocalResolvers = []netaddr.IP{ +var siteLocalResolvers = []netip.Addr{ netip.MustParseAddr("fec0:0:0:ffff::1"), netip.MustParseAddr("fec0:0:0:ffff::2"), netip.MustParseAddr("fec0:0:0:ffff::3"), diff --git a/net/dns/manager_windows_test.go b/net/dns/manager_windows_test.go index 44cf0cd36..d8efdbabd 100644 --- a/net/dns/manager_windows_test.go +++ b/net/dns/manager_windows_test.go @@ -15,7 +15,6 @@ "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" - "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" "tailscale.com/util/winutil" ) @@ -92,7 +91,7 @@ func TestManagerWindowsGPMove(t *testing.T) { // Upon initialization of cfg, we should not have any NRPT rules ensureNoRules(t) - resolvers := []netaddr.IP{netip.MustParseAddr("1.1.1.1")} + resolvers := []netip.Addr{netip.MustParseAddr("1.1.1.1")} domains := genRandomSubdomains(t, 1) // 1. Populate local NRPT @@ -216,7 +215,7 @@ func runTest(t *testing.T, isLocal bool) { // Upon initialization of cfg, we should not have any NRPT rules ensureNoRules(t) - resolvers := []netaddr.IP{netip.MustParseAddr("1.1.1.1")} + resolvers := []netip.Addr{netip.MustParseAddr("1.1.1.1")} domains := genRandomSubdomains(t, 2*nrptMaxDomainsPerRule+1) diff --git a/net/dns/nm.go b/net/dns/nm.go index b70a4f93f..6a9a90524 100644 --- a/net/dns/nm.go +++ b/net/dns/nm.go @@ -16,7 +16,6 @@ "github.com/godbus/dbus/v5" "tailscale.com/net/interfaces" - "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" "tailscale.com/util/endian" ) @@ -294,7 +293,7 @@ func (m *nmManager) GetBaseConfig() (OSConfig, error) { } type dnsPrio struct { - resolvers []netaddr.IP + resolvers []netip.Addr domains []string priority int32 } @@ -342,7 +341,7 @@ type dnsPrio struct { var ( ret OSConfig - seenResolvers = map[netaddr.IP]bool{} + seenResolvers = map[netip.Addr]bool{} seenSearch = map[string]bool{} ) diff --git a/net/dns/osconfig.go b/net/dns/osconfig.go index b84ea5d72..94a7f25d3 100644 --- a/net/dns/osconfig.go +++ b/net/dns/osconfig.go @@ -6,8 +6,8 @@ import ( "errors" + "net/netip" - "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) @@ -40,7 +40,7 @@ type OSConfigurator interface { // OSConfig is an OS DNS configuration. type OSConfig struct { // Nameservers are the IP addresses of the nameservers to use. - Nameservers []netaddr.IP + Nameservers []netip.Addr // SearchDomains are the domain suffixes to use when expanding // single-label name queries. SearchDomains is additive to // whatever non-Tailscale search domains the OS has. diff --git a/net/dns/publicdns/publicdns.go b/net/dns/publicdns/publicdns.go index 5cf5dac09..76467004a 100644 --- a/net/dns/publicdns/publicdns.go +++ b/net/dns/publicdns/publicdns.go @@ -9,31 +9,29 @@ import ( "net/netip" "sync" - - "tailscale.com/net/netaddr" ) -var knownDoH = map[netaddr.IP]string{} // 8.8.8.8 => "https://..." -var dohIPsOfBase = map[string][]netaddr.IP{} +var knownDoH = map[netip.Addr]string{} // 8.8.8.8 => "https://..." +var dohIPsOfBase = map[string][]netip.Addr{} var populateOnce sync.Once // KnownDoH returns a map of well-known public DNS IPs to their DoH URL. // The returned map should not be modified. -func KnownDoH() map[netaddr.IP]string { +func KnownDoH() map[netip.Addr]string { populateOnce.Do(populate) return knownDoH } // DoHIPsOfBase returns a map of DNS server IP addresses keyed // by their DoH URL. It is the inverse of KnownDoH. -func DoHIPsOfBase() map[string][]netaddr.IP { +func DoHIPsOfBase() map[string][]netip.Addr { populateOnce.Do(populate) return dohIPsOfBase } // DoHV6 returns the first IPv6 DNS address from a given public DNS provider // if found, along with a boolean indicating success. -func DoHV6(base string) (ip netaddr.IP, ok bool) { +func DoHV6(base string) (ip netip.Addr, ok bool) { populateOnce.Do(populate) for _, ip := range dohIPsOfBase[base] { if ip.Is6() { @@ -43,7 +41,7 @@ func DoHV6(base string) (ip netaddr.IP, ok bool) { return ip, false } -// addDoH parses a given well-formed ip string into a netaddr.IP type and +// addDoH parses a given well-formed ip string into a netip.Addr type and // adds it to both knownDoH and dohIPsOFBase maps. func addDoH(ipStr, base string) { ip := netip.MustParseAddr(ipStr) diff --git a/net/dns/publicdns/publicdns_test.go b/net/dns/publicdns/publicdns_test.go index 8debe8116..0463b0877 100644 --- a/net/dns/publicdns/publicdns_test.go +++ b/net/dns/publicdns/publicdns_test.go @@ -7,8 +7,6 @@ import ( "net/netip" "testing" - - "tailscale.com/net/netaddr" ) func TestInit(t *testing.T) { @@ -24,12 +22,12 @@ func TestInit(t *testing.T) { func TestDohV6(t *testing.T) { tests := []struct { in string - firstIP netaddr.IP + firstIP netip.Addr want bool }{ {"https://cloudflare-dns.com/dns-query", netip.MustParseAddr("2606:4700:4700::1111"), true}, {"https://dns.google/dns-query", netip.MustParseAddr("2001:4860:4860::8888"), true}, - {"bogus", netaddr.IP{}, false}, + {"bogus", netip.Addr{}, false}, } for _, test := range tests { t.Run(test.in, func(t *testing.T) { diff --git a/net/dns/resolvconffile/resolvconffile.go b/net/dns/resolvconffile/resolvconffile.go index d9562a6cb..8ddc71357 100644 --- a/net/dns/resolvconffile/resolvconffile.go +++ b/net/dns/resolvconffile/resolvconffile.go @@ -20,7 +20,6 @@ "os" "strings" - "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) @@ -30,7 +29,7 @@ // Config represents a resolv.conf(5) file. type Config struct { // Nameservers are the IP addresses of the nameservers to use. - Nameservers []netaddr.IP + Nameservers []netip.Addr // SearchDomains are the domain suffixes to use when expanding // single-label name queries. SearchDomains is additive to diff --git a/net/dns/resolvconffile/resolvconffile_test.go b/net/dns/resolvconffile/resolvconffile_test.go index b148d9cbd..ed9583a09 100644 --- a/net/dns/resolvconffile/resolvconffile_test.go +++ b/net/dns/resolvconffile/resolvconffile_test.go @@ -10,7 +10,6 @@ "strings" "testing" - "tailscale.com/net/netaddr" "tailscale.com/util/dnsname" ) @@ -22,21 +21,21 @@ func TestParse(t *testing.T) { }{ {in: `nameserver 192.168.0.100`, want: &Config{ - Nameservers: []netaddr.IP{ + Nameservers: []netip.Addr{ netip.MustParseAddr("192.168.0.100"), }, }, }, {in: `nameserver 192.168.0.100 # comment`, want: &Config{ - Nameservers: []netaddr.IP{ + Nameservers: []netip.Addr{ netip.MustParseAddr("192.168.0.100"), }, }, }, {in: `nameserver 192.168.0.100#`, want: &Config{ - Nameservers: []netaddr.IP{ + Nameservers: []netip.Addr{ netip.MustParseAddr("192.168.0.100"), }, }, diff --git a/net/dns/resolver/forwarder.go b/net/dns/resolver/forwarder.go index 56f7ee579..fc6f5e02e 100644 --- a/net/dns/resolver/forwarder.go +++ b/net/dns/resolver/forwarder.go @@ -15,6 +15,7 @@ "math/rand" "net" "net/http" + "net/netip" "net/url" "runtime" "sort" @@ -28,7 +29,6 @@ "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" @@ -367,7 +367,7 @@ func (f *forwarder) setRoutes(routesBySuffix map[dnsname.FQDN][]*dnstype.Resolve var stdNetPacketListener nettype.PacketListenerWithNetIP = nettype.MakePacketListenerWithNetIP(new(net.ListenConfig)) -func (f *forwarder) packetListener(ip netaddr.IP) (nettype.PacketListenerWithNetIP, error) { +func (f *forwarder) packetListener(ip netip.Addr) (nettype.PacketListenerWithNetIP, error) { if f.linkSel == nil || initListenConfig == nil { return stdNetPacketListener, nil } diff --git a/net/dns/resolver/tsdns.go b/net/dns/resolver/tsdns.go index 4ba90ae24..f28c3142c 100644 --- a/net/dns/resolver/tsdns.go +++ b/net/dns/resolver/tsdns.go @@ -54,7 +54,7 @@ type packet struct { bs []byte - addr netaddr.IPPort // src for a request, dst for a response + addr netip.AddrPort // src for a request, dst for a response } // Config is a resolver configuration. @@ -70,7 +70,7 @@ type Config struct { // To register a "default route", add an entry for ".". Routes map[dnsname.FQDN][]*dnstype.Resolver // LocalHosts is a map of FQDNs to corresponding IPs. - Hosts map[dnsname.FQDN][]netaddr.IP + Hosts map[dnsname.FQDN][]netip.Addr // LocalDomains is a list of DNS name suffixes that should not be // routed to upstream resolvers. LocalDomains []dnsname.FQDN @@ -106,7 +106,7 @@ func (c *Config) WriteToBufioWriter(w *bufio.Writer) { } // WriteIPPorts writes vv to w. -func WriteIPPorts(w *bufio.Writer, vv []netaddr.IPPort) { +func WriteIPPorts(w *bufio.Writer, vv []netip.AddrPort) { w.WriteByte('[') var b []byte for i, v := range vv { @@ -193,15 +193,15 @@ type Resolver struct { // mu guards the following fields from being updated while used. mu sync.Mutex localDomains []dnsname.FQDN - hostToIP map[dnsname.FQDN][]netaddr.IP - ipToHost map[netaddr.IP]dnsname.FQDN + hostToIP map[dnsname.FQDN][]netip.Addr + ipToHost map[netip.Addr]dnsname.FQDN } type ForwardLinkSelector interface { // PickLink returns which network device should be used to query // the DNS server at the given IP. // The empty string means to use an unspecified default. - PickLink(netaddr.IP) (linkName string) + PickLink(netip.Addr) (linkName string) } // New returns a new resolver. @@ -214,8 +214,8 @@ func New(logf logger.Logf, linkMon *monitor.Mon, linkSel ForwardLinkSelector, di logf: logger.WithPrefix(logf, "resolver: "), linkMon: linkMon, closed: make(chan struct{}), - hostToIP: map[dnsname.FQDN][]netaddr.IP{}, - ipToHost: map[netaddr.IP]dnsname.FQDN{}, + hostToIP: map[dnsname.FQDN][]netip.Addr{}, + ipToHost: map[netip.Addr]dnsname.FQDN{}, dialer: dialer, } r.forwarder = newForwarder(r.logf, linkMon, linkSel, dialer) @@ -229,7 +229,7 @@ func (r *Resolver) SetConfig(cfg Config) error { r.saveConfigForTests(cfg) } - reverse := make(map[netaddr.IP]dnsname.FQDN, len(cfg.Hosts)) + reverse := make(map[netip.Addr]dnsname.FQDN, len(cfg.Hosts)) for host, ips := range cfg.Hosts { for _, ip := range ips { @@ -266,7 +266,7 @@ func (r *Resolver) Close() { // bound on per-query resource usage. const dnsQueryTimeout = 10 * time.Second -func (r *Resolver) Query(ctx context.Context, bs []byte, from netaddr.IPPort) ([]byte, error) { +func (r *Resolver) Query(ctx context.Context, bs []byte, from netip.AddrPort) ([]byte, error) { metricDNSQueryLocal.Add(1) select { case <-r.closed: @@ -323,7 +323,7 @@ func parseExitNodeQuery(q []byte) *response { // still result in a response DNS packet (saying there's a failure) // and a nil error. // TODO: figure out if we even need an error result. -func (r *Resolver) HandleExitNodeDNSQuery(ctx context.Context, q []byte, from netaddr.IPPort, allowName func(name string) bool) (res []byte, err error) { +func (r *Resolver) HandleExitNodeDNSQuery(ctx context.Context, q []byte, from netip.AddrPort, allowName func(name string) bool) (res []byte, err error) { metricDNSExitProxyQuery.Add(1) ch := make(chan packet, 1) @@ -489,7 +489,7 @@ func isGoNoSuchHostError(err error) bool { type resolvConfCache struct { mod time.Time size int64 - ip netaddr.IP + ip netip.Addr // TODO: inode/dev? } @@ -501,10 +501,10 @@ type resolvConfCache struct { // stubResolverForOS returns the IP address of the first nameserver in // /etc/resolv.conf. -func stubResolverForOS() (ip netaddr.IP, err error) { +func stubResolverForOS() (ip netip.Addr, err error) { fi, err := os.Stat(resolvconffile.Path) if err != nil { - return netaddr.IP{}, err + return netip.Addr{}, err } cur := resolvConfCache{ mod: fi.ModTime(), @@ -515,10 +515,10 @@ func stubResolverForOS() (ip netaddr.IP, err error) { } conf, err := resolvconffile.ParseFile(resolvconffile.Path) if err != nil { - return netaddr.IP{}, err + return netip.Addr{}, err } if len(conf.Nameservers) == 0 { - return netaddr.IP{}, errEmptyResolvConf + return netip.Addr{}, errEmptyResolvConf } ip = conf.Nameservers[0] cur.ip = ip @@ -531,12 +531,12 @@ func stubResolverForOS() (ip netaddr.IP, err error) { // typ (A, AAAA, ALL). // Returns dns.RCodeRefused to indicate that the local map is not // authoritative for domain. -func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netaddr.IP, dns.RCode) { +func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netip.Addr, dns.RCode) { metricDNSResolveLocal.Add(1) // Reject .onion domains per RFC 7686. if dnsname.HasSuffix(domain.WithoutTrailingDot(), ".onion") { metricDNSResolveLocalErrorOnion.Add(1) - return netaddr.IP{}, dns.RCodeNameError + return netip.Addr{}, dns.RCodeNameError } // We return a symbolic domain if someone does a reverse lookup on the @@ -566,11 +566,11 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netaddr.IP, if suffix.Contains(domain) { // We are authoritative for the queried domain. metricDNSResolveLocalErrorMissing.Add(1) - return netaddr.IP{}, dns.RCodeNameError + return netip.Addr{}, dns.RCodeNameError } } // Not authoritative, signal that forwarding is advisable. - return netaddr.IP{}, dns.RCodeRefused + return netip.Addr{}, dns.RCodeRefused } // Refactoring note: this must happen after we check suffixes, @@ -588,7 +588,7 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netaddr.IP, } } metricDNSResolveLocalNoA.Add(1) - return netaddr.IP{}, dns.RCodeSuccess + return netip.Addr{}, dns.RCodeSuccess case dns.TypeAAAA: for _, ip := range addrs { if ip.Is6() { @@ -597,14 +597,14 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netaddr.IP, } } metricDNSResolveLocalNoAAAA.Add(1) - return netaddr.IP{}, dns.RCodeSuccess + return netip.Addr{}, dns.RCodeSuccess case dns.TypeALL: // Answer with whatever we've got. // It could be IPv4, IPv6, or a zero addr. // TODO: Return all available resolutions (A and AAAA, if we have them). if len(addrs) == 0 { metricDNSResolveLocalNoAll.Add(1) - return netaddr.IP{}, dns.RCodeSuccess + return netip.Addr{}, dns.RCodeSuccess } metricDNSResolveLocalOKAll.Add(1) return addrs[0], dns.RCodeSuccess @@ -614,7 +614,7 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netaddr.IP, // DNS semantics and might be implemented in the future. case dns.TypeNS, dns.TypeSOA, dns.TypeAXFR, dns.TypeHINFO: metricDNSResolveNotImplType.Add(1) - return netaddr.IP{}, dns.RCodeNotImplemented + return netip.Addr{}, dns.RCodeNotImplemented // For everything except for the few types above that are explicitly not implemented, return no records. // This is what other DNS systems do: always return NOERROR @@ -625,7 +625,7 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netaddr.IP, default: metricDNSResolveNoRecordType.Add(1) // The name exists, but no records exist of the requested type. - return netaddr.IP{}, dns.RCodeSuccess + return netip.Addr{}, dns.RCodeSuccess } } @@ -639,13 +639,13 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netaddr.IP, // (2022-06-02) to work around an issue in Chrome where it would treat // "http://via-1.1.2.3.4" as a search string instead of a URL. We should rip out // the old format in early 2023. -func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netaddr.IP, bool) { +func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr, bool) { fqdn := string(domain.WithoutTrailingDot()) if typ != dns.TypeAAAA { - return netaddr.IP{}, false + return netip.Addr{}, false } if len(fqdn) < len("via-X.0.0.0.0") { - return netaddr.IP{}, false // too short to be valid + return netip.Addr{}, false // too short to be valid } var siteID string @@ -653,18 +653,18 @@ func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netaddr.IP if strings.HasPrefix(fqdn, "via-") { firstDot := strings.Index(fqdn, ".") if firstDot < 0 { - return netaddr.IP{}, false // missing dot delimiters + return netip.Addr{}, false // missing dot delimiters } siteID = fqdn[len("via-"):firstDot] ip4Str = fqdn[firstDot+1:] } else { lastDot := strings.LastIndex(fqdn, ".") if lastDot < 0 { - return netaddr.IP{}, false // missing dot delimiters + return netip.Addr{}, false // missing dot delimiters } suffix := fqdn[lastDot+1:] if !strings.HasPrefix(suffix, "via-") { - return netaddr.IP{}, false + return netip.Addr{}, false } siteID = suffix[len("via-"):] ip4Str = fqdn[:lastDot] @@ -672,22 +672,22 @@ func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netaddr.IP ip4, err := netip.ParseAddr(ip4Str) if err != nil { - return netaddr.IP{}, false // badly formed, dont respond + return netip.Addr{}, false // badly formed, dont respond } prefix, err := strconv.ParseUint(siteID, 0, 32) if err != nil { - return netaddr.IP{}, false // badly formed, dont respond + return netip.Addr{}, false // badly formed, dont respond } - // MapVia will never error when given an ipv4 netaddr.IPPrefix. + // MapVia will never error when given an ipv4 netip.Prefix. 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. func (r *Resolver) resolveLocalReverse(name dnsname.FQDN) (dnsname.FQDN, dns.RCode) { - var ip netaddr.IP + var ip netip.Addr var ok bool switch { case strings.HasSuffix(name.WithTrailingDot(), rdnsv4Suffix): @@ -717,7 +717,7 @@ func (r *Resolver) resolveLocalReverse(name dnsname.FQDN) (dnsname.FQDN, dns.RCo } // r.mu must be held. -func (r *Resolver) fqdnForIPLocked(ip netaddr.IP, name dnsname.FQDN) (dnsname.FQDN, dns.RCode) { +func (r *Resolver) fqdnForIPLocked(ip netip.Addr, name dnsname.FQDN) (dnsname.FQDN, dns.RCode) { // If someone curiously does a reverse lookup on the DNS IP, we // return a domain that helps indicate that Tailscale is using // this IP for a special purpose and it is not a node on their @@ -749,8 +749,8 @@ type response struct { // IP and IPs are the responses to an A, AAAA, or ALL query. // Either/both/neither can be populated. - IP netaddr.IP - IPs []netaddr.IP + IP netip.Addr + IPs []netip.Addr // TXT is the response to a TXT query. // Each one is its own RR with one string. @@ -809,7 +809,7 @@ func (p *dnsParser) parseQuery(query []byte) error { // marshalARecord serializes an A record into an active builder. // The caller may continue using the builder following the call. -func marshalARecord(name dns.Name, ip netaddr.IP, builder *dns.Builder) error { +func marshalARecord(name dns.Name, ip netip.Addr, builder *dns.Builder) error { var answer dns.AResource answerHeader := dns.ResourceHeader{ @@ -825,7 +825,7 @@ func marshalARecord(name dns.Name, ip netaddr.IP, builder *dns.Builder) error { // marshalAAAARecord serializes an AAAA record into an active builder. // The caller may continue using the builder following the call. -func marshalAAAARecord(name dns.Name, ip netaddr.IP, builder *dns.Builder) error { +func marshalAAAARecord(name dns.Name, ip netip.Addr, builder *dns.Builder) error { var answer dns.AAAAResource answerHeader := dns.ResourceHeader{ @@ -839,7 +839,7 @@ func marshalAAAARecord(name dns.Name, ip netaddr.IP, builder *dns.Builder) error return builder.AAAAResource(answerHeader, answer) } -func marshalIP(name dns.Name, ip netaddr.IP, builder *dns.Builder) error { +func marshalIP(name dns.Name, ip netip.Addr, builder *dns.Builder) error { if ip.Is4() { return marshalARecord(name, ip, builder) } @@ -1066,14 +1066,14 @@ func rawNameToLower(name []byte) string { // 4.3.2.1.in-addr.arpa // is transformed to // 1.2.3.4 -func rdnsNameToIPv4(name dnsname.FQDN) (ip netaddr.IP, ok bool) { +func rdnsNameToIPv4(name dnsname.FQDN) (ip netip.Addr, ok bool) { s := strings.TrimSuffix(name.WithTrailingDot(), rdnsv4Suffix) ip, err := netip.ParseAddr(s) if err != nil { - return netaddr.IP{}, false + return netip.Addr{}, false } if !ip.Is4() { - return netaddr.IP{}, false + return netip.Addr{}, false } b := ip.As4() return netaddr.IPv4(b[3], b[2], b[1], b[0]), true @@ -1085,14 +1085,14 @@ func rdnsNameToIPv4(name dnsname.FQDN) (ip netaddr.IP, ok bool) { // b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. // is transformed to // 2001:db8::567:89ab -func rdnsNameToIPv6(name dnsname.FQDN) (ip netaddr.IP, ok bool) { +func rdnsNameToIPv6(name dnsname.FQDN) (ip netip.Addr, ok bool) { var b [32]byte var ipb [16]byte s := strings.TrimSuffix(name.WithTrailingDot(), rdnsv6Suffix) // 32 nibbles and 31 dots between them. if len(s) != 63 { - return netaddr.IP{}, false + return netip.Addr{}, false } // Dots and hex digits alternate. @@ -1101,7 +1101,7 @@ func rdnsNameToIPv6(name dnsname.FQDN) (ip netaddr.IP, ok bool) { for i, j := len(s)-1, 0; i >= 0; i-- { thisDot := (s[i] == '.') if prevDot == thisDot { - return netaddr.IP{}, false + return netip.Addr{}, false } prevDot = thisDot @@ -1115,7 +1115,7 @@ func rdnsNameToIPv6(name dnsname.FQDN) (ip netaddr.IP, ok bool) { _, err := hex.Decode(ipb[:], b[:]) if err != nil { - return netaddr.IP{}, false + return netip.Addr{}, false } return netaddr.IPFrom16(ipb), true diff --git a/net/dns/resolver/tsdns_server_test.go b/net/dns/resolver/tsdns_server_test.go index ab0f6c2b0..72860b280 100644 --- a/net/dns/resolver/tsdns_server_test.go +++ b/net/dns/resolver/tsdns_server_test.go @@ -7,11 +7,11 @@ import ( "fmt" "net" + "net/netip" "strings" "testing" "github.com/miekg/dns" - "tailscale.com/net/netaddr" ) // This file exists to isolate the test infrastructure @@ -22,7 +22,7 @@ // to queries of type A it receives with an A record containing ipv4, // to queries of type AAAA with an AAAA record containing ipv6, // to queries of type NS with an NS record containing name. -func resolveToIP(ipv4, ipv6 netaddr.IP, ns string) dns.HandlerFunc { +func resolveToIP(ipv4, ipv6 netip.Addr, ns string) dns.HandlerFunc { return func(w dns.ResponseWriter, req *dns.Msg) { m := new(dns.Msg) m.SetReply(req) @@ -73,7 +73,7 @@ func resolveToIP(ipv4, ipv6 netaddr.IP, ns string) dns.HandlerFunc { // to queries of type A it receives with an A record containing ipv4, // to queries of type AAAA with an AAAA record containing ipv6, // to queries of type NS with an NS record containing name. -func resolveToIPLowercase(ipv4, ipv6 netaddr.IP, ns string) dns.HandlerFunc { +func resolveToIPLowercase(ipv4, ipv6 netip.Addr, ns string) dns.HandlerFunc { return func(w dns.ResponseWriter, req *dns.Msg) { m := new(dns.Msg) m.SetReply(req) @@ -220,7 +220,7 @@ func weirdoGoCNAMEHandler(target string) dns.HandlerFunc { // dnsHandler returns a handler that replies with the answers/options // provided. // -// Types supported: netaddr.IP. +// Types supported: netip.Addr. func dnsHandler(answers ...any) dns.HandlerFunc { return func(w dns.ResponseWriter, req *dns.Msg) { m := new(dns.Msg) @@ -235,7 +235,7 @@ func dnsHandler(answers ...any) dns.HandlerFunc { switch a := a.(type) { default: panic(fmt.Sprintf("unsupported dnsHandler arg %T", a)) - case netaddr.IP: + case netip.Addr: ip := a if ip.Is4() { m.Answer = append(m.Answer, &dns.A{ diff --git a/net/dns/resolver/tsdns_test.go b/net/dns/resolver/tsdns_test.go index ef73833be..774de0a2a 100644 --- a/net/dns/resolver/tsdns_test.go +++ b/net/dns/resolver/tsdns_test.go @@ -43,7 +43,7 @@ ) var dnsCfg = Config{ - Hosts: map[dnsname.FQDN][]netaddr.IP{ + Hosts: map[dnsname.FQDN][]netip.Addr{ "test1.ipn.dev.": {testipv4}, "test2.ipn.dev.": {testipv6}, }, @@ -92,7 +92,7 @@ func dnspacket(domain dnsname.FQDN, tp dns.Type, ednsSize uint16) []byte { } type dnsResponse struct { - ip netaddr.IP + ip netip.Addr txt []string name dnsname.FQDN rcode dns.RCode @@ -157,7 +157,7 @@ func unpackResponse(payload []byte) (dnsResponse, error) { if err != nil { return response, err } - response.ip = netaddr.IPv6Raw(res.AAAA) + response.ip = netip.AddrFrom16(res.AAAA) case dns.TypeTXT: res, err := parser.TXTResource() if err != nil { @@ -234,10 +234,10 @@ func unpackResponse(payload []byte) (dnsResponse, error) { } func syncRespond(r *Resolver, query []byte) ([]byte, error) { - return r.Query(context.Background(), query, netaddr.IPPort{}) + return r.Query(context.Background(), query, netip.AddrPort{}) } -func mustIP(str string) netaddr.IP { +func mustIP(str string) netip.Addr { ip, err := netip.ParseAddr(str) if err != nil { panic(err) @@ -249,13 +249,13 @@ func TestRDNSNameToIPv4(t *testing.T) { tests := []struct { name string input dnsname.FQDN - wantIP netaddr.IP + wantIP netip.Addr wantOK bool }{ {"valid", "4.123.24.1.in-addr.arpa.", netaddr.IPv4(1, 24, 123, 4), true}, - {"double_dot", "1..2.3.in-addr.arpa.", netaddr.IP{}, false}, - {"overflow", "1.256.3.4.in-addr.arpa.", netaddr.IP{}, false}, - {"not_ip", "sub.do.ma.in.in-addr.arpa.", netaddr.IP{}, false}, + {"double_dot", "1..2.3.in-addr.arpa.", netip.Addr{}, false}, + {"overflow", "1.256.3.4.in-addr.arpa.", netip.Addr{}, false}, + {"not_ip", "sub.do.ma.in.in-addr.arpa.", netip.Addr{}, false}, } for _, tt := range tests { @@ -274,7 +274,7 @@ func TestRDNSNameToIPv6(t *testing.T) { tests := []struct { name string input dnsname.FQDN - wantIP netaddr.IP + wantIP netip.Addr wantOK bool }{ { @@ -286,19 +286,19 @@ func TestRDNSNameToIPv6(t *testing.T) { { "double_dot", "b..9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.", - netaddr.IP{}, + netip.Addr{}, false, }, { "double_hex", "b.a.98.0.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.", - netaddr.IP{}, + netip.Addr{}, false, }, { "not_hex", "b.a.g.0.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.", - netaddr.IP{}, + netip.Addr{}, false, }, } @@ -329,27 +329,27 @@ func TestResolveLocal(t *testing.T) { name string qname dnsname.FQDN qtype dns.Type - ip netaddr.IP + ip netip.Addr code dns.RCode }{ {"ipv4", "test1.ipn.dev.", dns.TypeA, testipv4, dns.RCodeSuccess}, {"ipv6", "test2.ipn.dev.", dns.TypeAAAA, testipv6, dns.RCodeSuccess}, - {"no-ipv6", "test1.ipn.dev.", dns.TypeAAAA, netaddr.IP{}, dns.RCodeSuccess}, - {"nxdomain", "test3.ipn.dev.", dns.TypeA, netaddr.IP{}, dns.RCodeNameError}, - {"foreign domain", "google.com.", dns.TypeA, netaddr.IP{}, dns.RCodeRefused}, + {"no-ipv6", "test1.ipn.dev.", dns.TypeAAAA, netip.Addr{}, dns.RCodeSuccess}, + {"nxdomain", "test3.ipn.dev.", dns.TypeA, netip.Addr{}, dns.RCodeNameError}, + {"foreign domain", "google.com.", dns.TypeA, netip.Addr{}, dns.RCodeRefused}, {"all", "test1.ipn.dev.", dns.TypeA, testipv4, dns.RCodeSuccess}, - {"mx-ipv4", "test1.ipn.dev.", dns.TypeMX, netaddr.IP{}, dns.RCodeSuccess}, - {"mx-ipv6", "test2.ipn.dev.", dns.TypeMX, netaddr.IP{}, dns.RCodeSuccess}, - {"mx-nxdomain", "test3.ipn.dev.", dns.TypeMX, netaddr.IP{}, dns.RCodeNameError}, - {"ns-nxdomain", "test3.ipn.dev.", dns.TypeNS, netaddr.IP{}, dns.RCodeNameError}, - {"onion-domain", "footest.onion.", dns.TypeA, netaddr.IP{}, dns.RCodeNameError}, + {"mx-ipv4", "test1.ipn.dev.", dns.TypeMX, netip.Addr{}, dns.RCodeSuccess}, + {"mx-ipv6", "test2.ipn.dev.", dns.TypeMX, netip.Addr{}, dns.RCodeSuccess}, + {"mx-nxdomain", "test3.ipn.dev.", dns.TypeMX, netip.Addr{}, dns.RCodeNameError}, + {"ns-nxdomain", "test3.ipn.dev.", dns.TypeNS, netip.Addr{}, dns.RCodeNameError}, + {"onion-domain", "footest.onion.", dns.TypeA, netip.Addr{}, dns.RCodeNameError}, {"magicdns", dnsSymbolicFQDN, dns.TypeA, netip.MustParseAddr("100.100.100.100"), dns.RCodeSuccess}, {"via_hex", dnsname.FQDN("via-0xff.1.2.3.4."), dns.TypeAAAA, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0:ff:1.2.3.4"), dns.RCodeSuccess}, {"via_dec", dnsname.FQDN("via-1.10.0.0.1."), dns.TypeAAAA, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0:1:10.0.0.1"), dns.RCodeSuccess}, {"x_via_hex", dnsname.FQDN("4.3.2.1.via-0xff."), dns.TypeAAAA, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0:ff:4.3.2.1"), dns.RCodeSuccess}, {"x_via_dec", dnsname.FQDN("1.0.0.10.via-1."), dns.TypeAAAA, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0:1:1.0.0.10"), dns.RCodeSuccess}, - {"via_invalid", dnsname.FQDN("via-."), dns.TypeAAAA, netaddr.IP{}, dns.RCodeRefused}, - {"via_invalid_2", dnsname.FQDN("2.3.4.5.via-."), dns.TypeAAAA, netaddr.IP{}, dns.RCodeRefused}, + {"via_invalid", dnsname.FQDN("via-."), dns.TypeAAAA, netip.Addr{}, dns.RCodeRefused}, + {"via_invalid_2", dnsname.FQDN("2.3.4.5.via-."), dns.TypeAAAA, netip.Addr{}, dns.RCodeRefused}, } for _, tt := range tests { @@ -1003,7 +1003,7 @@ func TestForwardLinkSelection(t *testing.T) { // routes differently. specialIP := netaddr.IPv4(1, 2, 3, 4) - fwd := newForwarder(t.Logf, nil, linkSelFunc(func(ip netaddr.IP) string { + fwd := newForwarder(t.Logf, nil, linkSelFunc(func(ip netip.Addr) string { if ip == netaddr.IPv4(1, 2, 3, 4) { return "special" } @@ -1011,7 +1011,7 @@ func TestForwardLinkSelection(t *testing.T) { }), new(tsdial.Dialer)) // Test non-special IP. - if got, err := fwd.packetListener(netaddr.IP{}); err != nil { + if got, err := fwd.packetListener(netip.Addr{}); err != nil { t.Fatal(err) } else if got != stdNetPacketListener { t.Errorf("for IP zero value, didn't get expected packet listener") @@ -1035,9 +1035,9 @@ func TestForwardLinkSelection(t *testing.T) { } } -type linkSelFunc func(ip netaddr.IP) string +type linkSelFunc func(ip netip.Addr) string -func (f linkSelFunc) PickLink(ip netaddr.IP) string { return f(ip) } +func (f linkSelFunc) PickLink(ip netip.Addr) string { return f(ip) } func TestHandleExitNodeDNSQueryWithNetPkg(t *testing.T) { if runtime.GOOS == "windows" { diff --git a/net/dnscache/dnscache.go b/net/dnscache/dnscache.go index 18031af3b..875361a22 100644 --- a/net/dnscache/dnscache.go +++ b/net/dnscache/dnscache.go @@ -15,6 +15,7 @@ "fmt" "log" "net" + "net/netip" "runtime" "sync" "time" @@ -62,7 +63,7 @@ type Resolver struct { // LookupIPFallback optionally provides a backup DNS mechanism // to use if Forward returns an error or no results. - LookupIPFallback func(ctx context.Context, host string) ([]netaddr.IP, error) + LookupIPFallback func(ctx context.Context, host string) ([]netip.Addr, error) // TTL is how long to keep entries cached // @@ -76,7 +77,7 @@ type Resolver struct { // SingleHostStaticResult, if non-nil, is the static result of IPs that is returned // by Resolver.LookupIP for any hostname. When non-nil, SingleHost must also be // set with the expected name. - SingleHostStaticResult []netaddr.IP + SingleHostStaticResult []netip.Addr // SingleHost is the hostname that SingleHostStaticResult is for. // It is required when SingleHostStaticResult is present. @@ -271,7 +272,7 @@ func (r *Resolver) lookupIP(host string) (ip, ip6 net.IP, allIPs []net.IPAddr, e if (err != nil || len(ips) == 0) && r.LookupIPFallback != nil { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - var fips []netaddr.IP + var fips []netip.Addr fips, err = r.LookupIPFallback(ctx, host) if err == nil { ips = nil @@ -344,7 +345,7 @@ func Dialer(fwd DialContextFunc, dnsCache *Resolver) DialContextFunc { d := &dialer{ fwd: fwd, dnsCache: dnsCache, - pastConnect: map[netaddr.IP]time.Time{}, + pastConnect: map[netip.Addr]time.Time{}, } return d.DialContext } @@ -355,7 +356,7 @@ type dialer struct { dnsCache *Resolver mu sync.Mutex - pastConnect map[netaddr.IP]time.Time + pastConnect map[netip.Addr]time.Time } func (d *dialer) DialContext(ctx context.Context, network, address string) (retConn net.Conn, ret error) { @@ -426,7 +427,7 @@ type dialCall struct { network, address, host, port string mu sync.Mutex // lock ordering: dialer.mu, then dialCall.mu - fails map[netaddr.IP]error // set of IPs that failed to dial thus far + fails map[netip.Addr]error // set of IPs that failed to dial thus far } // dnsWasTrustworthy reports whether we think the IP address(es) we @@ -453,7 +454,7 @@ func (dc *dialCall) dnsWasTrustworthy() bool { return false } -func (dc *dialCall) dialOne(ctx context.Context, ip netaddr.IP) (net.Conn, error) { +func (dc *dialCall) dialOne(ctx context.Context, ip netip.Addr) (net.Conn, error) { c, err := dc.d.fwd(ctx, dc.network, net.JoinHostPort(ip.String(), dc.port)) dc.noteDialResult(ip, err) return c, err @@ -461,7 +462,7 @@ func (dc *dialCall) dialOne(ctx context.Context, ip netaddr.IP) (net.Conn, error // noteDialResult records that a dial to ip either succeeded or // failed. -func (dc *dialCall) noteDialResult(ip netaddr.IP, err error) { +func (dc *dialCall) noteDialResult(ip netip.Addr, err error) { if err == nil { d := dc.d d.mu.Lock() @@ -472,17 +473,17 @@ func (dc *dialCall) noteDialResult(ip netaddr.IP, err error) { dc.mu.Lock() defer dc.mu.Unlock() if dc.fails == nil { - dc.fails = map[netaddr.IP]error{} + dc.fails = map[netip.Addr]error{} } dc.fails[ip] = err } // uniqueIPs returns a possibly-mutated subslice of ips, filtering out // dups and ones that have already failed previously. -func (dc *dialCall) uniqueIPs(ips []netaddr.IP) (ret []netaddr.IP) { +func (dc *dialCall) uniqueIPs(ips []netip.Addr) (ret []netip.Addr) { dc.mu.Lock() defer dc.mu.Unlock() - seen := map[netaddr.IP]bool{} + seen := map[netip.Addr]bool{} ret = ips[:0] for _, ip := range ips { if seen[ip] { @@ -504,7 +505,7 @@ func (dc *dialCall) uniqueIPs(ips []netaddr.IP) (ret []netaddr.IP) { // raceDial tries to dial port on each ip in ips, starting a new race // dial every fallbackDelay apart, returning whichever completes first. -func (dc *dialCall) raceDial(ctx context.Context, ips []netaddr.IP) (net.Conn, error) { +func (dc *dialCall) raceDial(ctx context.Context, ips []netip.Addr) (net.Conn, error) { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -536,7 +537,7 @@ type res struct { return } } - go func(ip netaddr.IP) { + go func(ip netip.Addr) { c, err := dc.dialOne(ctx, ip) if err != nil { // Best effort wake-up a pending dial. @@ -580,7 +581,7 @@ type res struct { } } -func v4addrs(aa []net.IPAddr) (ret []netaddr.IP) { +func v4addrs(aa []net.IPAddr) (ret []netip.Addr) { for _, a := range aa { if ip, ok := netaddr.FromStdIP(a.IP); ok && ip.Is4() { ret = append(ret, ip) @@ -589,7 +590,7 @@ func v4addrs(aa []net.IPAddr) (ret []netaddr.IP) { return ret } -func v6addrs(aa []net.IPAddr) (ret []netaddr.IP) { +func v6addrs(aa []net.IPAddr) (ret []netip.Addr) { for _, a := range aa { if ip, ok := netaddr.FromStdIP(a.IP); ok && ip.Is6() { ret = append(ret, ip) diff --git a/net/dnscache/dnscache_test.go b/net/dnscache/dnscache_test.go index 4e1451214..29fcd8e39 100644 --- a/net/dnscache/dnscache_test.go +++ b/net/dnscache/dnscache_test.go @@ -14,8 +14,6 @@ "reflect" "testing" "time" - - "tailscale.com/net/netaddr" ) var dialTest = flag.String("dial-test", "", "if non-empty, addr:port to test dial") @@ -40,7 +38,7 @@ func TestDialer(t *testing.T) { func TestDialCall_DNSWasTrustworthy(t *testing.T) { type step struct { - ip netaddr.IP // IP we pretended to dial + ip netip.Addr // IP we pretended to dial err error // the dial error or nil for success } mustIP := netip.MustParseAddr @@ -73,7 +71,7 @@ type step struct { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d := &dialer{ - pastConnect: map[netaddr.IP]time.Time{}, + pastConnect: map[netip.Addr]time.Time{}, } dc := &dialCall{ d: d, @@ -95,7 +93,7 @@ func TestDialCall_uniqueIPs(t *testing.T) { errFail := errors.New("some connect failure") dc.noteDialResult(mustIP("2003::1"), errFail) dc.noteDialResult(mustIP("2003::2"), errFail) - got := dc.uniqueIPs([]netaddr.IP{ + got := dc.uniqueIPs([]netip.Addr{ mustIP("2003::1"), mustIP("2003::2"), mustIP("2003::2"), @@ -104,7 +102,7 @@ func TestDialCall_uniqueIPs(t *testing.T) { mustIP("2003::4"), mustIP("2003::4"), }) - want := []netaddr.IP{ + want := []netip.Addr{ mustIP("2003::3"), mustIP("2003::4"), } @@ -116,7 +114,7 @@ func TestDialCall_uniqueIPs(t *testing.T) { func TestResolverAllHostStaticResult(t *testing.T) { r := &Resolver{ SingleHost: "foo.bar", - SingleHostStaticResult: []netaddr.IP{ + SingleHostStaticResult: []netip.Addr{ netip.MustParseAddr("2001:4860:4860::8888"), netip.MustParseAddr("2001:4860:4860::8844"), netip.MustParseAddr("8.8.8.8"), diff --git a/net/dnsfallback/dnsfallback.go b/net/dnsfallback/dnsfallback.go index 1cf698403..80bc1fcf1 100644 --- a/net/dnsfallback/dnsfallback.go +++ b/net/dnsfallback/dnsfallback.go @@ -22,21 +22,20 @@ "net/url" "time" - "tailscale.com/net/netaddr" "tailscale.com/net/netns" "tailscale.com/net/tlsdial" "tailscale.com/net/tshttpproxy" "tailscale.com/tailcfg" ) -func Lookup(ctx context.Context, host string) ([]netaddr.IP, error) { +func Lookup(ctx context.Context, host string) ([]netip.Addr, error) { if ip, err := netip.ParseAddr(host); err == nil && ip.IsValid() { - return []netaddr.IP{ip}, nil + return []netip.Addr{ip}, nil } type nameIP struct { dnsName string - ip netaddr.IP + ip netip.Addr } dm := getDERPMap() @@ -94,7 +93,7 @@ type nameIP struct { // serverName and serverIP of are, say, "derpN.tailscale.com". // queryName is the name being sought (e.g. "controlplane.tailscale.com"), passed as hint. -func bootstrapDNSMap(ctx context.Context, serverName string, serverIP netaddr.IP, queryName string) (dnsMap, error) { +func bootstrapDNSMap(ctx context.Context, serverName string, serverIP netip.Addr, queryName string) (dnsMap, error) { dialer := netns.NewDialer(log.Printf) tr := http.DefaultTransport.(*http.Transport).Clone() tr.Proxy = tshttpproxy.ProxyFromEnvironment @@ -124,7 +123,7 @@ func bootstrapDNSMap(ctx context.Context, serverName string, serverIP netaddr.IP // dnsMap is the JSON type returned by the DERP /bootstrap-dns handler: // https://derp10.tailscale.com/bootstrap-dns -type dnsMap map[string][]netaddr.IP +type dnsMap map[string][]netip.Addr // getDERPMap returns some DERP map. The DERP servers also run a fallback // DNS server. diff --git a/net/flowtrack/flowtrack.go b/net/flowtrack/flowtrack.go index 61cde8738..9fcf62618 100644 --- a/net/flowtrack/flowtrack.go +++ b/net/flowtrack/flowtrack.go @@ -13,16 +13,16 @@ import ( "container/list" "fmt" + "net/netip" - "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) // Tuple is a 5-tuple of proto, source and destination IP and port. type Tuple struct { Proto ipproto.Proto - Src netaddr.IPPort - Dst netaddr.IPPort + Src netip.AddrPort + Dst netip.AddrPort } func (t Tuple) String() string { diff --git a/net/interfaces/interfaces.go b/net/interfaces/interfaces.go index 6a93054c4..bc1d138e6 100644 --- a/net/interfaces/interfaces.go +++ b/net/interfaces/interfaces.go @@ -28,7 +28,7 @@ // Tailscale returns the current machine's Tailscale interface, if any. // If none is found, all zero values are returned. // A non-nil error is only returned on a problem listing the system interfaces. -func Tailscale() ([]netaddr.IP, *net.Interface, error) { +func Tailscale() ([]netip.Addr, *net.Interface, error) { ifs, err := netInterfaces() if err != nil { return nil, nil, err @@ -41,7 +41,7 @@ func Tailscale() ([]netaddr.IP, *net.Interface, error) { if err != nil { continue } - var tsIPs []netaddr.IP + var tsIPs []netip.Addr for _, a := range addrs { if ipnet, ok := a.(*net.IPNet); ok { nip, ok := netaddr.FromStdIP(ipnet.IP) @@ -86,13 +86,13 @@ func isProblematicInterface(nif *net.Interface) bool { // whether they're loopback addresses. If there are no regular addresses // it will return any IPv4 linklocal or IPv6 unique local addresses because we // know of environments where these are used with NAT to provide connectivity. -func LocalAddresses() (regular, loopback []netaddr.IP, err error) { +func LocalAddresses() (regular, loopback []netip.Addr, err error) { // TODO(crawshaw): don't serve interface addresses that we are routing ifaces, err := netInterfaces() if err != nil { return nil, nil, err } - var regular4, regular6, linklocal4, ula6 []netaddr.IP + var regular4, regular6, linklocal4, ula6 []netip.Addr for _, iface := range ifaces { stdIf := iface.Interface if !isUp(stdIf) || isProblematicInterface(stdIf) { @@ -165,7 +165,7 @@ func LocalAddresses() (regular, loopback []netaddr.IP, err error) { return regular, loopback, nil } -func sortIPs(s []netaddr.IP) { +func sortIPs(s []netip.Addr) { sort.Slice(s, func(i, j int) bool { return s[i].Less(s[j]) }) } @@ -187,7 +187,7 @@ func (i Interface) Addrs() ([]net.Addr, error) { // ForeachInterfaceAddress is a wrapper for GetList, then // List.ForeachInterfaceAddress. -func ForeachInterfaceAddress(fn func(Interface, netaddr.IPPrefix)) error { +func ForeachInterfaceAddress(fn func(Interface, netip.Prefix)) error { ifaces, err := GetList() if err != nil { return err @@ -198,7 +198,7 @@ func ForeachInterfaceAddress(fn func(Interface, netaddr.IPPrefix)) error { // ForeachInterfaceAddress calls fn for each interface in ifaces, with // all its addresses. The IPPrefix's IP is the IP address assigned to // the interface, and Bits are the subnet mask. -func (ifaces List) ForeachInterfaceAddress(fn func(Interface, netaddr.IPPrefix)) error { +func (ifaces List) ForeachInterfaceAddress(fn func(Interface, netip.Prefix)) error { for _, iface := range ifaces { addrs, err := iface.Addrs() if err != nil { @@ -218,7 +218,7 @@ func (ifaces List) ForeachInterfaceAddress(fn func(Interface, netaddr.IPPrefix)) // ForeachInterface is a wrapper for GetList, then // List.ForeachInterface. -func ForeachInterface(fn func(Interface, []netaddr.IPPrefix)) error { +func ForeachInterface(fn func(Interface, []netip.Prefix)) error { ifaces, err := GetList() if err != nil { return err @@ -229,7 +229,7 @@ func ForeachInterface(fn func(Interface, []netaddr.IPPrefix)) error { // ForeachInterface calls fn for each interface in ifaces, with // all its addresses. The IPPrefix's IP is the IP address assigned to // the interface, and Bits are the subnet mask. -func (ifaces List) ForeachInterface(fn func(Interface, []netaddr.IPPrefix)) error { +func (ifaces List) ForeachInterface(fn func(Interface, []netip.Prefix)) error { ifaces, err := GetList() if err != nil { return err @@ -239,7 +239,7 @@ func (ifaces List) ForeachInterface(fn func(Interface, []netaddr.IPPrefix)) erro if err != nil { return err } - var pfxs []netaddr.IPPrefix + var pfxs []netip.Prefix for _, a := range addrs { switch v := a.(type) { case *net.IPNet: @@ -264,7 +264,7 @@ type State struct { // configured on that interface. Each address is represented as an // IPPrefix, where the IP is the interface IP address and Bits is // the subnet mask. - InterfaceIPs map[string][]netaddr.IPPrefix + InterfaceIPs map[string][]netip.Prefix Interface map[string]Interface // HaveV6 is whether this machine has an IPv6 Global or Unique Local Address @@ -358,11 +358,11 @@ func (s *State) String() string { // An InterfaceFilter indicates whether EqualFiltered should use i when deciding whether two States are equal. // ips are all the IPPrefixes associated with i. -type InterfaceFilter func(i Interface, ips []netaddr.IPPrefix) bool +type InterfaceFilter func(i Interface, ips []netip.Prefix) bool // An IPFilter indicates whether EqualFiltered should use ip when deciding whether two States are equal. // ip is an ip address associated with some interface under consideration. -type IPFilter func(ip netaddr.IP) bool +type IPFilter func(ip netip.Addr) bool // EqualFiltered reports whether s and s2 are equal, // considering only interfaces in s for which filter returns true, @@ -410,9 +410,9 @@ func interfacesEqual(a, b Interface) bool { bytes.Equal([]byte(a.HardwareAddr), []byte(b.HardwareAddr)) } -func filteredIPPs(ipps []netaddr.IPPrefix, useIP IPFilter) []netaddr.IPPrefix { +func filteredIPPs(ipps []netip.Prefix, useIP IPFilter) []netip.Prefix { // TODO: rewrite prefixesEqualFiltered to avoid making copies - x := make([]netaddr.IPPrefix, 0, len(ipps)) + x := make([]netip.Prefix, 0, len(ipps)) for _, ipp := range ipps { if useIP(ipp.Addr()) { x = append(x, ipp) @@ -421,11 +421,11 @@ func filteredIPPs(ipps []netaddr.IPPrefix, useIP IPFilter) []netaddr.IPPrefix { return x } -func prefixesEqualFiltered(a, b []netaddr.IPPrefix, useIP IPFilter) bool { +func prefixesEqualFiltered(a, b []netip.Prefix, useIP IPFilter) bool { return prefixesEqual(filteredIPPs(a, useIP), filteredIPPs(b, useIP)) } -func prefixesEqual(a, b []netaddr.IPPrefix) bool { +func prefixesEqual(a, b []netip.Prefix) bool { if len(a) != len(b) { return false } @@ -440,21 +440,21 @@ func prefixesEqual(a, b []netaddr.IPPrefix) bool { // UseInterestingInterfaces is an InterfaceFilter that reports whether i is an interesting interface. // An interesting interface if it is (a) not owned by Tailscale and (b) routes interesting IP addresses. // See UseInterestingIPs for the defition of an interesting IP address. -func UseInterestingInterfaces(i Interface, ips []netaddr.IPPrefix) bool { +func UseInterestingInterfaces(i Interface, ips []netip.Prefix) bool { return !isTailscaleInterface(i.Name, ips) && anyInterestingIP(ips) } // UseInterestingIPs is an IPFilter that reports whether ip is an interesting IP address. // An IP address is interesting if it is neither a lopback not a link local unicast IP address. -func UseInterestingIPs(ip netaddr.IP) bool { +func UseInterestingIPs(ip netip.Addr) bool { return isInterestingIP(ip) } // UseAllInterfaces is an InterfaceFilter that includes all interfaces. -func UseAllInterfaces(i Interface, ips []netaddr.IPPrefix) bool { return true } +func UseAllInterfaces(i Interface, ips []netip.Prefix) bool { return true } // UseAllIPs is an IPFilter that includes all all IPs. -func UseAllIPs(ips netaddr.IP) bool { return true } +func UseAllIPs(ips netip.Addr) bool { return true } func (s *State) HasPAC() bool { return s != nil && s.PAC != "" } @@ -466,7 +466,7 @@ func (s *State) AnyInterfaceUp() bool { return s != nil && (s.HaveV4 || s.HaveV6) } -func hasTailscaleIP(pfxs []netaddr.IPPrefix) bool { +func hasTailscaleIP(pfxs []netip.Prefix) bool { for _, pfx := range pfxs { if tsaddr.IsTailscaleIP(pfx.Addr()) { return true @@ -475,7 +475,7 @@ func hasTailscaleIP(pfxs []netaddr.IPPrefix) bool { return false } -func isTailscaleInterface(name string, ips []netaddr.IPPrefix) bool { +func isTailscaleInterface(name string, ips []netip.Prefix) bool { if runtime.GOOS == "darwin" && strings.HasPrefix(name, "utun") && hasTailscaleIP(ips) { // On macOS in the sandboxed app (at least as of // 2021-02-25), we often see two utun devices @@ -497,10 +497,10 @@ func isTailscaleInterface(name string, ips []netaddr.IPPrefix) bool { // It does not set the returned State.IsExpensive. The caller can populate that. func GetState() (*State, error) { s := &State{ - InterfaceIPs: make(map[string][]netaddr.IPPrefix), + InterfaceIPs: make(map[string][]netip.Prefix), Interface: make(map[string]Interface), } - if err := ForeachInterface(func(ni Interface, pfxs []netaddr.IPPrefix) { + if err := ForeachInterface(func(ni Interface, pfxs []netip.Prefix) { ifUp := ni.IsUp() s.Interface[ni.Name] = ni s.InterfaceIPs[ni.Name] = append(s.InterfaceIPs[ni.Name], pfxs...) @@ -556,7 +556,7 @@ func HTTPOfListener(ln net.Listener) string { var goodIP string var privateIP string - ForeachInterfaceAddress(func(i Interface, pfx netaddr.IPPrefix) { + ForeachInterfaceAddress(func(i Interface, pfx netip.Prefix) { ip := pfx.Addr() if ip.IsPrivate() { if privateIP == "" { @@ -576,14 +576,14 @@ func HTTPOfListener(ln net.Listener) string { } -var likelyHomeRouterIP func() (netaddr.IP, bool) +var likelyHomeRouterIP func() (netip.Addr, bool) // LikelyHomeRouterIP returns the likely IP of the residential router, // which will always be an IPv4 private address, if found. // In addition, it returns the IP address of the current machine on // the LAN using that gateway. // This is used as the destination for UPnP, NAT-PMP, PCP, etc queries. -func LikelyHomeRouterIP() (gateway, myIP netaddr.IP, ok bool) { +func LikelyHomeRouterIP() (gateway, myIP netip.Addr, ok bool) { if likelyHomeRouterIP != nil { gateway, ok = likelyHomeRouterIP() if !ok { @@ -593,7 +593,7 @@ func LikelyHomeRouterIP() (gateway, myIP netaddr.IP, ok bool) { if !ok { return } - ForeachInterfaceAddress(func(i Interface, pfx netaddr.IPPrefix) { + ForeachInterfaceAddress(func(i Interface, pfx netip.Prefix) { ip := pfx.Addr() if !i.IsUp() || !ip.IsValid() || myIP.IsValid() { return @@ -611,7 +611,7 @@ func LikelyHomeRouterIP() (gateway, myIP netaddr.IP, ok bool) { // conceivably be used to get Internet connectivity. Globally routable and // private IPv4 addresses are always Usable, and link local 169.254.x.x // addresses are in some environments. -func isUsableV4(ip netaddr.IP) bool { +func isUsableV4(ip netip.Addr) bool { if !ip.Is4() || ip.IsLoopback() { return false } @@ -625,7 +625,7 @@ func isUsableV4(ip netaddr.IP) bool { // conceivably be used to get Internet connectivity. Globally routable // IPv6 addresses are always Usable, and Unique Local Addresses // (fc00::/7) are in some environments used with address translation. -func isUsableV6(ip netaddr.IP) bool { +func isUsableV6(ip netip.Addr) bool { return v6Global1.Contains(ip) || (ip.Is6() && ip.IsPrivate() && !tsaddr.TailscaleULARange().Contains(ip)) } @@ -636,7 +636,7 @@ func isUsableV6(ip netaddr.IP) bool { // anyInterestingIP reports whether pfxs contains any IP that matches // isInterestingIP. -func anyInterestingIP(pfxs []netaddr.IPPrefix) bool { +func anyInterestingIP(pfxs []netip.Prefix) bool { for _, pfx := range pfxs { if isInterestingIP(pfx.Addr()) { return true @@ -648,7 +648,7 @@ func anyInterestingIP(pfxs []netaddr.IPPrefix) bool { // isInterestingIP reports whether ip is an interesting IP that we // should log in interfaces.State logging. We don't need to show // localhost or link-local addresses. -func isInterestingIP(ip netaddr.IP) bool { +func isInterestingIP(ip netip.Addr) bool { return !ip.IsLoopback() && !ip.IsLinkLocalUnicast() } @@ -727,7 +727,7 @@ func DefaultRoute() (DefaultRouteDetails, error) { func HasCGNATInterface() (bool, error) { hasCGNATInterface := false cgnatRange := tsaddr.CGNATRange() - err := ForeachInterface(func(i Interface, pfxs []netaddr.IPPrefix) { + err := ForeachInterface(func(i Interface, pfxs []netip.Prefix) { if hasCGNATInterface || !i.IsUp() || isTailscaleInterface(i.Name, pfxs) { return } diff --git a/net/interfaces/interfaces_bsd.go b/net/interfaces/interfaces_bsd.go index 5e35ffbe9..60bba1d95 100644 --- a/net/interfaces/interfaces_bsd.go +++ b/net/interfaces/interfaces_bsd.go @@ -15,6 +15,7 @@ "fmt" "log" "net" + "net/netip" "syscall" "golang.org/x/net/route" @@ -95,7 +96,7 @@ func init() { likelyHomeRouterIP = likelyHomeRouterIPBSDFetchRIB } -func likelyHomeRouterIPBSDFetchRIB() (ret netaddr.IP, ok bool) { +func likelyHomeRouterIPBSDFetchRIB() (ret netip.Addr, ok bool) { rib, err := fetchRoutingTable() if err != nil { log.Printf("routerIP/FetchRIB: %v", err) diff --git a/net/interfaces/interfaces_darwin.go b/net/interfaces/interfaces_darwin.go index 5453e9e6a..60335bf80 100644 --- a/net/interfaces/interfaces_darwin.go +++ b/net/interfaces/interfaces_darwin.go @@ -9,6 +9,7 @@ "fmt" "log" "net" + "net/netip" "syscall" "golang.org/x/net/route" @@ -89,7 +90,7 @@ func init() { likelyHomeRouterIP = likelyHomeRouterIPDarwinFetchRIB } -func likelyHomeRouterIPDarwinFetchRIB() (ret netaddr.IP, ok bool) { +func likelyHomeRouterIPDarwinFetchRIB() (ret netip.Addr, ok bool) { rib, err := fetchRoutingTable() if err != nil { log.Printf("routerIP/FetchRIB: %v", err) diff --git a/net/interfaces/interfaces_darwin_test.go b/net/interfaces/interfaces_darwin_test.go index 36ceb890e..0ee238caf 100644 --- a/net/interfaces/interfaces_darwin_test.go +++ b/net/interfaces/interfaces_darwin_test.go @@ -11,7 +11,6 @@ "testing" "go4.org/mem" - "tailscale.com/net/netaddr" "tailscale.com/util/lineread" "tailscale.com/version" ) @@ -42,7 +41,7 @@ func TestLikelyHomeRouterIPSyscallExec(t *testing.T) { ... */ -func likelyHomeRouterIPDarwinExec() (ret netaddr.IP, ok bool) { +func likelyHomeRouterIPDarwinExec() (ret netip.Addr, ok bool) { if version.IsMobile() { // Don't try to do subprocesses on iOS. Ends up with log spam like: // kernel: "Sandbox: IPNExtension(86580) deny(1) process-fork" diff --git a/net/interfaces/interfaces_linux.go b/net/interfaces/interfaces_linux.go index e829eab8f..73c5ff22e 100644 --- a/net/interfaces/interfaces_linux.go +++ b/net/interfaces/interfaces_linux.go @@ -46,7 +46,7 @@ func init() { ens18 00000000 0100000A 0003 0 0 0 00000000 0 0 0 ens18 0000000A 00000000 0001 0 0 0 0000FFFF 0 0 0 */ -func likelyHomeRouterIPLinux() (ret netaddr.IP, ok bool) { +func likelyHomeRouterIPLinux() (ret netip.Addr, ok bool) { if procNetRouteErr.Get() { // If we failed to read /proc/net/route previously, don't keep trying. // But if we're on Android, go into the Android path. @@ -104,7 +104,7 @@ func likelyHomeRouterIPLinux() (ret netaddr.IP, ok bool) { // Android apps don't have permission to read /proc/net/route, at // least on Google devices and the Android emulator. -func likelyHomeRouterIPAndroid() (ret netaddr.IP, ok bool) { +func likelyHomeRouterIPAndroid() (ret netip.Addr, ok bool) { cmd := exec.Command("/system/bin/ip", "route", "show", "table", "0") out, err := cmd.StdoutPipe() if err != nil { diff --git a/net/interfaces/interfaces_test.go b/net/interfaces/interfaces_test.go index 9f7898ec3..7c1c135e6 100644 --- a/net/interfaces/interfaces_test.go +++ b/net/interfaces/interfaces_test.go @@ -9,8 +9,6 @@ "net" "net/netip" "testing" - - "tailscale.com/net/netaddr" ) func TestGetState(t *testing.T) { @@ -76,7 +74,7 @@ func TestStateEqualFilteredIPFilter(t *testing.T) { // has gained an "uninteresting" IP address. s1 := &State{ - InterfaceIPs: map[string][]netaddr.IPPrefix{"x": { + InterfaceIPs: map[string][]netip.Prefix{"x": { netip.MustParsePrefix("42.0.0.0/8"), netip.MustParsePrefix("169.254.0.0/16"), // link local unicast }}, @@ -84,7 +82,7 @@ func TestStateEqualFilteredIPFilter(t *testing.T) { } s2 := &State{ - InterfaceIPs: map[string][]netaddr.IPPrefix{"x": { + InterfaceIPs: map[string][]netip.Prefix{"x": { netip.MustParsePrefix("42.0.0.0/8"), netip.MustParsePrefix("169.254.0.0/16"), // link local unicast netip.MustParsePrefix("127.0.0.0/8"), // loopback (added) @@ -126,8 +124,8 @@ func TestStateString(t *testing.T) { Interface: &net.Interface{}, }, }, - InterfaceIPs: map[string][]netaddr.IPPrefix{ - "eth0": []netaddr.IPPrefix{ + InterfaceIPs: map[string][]netip.Prefix{ + "eth0": []netip.Prefix{ netip.MustParsePrefix("10.0.0.2/8"), }, }, diff --git a/net/interfaces/interfaces_windows.go b/net/interfaces/interfaces_windows.go index 3e82a87da..611d426fa 100644 --- a/net/interfaces/interfaces_windows.go +++ b/net/interfaces/interfaces_windows.go @@ -7,6 +7,7 @@ import ( "log" "net" + "net/netip" "net/url" "strings" "syscall" @@ -27,7 +28,7 @@ func init() { getPAC = getPACWindows } -func likelyHomeRouterIPWindows() (ret netaddr.IP, ok bool) { +func likelyHomeRouterIPWindows() (ret netip.Addr, ok bool) { rs, err := winipcfg.GetIPForwardTable2(windows.AF_INET) if err != nil { log.Printf("routerIP/GetIPForwardTable2 error: %v", err) @@ -94,7 +95,7 @@ func likelyHomeRouterIPWindows() (ret netaddr.IP, ok bool) { if ret.IsValid() && !ret.IsPrivate() { // Default route has a non-private gateway - return netaddr.IP{}, false + return netip.Addr{}, false } return ret, ret.IsValid() diff --git a/net/netaddr/netaddr.go b/net/netaddr/netaddr.go index bb50d9523..c4b2ea88c 100644 --- a/net/netaddr/netaddr.go +++ b/net/netaddr/netaddr.go @@ -15,14 +15,8 @@ "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 { +func IPv4(a, b, c, d uint8) netip.Addr { return netip.AddrFrom4([4]byte{a, b, c, d}) } @@ -30,41 +24,10 @@ func IPv4(a, b, c, d uint8) IP { // v6-mapped IPv4 address. // // It is equivalent to calling IPv6Raw(addr).Unmap(). -func IPFrom16(a [16]byte) IP { +func IPFrom16(a [16]byte) netip.Addr { 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. @@ -74,9 +37,9 @@ func FromStdIPRaw(std net.IP) (ip IP, ok bool) { // 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) +// netip.AddrFromSlice. +func FromStdIP(std net.IP) (ip netip.Addr, ok bool) { + ret, ok := netip.AddrFromSlice(std) if !ok { return ret, false } @@ -88,21 +51,21 @@ func FromStdIP(std net.IP) (ip IP, ok bool) { // 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) { +func FromStdIPNet(std *net.IPNet) (prefix netip.Prefix, ok bool) { ip, ok := FromStdIP(std.IP) if !ok { - return IPPrefix{}, false + return netip.Prefix{}, false } if l := len(std.Mask); l != net.IPv4len && l != net.IPv6len { // Invalid mask. - return IPPrefix{}, false + return netip.Prefix{}, false } ones, bits := std.Mask.Size() if ones == 0 && bits == 0 { // IPPrefix does not support non-contiguous masks. - return IPPrefix{}, false + return netip.Prefix{}, false } return netip.PrefixFrom(ip, ones), true @@ -110,7 +73,7 @@ func FromStdIPNet(std *net.IPNet) (prefix IPPrefix, ok bool) { // 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) { +func FromStdAddr(stdIP net.IP, port int, zone string) (_ netip.AddrPort, ok bool) { ip, ok := FromStdIP(stdIP) if !ok || port < 0 || port > math.MaxUint16 { return diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index 4bd72de32..577131feb 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -211,7 +211,7 @@ func (c *Client) vlogf(format string, a ...any) { // handleHairSTUN reports whether pkt (from src) was our magic hairpin // probe packet that we sent to ourselves. -func (c *Client) handleHairSTUNLocked(pkt []byte, src netaddr.IPPort) bool { +func (c *Client) handleHairSTUNLocked(pkt []byte, src netip.AddrPort) bool { rs := c.curState if rs == nil { return false @@ -234,7 +234,7 @@ func (c *Client) MakeNextReportFull() { c.nextFull = true } -func (c *Client) ReceiveSTUNPacket(pkt []byte, src netaddr.IPPort) { +func (c *Client) ReceiveSTUNPacket(pkt []byte, src netip.AddrPort) { c.vlogf("received STUN packet from %s", src) if src.Addr().Is4() { @@ -526,7 +526,7 @@ func (c *Client) readPackets(ctx context.Context, pc net.PacketConn) { type reportState struct { c *Client hairTX stun.TxID - gotHairSTUN chan netaddr.IPPort + gotHairSTUN chan netip.AddrPort hairTimeout chan struct{} // closed on timeout pc4 STUNConn pc6 STUNConn @@ -538,7 +538,7 @@ type reportState struct { mu sync.Mutex sentHairCheck bool report *Report // to be returned by GetReport - inFlight map[stun.TxID]func(netaddr.IPPort) // called without c.mu held + inFlight map[stun.TxID]func(netip.AddrPort) // called without c.mu held gotEP4 string timers []*time.Timer } @@ -590,7 +590,7 @@ func (rs *reportState) probeWouldHelp(probe probe, node *tailcfg.DERPNode) bool return false } -func (rs *reportState) startHairCheckLocked(dst netaddr.IPPort) { +func (rs *reportState) startHairCheckLocked(dst netip.AddrPort) { if rs.sentHairCheck || rs.incremental { return } @@ -642,9 +642,9 @@ func (rs *reportState) stopTimers() { // addNodeLatency updates rs to note that node's latency is d. If ipp // is non-zero (for all but HTTPS replies), it's recorded as our UDP // IP:port. -func (rs *reportState) addNodeLatency(node *tailcfg.DERPNode, ipp netaddr.IPPort, d time.Duration) { +func (rs *reportState) addNodeLatency(node *tailcfg.DERPNode, ipp netip.AddrPort, d time.Duration) { var ipPortStr string - if ipp != (netaddr.IPPort{}) { + if ipp != (netip.AddrPort{}) { ipPortStr = net.JoinHostPort(ipp.Addr().String(), fmt.Sprint(ipp.Port())) } @@ -772,9 +772,9 @@ func (c *Client) GetReport(ctx context.Context, dm *tailcfg.DERPMap) (_ *Report, rs := &reportState{ c: c, report: newReport(), - inFlight: map[stun.TxID]func(netaddr.IPPort){}, + inFlight: map[stun.TxID]func(netip.AddrPort){}, hairTX: stun.NewTxID(), // random payload - gotHairSTUN: make(chan netaddr.IPPort, 1), + gotHairSTUN: make(chan netip.AddrPort, 1), hairTimeout: make(chan struct{}), stopProbeCh: make(chan struct{}, 1), } @@ -1008,20 +1008,20 @@ func (c *Client) runHTTPOnlyChecks(ctx context.Context, last *Report, rs *report return } d := c.timeNow().Sub(t0) - rs.addNodeLatency(node, netaddr.IPPort{}, d) + rs.addNodeLatency(node, netip.AddrPort{}, d) }() } wg.Wait() return nil } -func (c *Client) measureHTTPSLatency(ctx context.Context, reg *tailcfg.DERPRegion) (time.Duration, netaddr.IP, error) { +func (c *Client) measureHTTPSLatency(ctx context.Context, reg *tailcfg.DERPRegion) (time.Duration, netip.Addr, error) { metricHTTPSend.Add(1) var result httpstat.Result ctx, cancel := context.WithTimeout(httpstat.WithHTTPStat(ctx, &result), overallProbeTimeout) defer cancel() - var ip netaddr.IP + var ip netip.Addr dc := derphttp.NewNetcheckClient(c.logf) tlsConn, tcpConn, node, err := dc.DialRegionTLS(ctx, reg) @@ -1033,7 +1033,7 @@ func (c *Client) measureHTTPSLatency(ctx context.Context, reg *tailcfg.DERPRegio if ta, ok := tlsConn.RemoteAddr().(*net.TCPAddr); ok { ip, _ = netaddr.FromStdIP(ta.IP) } - if ip == (netaddr.IP{}) { + if ip == (netip.Addr{}) { return 0, ip, fmt.Errorf("no unexpected RemoteAddr %#v", tlsConn.RemoteAddr()) } @@ -1250,7 +1250,7 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe sent := time.Now() // after DNS lookup above rs.mu.Lock() - rs.inFlight[txID] = func(ipp netaddr.IPPort) { + rs.inFlight[txID] = func(ipp netip.AddrPort) { rs.addNodeLatency(node, ipp, time.Since(sent)) cancelSet() // abort other nodes in this set } diff --git a/net/netcheck/netcheck_test.go b/net/netcheck/netcheck_test.go index ebb513240..6dec50a25 100644 --- a/net/netcheck/netcheck_test.go +++ b/net/netcheck/netcheck_test.go @@ -9,6 +9,7 @@ "context" "fmt" "net" + "net/netip" "reflect" "sort" "strconv" @@ -17,7 +18,6 @@ "time" "tailscale.com/net/interfaces" - "tailscale.com/net/netaddr" "tailscale.com/net/stun" "tailscale.com/net/stun/stuntest" "tailscale.com/tailcfg" @@ -28,14 +28,14 @@ func TestHairpinSTUN(t *testing.T) { c := &Client{ curState: &reportState{ hairTX: tx, - gotHairSTUN: make(chan netaddr.IPPort, 1), + gotHairSTUN: make(chan netip.AddrPort, 1), }, } req := stun.Request(tx) if !stun.Is(req) { t.Fatal("expected STUN message") } - if !c.handleHairSTUNLocked(req, netaddr.IPPort{}) { + if !c.handleHairSTUNLocked(req, netip.AddrPort{}) { t.Fatal("expected true") } select { diff --git a/net/netstat/netstat.go b/net/netstat/netstat.go index aa969d8ba..13edf0afb 100644 --- a/net/netstat/netstat.go +++ b/net/netstat/netstat.go @@ -7,15 +7,14 @@ import ( "errors" + "net/netip" "runtime" - - "tailscale.com/net/netaddr" ) var ErrNotImplemented = errors.New("not implemented for GOOS=" + runtime.GOOS) type Entry struct { - Local, Remote netaddr.IPPort + Local, Remote netip.AddrPort Pid int State string // TODO: type? } diff --git a/net/netstat/netstat_windows.go b/net/netstat/netstat_windows.go index b2979e65f..7d2467632 100644 --- a/net/netstat/netstat_windows.go +++ b/net/netstat/netstat_windows.go @@ -9,6 +9,7 @@ "errors" "fmt" "math/bits" + "net/netip" "syscall" "unsafe" @@ -153,22 +154,22 @@ func state(v uint32) string { return fmt.Sprintf("unknown-state-%d", v) } -func ipport4(addr uint32, port uint16) netaddr.IPPort { +func ipport4(addr uint32, port uint16) netip.AddrPort { if !endian.Big { addr = bits.ReverseBytes32(addr) } - return netaddr.IPPortFrom( + return netip.AddrPortFrom( netaddr.IPv4(byte(addr>>24), byte(addr>>16), byte(addr>>8), byte(addr)), port) } -func ipport6(addr [16]byte, scope uint32, port uint16) netaddr.IPPort { +func ipport6(addr [16]byte, scope uint32, port uint16) netip.AddrPort { ip := netaddr.IPFrom16(addr) if scope != 0 { // TODO: something better here? ip = ip.WithZone(fmt.Sprint(scope)) } - return netaddr.IPPortFrom(ip, port) + return netip.AddrPortFrom(ip, port) } func port(v *uint32) uint16 { diff --git a/net/netutil/ip_forward.go b/net/netutil/ip_forward.go index c42f2b240..f737538da 100644 --- a/net/netutil/ip_forward.go +++ b/net/netutil/ip_forward.go @@ -8,6 +8,7 @@ import ( "bytes" "fmt" + "net/netip" "os" "os/exec" "path/filepath" @@ -16,19 +17,18 @@ "strings" "tailscale.com/net/interfaces" - "tailscale.com/net/netaddr" ) // protocolsRequiredForForwarding reports whether IPv4 and/or IPv6 protocols are // required to forward the specified routes. // The state param must be specified. -func protocolsRequiredForForwarding(routes []netaddr.IPPrefix, state *interfaces.State) (v4, v6 bool) { +func protocolsRequiredForForwarding(routes []netip.Prefix, state *interfaces.State) (v4, v6 bool) { if len(routes) == 0 { // Nothing to route, so no need to warn. return false, false } - localIPs := make(map[netaddr.IP]bool) + localIPs := make(map[netip.Addr]bool) for _, addrs := range state.InterfaceIPs { for _, pfx := range addrs { localIPs[pfx.Addr()] = true @@ -59,7 +59,7 @@ func protocolsRequiredForForwarding(routes []netaddr.IPPrefix, state *interfaces // It returns an error if it is unable to determine if IP forwarding is enabled. // It returns a warning describing configuration issues if IP forwarding is // non-functional or partly functional. -func CheckIPForwarding(routes []netaddr.IPPrefix, state *interfaces.State) (warn, err error) { +func CheckIPForwarding(routes []netip.Prefix, state *interfaces.State) (warn, err error) { if runtime.GOOS != "linux" { switch runtime.GOOS { case "dragonfly", "freebsd", "netbsd", "openbsd": diff --git a/net/packet/ip4.go b/net/packet/ip4.go index 21941d733..2b9ccf8d4 100644 --- a/net/packet/ip4.go +++ b/net/packet/ip4.go @@ -7,8 +7,8 @@ import ( "encoding/binary" "errors" + "net/netip" - "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) @@ -19,8 +19,8 @@ type IP4Header struct { IPProto ipproto.Proto IPID uint16 - Src netaddr.IP - Dst netaddr.IP + Src netip.Addr + Dst netip.Addr } // Len implements Header. diff --git a/net/packet/ip6.go b/net/packet/ip6.go index 4f30aea3c..f829f3f28 100644 --- a/net/packet/ip6.go +++ b/net/packet/ip6.go @@ -6,8 +6,8 @@ import ( "encoding/binary" + "net/netip" - "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) @@ -18,8 +18,8 @@ type IP6Header struct { IPProto ipproto.Proto IPID uint32 // only lower 20 bits used - Src netaddr.IP - Dst netaddr.IP + Src netip.Addr + Dst netip.Addr } // Len implements Header. diff --git a/net/packet/packet.go b/net/packet/packet.go index 79e5b7412..7b97d856a 100644 --- a/net/packet/packet.go +++ b/net/packet/packet.go @@ -54,9 +54,9 @@ type Parsed struct { IPProto ipproto.Proto // SrcIP4 is the source address. Family matches IPVersion. Port is // valid iff IPProto == TCP || IPProto == UDP. - Src netaddr.IPPort + Src netip.AddrPort // DstIP4 is the destination address. Family matches IPVersion. - Dst netaddr.IPPort + Dst netip.AddrPort // TCPFlags is the packet's TCP flag bits. Valid iff IPProto == TCP. TCPFlags TCPFlag } diff --git a/net/packet/packet_test.go b/net/packet/packet_test.go index a7064713b..510808adf 100644 --- a/net/packet/packet_test.go +++ b/net/packet/packet_test.go @@ -10,7 +10,6 @@ "reflect" "testing" - "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/types/ipproto" ) @@ -27,7 +26,7 @@ Fragment = ipproto.Fragment ) -func mustIPPort(s string) netaddr.IPPort { +func mustIPPort(s string) netip.AddrPort { ipp, err := netip.ParseAddrPort(s) if err != nil { panic(err) diff --git a/net/packet/tsmp.go b/net/packet/tsmp.go index 7f116c618..76642b97b 100644 --- a/net/packet/tsmp.go +++ b/net/packet/tsmp.go @@ -14,9 +14,9 @@ "encoding/binary" "errors" "fmt" + "net/netip" "tailscale.com/net/flowtrack" - "tailscale.com/net/netaddr" "tailscale.com/types/ipproto" ) @@ -36,10 +36,10 @@ // In the future it might also accept 16 byte IP flow src/dst IPs // after the header, if they're different than the IP-level ones. type TailscaleRejectedHeader struct { - IPSrc netaddr.IP // IPv4 or IPv6 header's src IP - IPDst netaddr.IP // IPv4 or IPv6 header's dst IP - Src netaddr.IPPort // rejected flow's src - Dst netaddr.IPPort // rejected flow's dst + IPSrc netip.Addr // IPv4 or IPv6 header's src IP + IPDst netip.Addr // IPv4 or IPv6 header's dst IP + Src netip.AddrPort // rejected flow's src + Dst netip.AddrPort // rejected flow's dst Proto ipproto.Proto // proto that was rejected (TCP or UDP) Reason TailscaleRejectReason // why the connection was rejected @@ -192,8 +192,8 @@ func (pp *Parsed) AsTailscaleRejectedHeader() (h TailscaleRejectedHeader, ok boo Reason: TailscaleRejectReason(p[2]), 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])), + Src: netip.AddrPortFrom(pp.Dst.Addr(), binary.BigEndian.Uint16(p[3:5])), + Dst: netip.AddrPortFrom(pp.Src.Addr(), binary.BigEndian.Uint16(p[5:7])), } if len(p) > 7 { flags := p[7] diff --git a/net/portmapper/disabled_stubs.go b/net/portmapper/disabled_stubs.go index 67e250a3b..f738e6e28 100644 --- a/net/portmapper/disabled_stubs.go +++ b/net/portmapper/disabled_stubs.go @@ -9,8 +9,7 @@ import ( "context" - - "tailscale.com/net/netaddr" + "net/netip" ) type upnpClient any @@ -23,9 +22,9 @@ func parseUPnPDiscoResponse([]byte) (uPnPDiscoResponse, error) { func (c *Client) getUPnPPortMapping( ctx context.Context, - gw netaddr.IP, - internal netaddr.IPPort, + gw netip.Addr, + internal netip.AddrPort, prevPort uint16, -) (external netaddr.IPPort, ok bool) { - return netaddr.IPPort{}, false +) (external netip.AddrPort, ok bool) { + return netip.AddrPort{}, false } diff --git a/net/portmapper/igd_test.go b/net/portmapper/igd_test.go index f7516eb28..717dd9946 100644 --- a/net/portmapper/igd_test.go +++ b/net/portmapper/igd_test.go @@ -10,6 +10,7 @@ "net" "net/http" "net/http/httptest" + "net/netip" "sync" "testing" @@ -101,7 +102,7 @@ func (d *TestIGD) TestUPnPPort() uint16 { return uint16(d.upnpConn.LocalAddr().(*net.UDPAddr).Port) } -func testIPAndGateway() (gw, ip netaddr.IP, ok bool) { +func testIPAndGateway() (gw, ip netip.Addr, ok bool) { return netaddr.IPv4(127, 0, 0, 1), netaddr.IPv4(1, 2, 3, 4), true } @@ -187,7 +188,7 @@ func (d *TestIGD) servePxP() { } } -func (d *TestIGD) handlePMPQuery(pkt []byte, src netaddr.IPPort) { +func (d *TestIGD) handlePMPQuery(pkt []byte, src netip.AddrPort) { d.inc(&d.counters.numPMPRecv) if len(pkt) < 2 { return @@ -205,7 +206,7 @@ func (d *TestIGD) handlePMPQuery(pkt []byte, src netaddr.IPPort) { // TODO } -func (d *TestIGD) handlePCPQuery(pkt []byte, src netaddr.IPPort) { +func (d *TestIGD) handlePCPQuery(pkt []byte, src netip.AddrPort) { d.inc(&d.counters.numPCPRecv) if len(pkt) < 24 { return diff --git a/net/portmapper/pcp.go b/net/portmapper/pcp.go index db5848c36..9cfe7c8a7 100644 --- a/net/portmapper/pcp.go +++ b/net/portmapper/pcp.go @@ -9,6 +9,7 @@ "crypto/rand" "encoding/binary" "fmt" + "net/netip" "time" "tailscale.com/net/netaddr" @@ -49,9 +50,9 @@ type pcpMapping struct { c *Client - gw netaddr.IPPort - internal netaddr.IPPort - external netaddr.IPPort + gw netip.AddrPort + internal netip.AddrPort + external netip.AddrPort renewAfter time.Time goodUntil time.Time @@ -62,7 +63,7 @@ type pcpMapping struct { func (p *pcpMapping) GoodUntil() time.Time { return p.goodUntil } func (p *pcpMapping) RenewAfter() time.Time { return p.renewAfter } -func (p *pcpMapping) External() netaddr.IPPort { return p.external } +func (p *pcpMapping) External() netip.AddrPort { return p.external } func (p *pcpMapping) Release(ctx context.Context) { uc, err := p.c.listenPacket(ctx, "udp4", ":0") if err != nil { @@ -78,10 +79,10 @@ func (p *pcpMapping) Release(ctx context.Context) { // If prevPort is not known, it should be set to 0. // If prevExternalIP is not known, it should be set to 0.0.0.0. func buildPCPRequestMappingPacket( - myIP netaddr.IP, + myIP netip.Addr, localPort, prevPort uint16, lifetimeSec uint32, - prevExternalIP netaddr.IP, + prevExternalIP netip.Addr, ) (pkt []byte) { // 24 byte common PCP header + 36 bytes of MAP-specific fields pkt = make([]byte, 24+36) @@ -127,7 +128,7 @@ func parsePCPMapResponse(resp []byte) (*pcpMapping, error) { copy(externalIPBytes[:], resp[44:]) externalIP := netaddr.IPFrom16(externalIPBytes) - external := netaddr.IPPortFrom(externalIP, externalPort) + external := netip.AddrPortFrom(externalIP, externalPort) lifetime := time.Second * time.Duration(res.Lifetime) now := time.Now() @@ -141,7 +142,7 @@ func parsePCPMapResponse(resp []byte) (*pcpMapping, error) { } // pcpAnnounceRequest generates a PCP packet with an ANNOUNCE opcode. -func pcpAnnounceRequest(myIP netaddr.IP) []byte { +func pcpAnnounceRequest(myIP netip.Addr) []byte { // See https://tools.ietf.org/html/rfc6887#section-7.1 pkt := make([]byte, 24) pkt[0] = pcpVersion diff --git a/net/portmapper/portmapper.go b/net/portmapper/portmapper.go index e59a3ab4a..3b5efd1d4 100644 --- a/net/portmapper/portmapper.go +++ b/net/portmapper/portmapper.go @@ -57,7 +57,7 @@ // Client is a port mapping client. type Client struct { logf logger.Logf - ipAndGateway func() (gw, ip netaddr.IP, ok bool) + ipAndGateway func() (gw, ip netip.Addr, ok bool) onChange func() // or nil testPxPPort uint16 // if non-zero, pxpPort to use for tests testUPnPPort uint16 // if non-zero, uPnPPort to use for tests @@ -69,13 +69,13 @@ type Client struct { // off a createMapping goroutine). runningCreate bool - lastMyIP netaddr.IP - lastGW netaddr.IP + lastMyIP netip.Addr + lastGW netip.Addr closed bool lastProbe time.Time - pmpPubIP netaddr.IP // non-zero if known + pmpPubIP netip.Addr // non-zero if known pmpPubIPTime time.Time // time pmpPubIP last verified pmpLastEpoch uint32 @@ -105,7 +105,7 @@ type mapping interface { // renewAfter returns the earliest time that the mapping should be renewed. RenewAfter() time.Time // externalIPPort indicates what port the mapping can be reached from on the outside. - External() netaddr.IPPort + External() netip.AddrPort } // HaveMapping reports whether we have a current valid mapping. @@ -120,9 +120,9 @@ func (c *Client) HaveMapping() bool { // All fields are immutable once created. type pmpMapping struct { c *Client - gw netaddr.IPPort - external netaddr.IPPort - internal netaddr.IPPort + gw netip.AddrPort + external netip.AddrPort + internal netip.AddrPort renewAfter time.Time // the time at which we want to renew the mapping goodUntil time.Time // the mapping's total lifetime epoch uint32 @@ -135,7 +135,7 @@ func (m *pmpMapping) externalValid() bool { func (p *pmpMapping) GoodUntil() time.Time { return p.goodUntil } func (p *pmpMapping) RenewAfter() time.Time { return p.renewAfter } -func (p *pmpMapping) External() netaddr.IPPort { return p.external } +func (p *pmpMapping) External() netip.AddrPort { return p.external } // Release does a best effort fire-and-forget release of the PMP mapping m. func (m *pmpMapping) Release(ctx context.Context) { @@ -164,7 +164,7 @@ func NewClient(logf logger.Logf, onChange func()) *Client { // SetGatewayLookupFunc set the func that returns the machine's default gateway IP, and // the primary IP address for that gateway. It must be called before the client is used. // If not called, interfaces.LikelyHomeRouterIP is used. -func (c *Client) SetGatewayLookupFunc(f func() (gw, myIP netaddr.IP, ok bool)) { +func (c *Client) SetGatewayLookupFunc(f func() (gw, myIP netip.Addr, ok bool)) { c.ipAndGateway = f } @@ -203,11 +203,11 @@ func (c *Client) SetLocalPort(localPort uint16) { c.invalidateMappingsLocked(true) } -func (c *Client) gatewayAndSelfIP() (gw, myIP netaddr.IP, ok bool) { +func (c *Client) gatewayAndSelfIP() (gw, myIP netip.Addr, ok bool) { gw, myIP, ok = c.ipAndGateway() if !ok { - gw = netaddr.IP{} - myIP = netaddr.IP{} + gw = netip.Addr{} + myIP = netip.Addr{} } c.mu.Lock() defer c.mu.Unlock() @@ -273,7 +273,7 @@ func (c *Client) invalidateMappingsLocked(releaseOld bool) { } c.mapping = nil } - c.pmpPubIP = netaddr.IP{} + c.pmpPubIP = netip.Addr{} c.pmpPubIPTime = time.Time{} c.pcpSawTime = time.Time{} c.uPnPSawTime = time.Time{} @@ -350,7 +350,7 @@ func IsNoMappingError(err error) bool { // If there's not one, it starts up a background goroutine to create one. // If the background goroutine ends up creating one, the onChange hook registered with the // NewClient constructor (if any) will fire. -func (c *Client) GetCachedMappingOrStartCreatingOne() (external netaddr.IPPort, ok bool) { +func (c *Client) GetCachedMappingOrStartCreatingOne() (external netip.AddrPort, ok bool) { c.mu.Lock() defer c.mu.Unlock() @@ -366,7 +366,7 @@ func (c *Client) GetCachedMappingOrStartCreatingOne() (external netaddr.IPPort, } c.maybeStartMappingLocked() - return netaddr.IPPort{}, false + return netip.AddrPort{}, false } // maybeStartMappingLocked starts a createMapping goroutine up, if one isn't already running. @@ -404,21 +404,21 @@ func (c *Client) createMapping() { // // If no mapping is available, the error will be of type // NoMappingError; see IsNoMappingError. -func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPort, err error) { +func (c *Client) createOrGetMapping(ctx context.Context) (external netip.AddrPort, err error) { if DisableUPnP && DisablePCP && DisablePMP { - return netaddr.IPPort{}, NoMappingError{ErrNoPortMappingServices} + return netip.AddrPort{}, NoMappingError{ErrNoPortMappingServices} } gw, myIP, ok := c.gatewayAndSelfIP() if !ok { - return netaddr.IPPort{}, NoMappingError{ErrGatewayRange} + return netip.AddrPort{}, NoMappingError{ErrGatewayRange} } if gw.Is6() { - return netaddr.IPPort{}, NoMappingError{ErrGatewayIPv6} + return netip.AddrPort{}, NoMappingError{ErrGatewayIPv6} } c.mu.Lock() localPort := c.localPort - internalAddr := netaddr.IPPortFrom(myIP, localPort) + internalAddr := netip.AddrPortFrom(myIP, localPort) // prevPort is the port we had most previously, if any. We try // to ask for the same port. 0 means to give us any port. @@ -440,7 +440,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor if external, ok := c.getUPnPPortMapping(ctx, gw, internalAddr, prevPort); ok { return external, nil } - return netaddr.IPPort{}, NoMappingError{ErrNoPortMappingServices} + return netip.AddrPort{}, NoMappingError{ErrNoPortMappingServices} } // If we just did a Probe (e.g. via netchecker) but didn't @@ -457,7 +457,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor // construct it upon receiving that packet. m := &pmpMapping{ c: c, - gw: netaddr.IPPortFrom(gw, c.pxpPort()), + gw: netip.AddrPortFrom(gw, c.pxpPort()), internal: internalAddr, } if haveRecentPMP { @@ -469,20 +469,20 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor if external, ok := c.getUPnPPortMapping(ctx, gw, internalAddr, prevPort); ok { return external, nil } - return netaddr.IPPort{}, NoMappingError{ErrNoPortMappingServices} + return netip.AddrPort{}, NoMappingError{ErrNoPortMappingServices} } c.mu.Unlock() uc, err := c.listenPacket(ctx, "udp4", ":0") if err != nil { - return netaddr.IPPort{}, err + return netip.AddrPort{}, err } defer uc.Close() uc.SetReadDeadline(time.Now().Add(portMapServiceTimeout)) defer closeCloserOnContextDone(ctx, uc)() - pxpAddr := netaddr.IPPortFrom(gw, c.pxpPort()) + pxpAddr := netip.AddrPortFrom(gw, c.pxpPort()) preferPCP := !DisablePCP && (DisablePMP || (!haveRecentPMP && haveRecentPCP)) @@ -495,7 +495,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor if neterror.TreatAsLostUDP(err) { err = NoMappingError{ErrNoPortMappingServices} } - return netaddr.IPPort{}, err + return netip.AddrPort{}, err } } else { // Ask for our external address if needed. @@ -504,7 +504,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor if neterror.TreatAsLostUDP(err) { err = NoMappingError{ErrNoPortMappingServices} } - return netaddr.IPPort{}, err + return netip.AddrPort{}, err } } @@ -513,7 +513,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor if neterror.TreatAsLostUDP(err) { err = NoMappingError{ErrNoPortMappingServices} } - return netaddr.IPPort{}, err + return netip.AddrPort{}, err } } @@ -522,13 +522,13 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor n, srci, err := uc.ReadFrom(res) if err != nil { if ctx.Err() == context.Canceled { - return netaddr.IPPort{}, err + return netip.AddrPort{}, err } // fallback to UPnP portmapping if mapping, ok := c.getUPnPPortMapping(ctx, gw, internalAddr, prevPort); ok { return mapping, nil } - return netaddr.IPPort{}, NoMappingError{ErrNoPortMappingServices} + return netip.AddrPort{}, NoMappingError{ErrNoPortMappingServices} } srcu := srci.(*net.UDPAddr) src, ok := netaddr.FromStdAddr(srcu.IP, srcu.Port, srcu.Zone) @@ -545,7 +545,7 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor continue } if pres.ResultCode != 0 { - return netaddr.IPPort{}, NoMappingError{fmt.Errorf("PMP response Op=0x%x,Res=0x%x", pres.OpCode, pres.ResultCode)} + return netip.AddrPort{}, NoMappingError{fmt.Errorf("PMP response Op=0x%x,Res=0x%x", pres.OpCode, pres.ResultCode)} } if pres.OpCode == pmpOpReply|pmpOpMapPublicAddr { m.external = netip.AddrPortFrom(pres.PublicAddr, m.external.Port()) @@ -563,18 +563,18 @@ func (c *Client) createOrGetMapping(ctx context.Context) (external netaddr.IPPor if err != nil { c.logf("failed to get PCP mapping: %v", err) // PCP should only have a single packet response - return netaddr.IPPort{}, NoMappingError{ErrNoPortMappingServices} + return netip.AddrPort{}, NoMappingError{ErrNoPortMappingServices} } pcpMapping.c = c pcpMapping.internal = m.internal - pcpMapping.gw = netaddr.IPPortFrom(gw, c.pxpPort()) + pcpMapping.gw = netip.AddrPortFrom(gw, c.pxpPort()) c.mu.Lock() defer c.mu.Unlock() c.mapping = pcpMapping return pcpMapping.external, nil default: c.logf("unknown PMP/PCP version number: %d %v", version, res[:n]) - return netaddr.IPPort{}, NoMappingError{ErrNoPortMappingServices} + return netip.AddrPort{}, NoMappingError{ErrNoPortMappingServices} } } @@ -632,7 +632,7 @@ type pmpResponse struct { ExternalPort uint16 // For public addr ops: - PublicAddr netaddr.IP + PublicAddr netip.Addr } func parsePMPResponse(pkt []byte) (res pmpResponse, ok bool) { @@ -701,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()) - upnpAddr := netaddr.IPPortFrom(gw, c.upnpPort()) - upnpMulticastAddr := netaddr.IPPortFrom(netaddr.IPv4(239, 255, 255, 250), c.upnpPort()) + pxpAddr := netip.AddrPortFrom(gw, c.pxpPort()) + upnpAddr := netip.AddrPortFrom(gw, c.upnpPort()) + upnpMulticastAddr := netip.AddrPortFrom(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 diff --git a/net/portmapper/upnp.go b/net/portmapper/upnp.go index 63c368abd..65f2c612f 100644 --- a/net/portmapper/upnp.go +++ b/net/portmapper/upnp.go @@ -24,7 +24,6 @@ "github.com/tailscale/goupnp" "github.com/tailscale/goupnp/dcps/internetgateway2" "tailscale.com/control/controlknobs" - "tailscale.com/net/netaddr" "tailscale.com/net/netns" "tailscale.com/types/logger" ) @@ -36,9 +35,9 @@ // upnpMapping is a port mapping over the upnp protocol. After being created it is immutable, // but the client field may be shared across mapping instances. type upnpMapping struct { - gw netaddr.IP - external netaddr.IPPort - internal netaddr.IPPort + gw netip.Addr + external netip.AddrPort + internal netip.AddrPort goodUntil time.Time renewAfter time.Time @@ -48,7 +47,7 @@ type upnpMapping struct { func (u *upnpMapping) GoodUntil() time.Time { return u.goodUntil } func (u *upnpMapping) RenewAfter() time.Time { return u.renewAfter } -func (u *upnpMapping) External() netaddr.IPPort { return u.external } +func (u *upnpMapping) External() netip.AddrPort { return u.external } func (u *upnpMapping) Release(ctx context.Context) { u.client.DeletePortMapping(ctx, "", u.external.Port(), "udp") } @@ -154,7 +153,7 @@ func addAnyPortMapping( // // The provided ctx is not retained in the returned upnpClient, but // its associated HTTP client is (if set via goupnp.WithHTTPClient). -func getUPnPClient(ctx context.Context, logf logger.Logf, gw netaddr.IP, meta uPnPDiscoResponse) (client upnpClient, err error) { +func getUPnPClient(ctx context.Context, logf logger.Logf, gw netip.Addr, meta uPnPDiscoResponse) (client upnpClient, err error) { if controlknobs.DisableUPnP() || DisableUPnP { return nil, nil } @@ -233,12 +232,12 @@ func (c *Client) upnpHTTPClientLocked() *http.Client { // port and an error. func (c *Client) getUPnPPortMapping( ctx context.Context, - gw netaddr.IP, - internal netaddr.IPPort, + gw netip.Addr, + internal netip.AddrPort, prevPort uint16, -) (external netaddr.IPPort, ok bool) { +) (external netip.AddrPort, ok bool) { if controlknobs.DisableUPnP() || DisableUPnP { - return netaddr.IPPort{}, false + return netip.AddrPort{}, false } now := time.Now() upnp := &upnpMapping{ @@ -262,11 +261,11 @@ func (c *Client) getUPnPPortMapping( c.logf("getUPnPClient: %T, %v", client, err) } if err != nil { - return netaddr.IPPort{}, false + return netip.AddrPort{}, false } } if client == nil { - return netaddr.IPPort{}, false + return netip.AddrPort{}, false } var newPort uint16 @@ -282,7 +281,7 @@ func (c *Client) getUPnPPortMapping( c.logf("addAnyPortMapping: %v, %v", newPort, err) } if err != nil { - return netaddr.IPPort{}, false + return netip.AddrPort{}, false } // TODO cache this ip somewhere? extIP, err := client.GetExternalIPAddress(ctx) @@ -291,14 +290,14 @@ func (c *Client) getUPnPPortMapping( } if err != nil { // TODO this doesn't seem right - return netaddr.IPPort{}, false + return netip.AddrPort{}, false } externalIP, err := netip.ParseAddr(extIP) if err != nil { - return netaddr.IPPort{}, false + return netip.AddrPort{}, false } - upnp.external = netaddr.IPPortFrom(externalIP, newPort) + upnp.external = netip.AddrPortFrom(externalIP, newPort) d := time.Duration(pmpMapLifetimeSec) * time.Second upnp.goodUntil = now.Add(d) upnp.renewAfter = now.Add(d / 2) diff --git a/net/tsaddr/tsaddr.go b/net/tsaddr/tsaddr.go index 5d4ac44b1..e728e725e 100644 --- a/net/tsaddr/tsaddr.go +++ b/net/tsaddr/tsaddr.go @@ -17,7 +17,7 @@ // ChromeOSVMRange returns the subset of the CGNAT IPv4 range used by // ChromeOS to interconnect the host OS to containers and VMs. We // avoid allocating Tailscale IPs from it, to avoid conflicts. -func ChromeOSVMRange() netaddr.IPPrefix { +func ChromeOSVMRange() netip.Prefix { chromeOSRange.Do(func() { mustPrefix(&chromeOSRange.v, "100.115.92.0/23") }) return chromeOSRange.v } @@ -28,7 +28,7 @@ func ChromeOSVMRange() netaddr.IPPrefix { // is the superset range that Tailscale assigns out of. // See https://tailscale.com/kb/1015/100.x-addresses. // Note that Tailscale does not assign out of the ChromeOSVMRange. -func CGNATRange() netaddr.IPPrefix { +func CGNATRange() netip.Prefix { cgnatRange.Do(func() { mustPrefix(&cgnatRange.v, "100.64.0.0/10") }) return cgnatRange.v } @@ -47,7 +47,7 @@ func CGNATRange() netaddr.IPPrefix { // provided by Tailscale itself such as the MagicDNS proxy. // // For IPv6, use TailscaleServiceIPv6. -func TailscaleServiceIP() netaddr.IP { +func TailscaleServiceIP() netip.Addr { return netaddr.IPv4(100, 100, 100, 100) // "100.100.100.100" for those grepping } @@ -55,14 +55,14 @@ func TailscaleServiceIP() netaddr.IP { // provided by Tailscale itself such as the MagicDNS proxy. // // For IPv4, use TailscaleServiceIP. -func TailscaleServiceIPv6() netaddr.IP { +func TailscaleServiceIPv6() netip.Addr { serviceIPv6.Do(func() { mustPrefix(&serviceIPv6.v, "fd7a:115c:a1e0::53/128") }) return serviceIPv6.v.Addr() } // IsTailscaleIP reports whether ip is an IP address in a range that // Tailscale assigns from. -func IsTailscaleIP(ip netaddr.IP) bool { +func IsTailscaleIP(ip netip.Addr) bool { if ip.Is4() { return CGNATRange().Contains(ip) && !ChromeOSVMRange().Contains(ip) } @@ -71,14 +71,14 @@ func IsTailscaleIP(ip netaddr.IP) bool { // TailscaleULARange returns the IPv6 Unique Local Address range that // is the superset range that Tailscale assigns out of. -func TailscaleULARange() netaddr.IPPrefix { +func TailscaleULARange() netip.Prefix { tsUlaRange.Do(func() { mustPrefix(&tsUlaRange.v, "fd7a:115c:a1e0::/48") }) return tsUlaRange.v } // TailscaleViaRange returns the IPv6 Unique Local Address subset range // TailscaleULARange that's used for IPv4 tunneling via IPv6. -func TailscaleViaRange() netaddr.IPPrefix { +func TailscaleViaRange() netip.Prefix { // Mnemonic: "b1a" sounds like "via". tsViaRange.Do(func() { mustPrefix(&tsViaRange.v, "fd7a:115c:a1e0:b1a::/64") }) return tsViaRange.v @@ -86,7 +86,7 @@ func TailscaleViaRange() netaddr.IPPrefix { // Tailscale4To6Range returns the subset of TailscaleULARange used for // auto-translated Tailscale ipv4 addresses. -func Tailscale4To6Range() netaddr.IPPrefix { +func Tailscale4To6Range() netip.Prefix { // This IP range has no significance, beyond being a subset of // TailscaleULARange. The bits from /48 to /104 were picked at // random. @@ -96,7 +96,7 @@ func Tailscale4To6Range() netaddr.IPPrefix { // TailscaleEphemeral6Range returns the subset of TailscaleULARange // used for ephemeral IPv6-only Tailscale nodes. -func TailscaleEphemeral6Range() netaddr.IPPrefix { +func TailscaleEphemeral6Range() netip.Prefix { // This IP range has no significance, beyond being a subset of // TailscaleULARange. The bits from /48 to /64 were picked at // random, with the only criterion being to not be the conflict @@ -112,16 +112,16 @@ func TailscaleEphemeral6Range() netaddr.IPPrefix { // // Currently used to work around a Windows limitation when programming // IPv6 routes in corner cases. -func Tailscale4To6Placeholder() netaddr.IP { +func Tailscale4To6Placeholder() netip.Addr { return Tailscale4To6Range().Addr() } // Tailscale4To6 returns a Tailscale IPv6 address that maps 1:1 to the // given Tailscale IPv4 address. Returns a zero IP if ipv4 isn't a // Tailscale IPv4 address. -func Tailscale4To6(ipv4 netaddr.IP) netaddr.IP { +func Tailscale4To6(ipv4 netip.Addr) netip.Addr { if !ipv4.Is4() || !IsTailscaleIP(ipv4) { - return netaddr.IP{} + return netip.Addr{} } ret := Tailscale4To6Range().Addr().As16() v4 := ipv4.As4() @@ -133,15 +133,15 @@ func Tailscale4To6(ipv4 netaddr.IP) netaddr.IP { // tailscale IPv6 address within the 4To6 range. The IPv4 address // and true are returned if the given address was in the correct range, // false if not. -func Tailscale6to4(ipv6 netaddr.IP) (netaddr.IP, bool) { +func Tailscale6to4(ipv6 netip.Addr) (netip.Addr, bool) { if !ipv6.Is6() || !Tailscale4To6Range().Contains(ipv6) { - return netaddr.IP{}, false + return netip.Addr{}, false } v6 := ipv6.As16() return netaddr.IPv4(100, v6[13], v6[14], v6[15]), true } -func mustPrefix(v *netaddr.IPPrefix, prefix string) { +func mustPrefix(v *netip.Prefix, prefix string) { var err error *v, err = netip.ParsePrefix(prefix) if err != nil { @@ -151,7 +151,7 @@ func mustPrefix(v *netaddr.IPPrefix, prefix string) { type oncePrefix struct { sync.Once - v netaddr.IPPrefix + v netip.Prefix } // NewContainsIPFunc returns a func that reports whether ip is in addrs. @@ -161,11 +161,11 @@ type oncePrefix struct { // one IPv6 address). // // Otherwise the implementation is somewhat slow. -func NewContainsIPFunc(addrs []netaddr.IPPrefix) func(ip netaddr.IP) bool { +func NewContainsIPFunc(addrs []netip.Prefix) func(ip netip.Addr) bool { // Specialize the three common cases: no address, just IPv4 // (or just IPv6), and both IPv4 and IPv6. if len(addrs) == 0 { - return func(netaddr.IP) bool { return false } + return func(netip.Addr) bool { return false } } // If any addr is more than a single IP, then just do the slow // linear thing until @@ -174,8 +174,8 @@ func NewContainsIPFunc(addrs []netaddr.IPPrefix) func(ip netaddr.IP) bool { if a.IsSingleIP() { continue } - acopy := append([]netaddr.IPPrefix(nil), addrs...) - return func(ip netaddr.IP) bool { + acopy := append([]netip.Prefix(nil), addrs...) + return func(ip netip.Addr) bool { for _, a := range acopy { if a.Contains(ip) { return true @@ -187,23 +187,23 @@ 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.Addr() } + return func(ip netip.Addr) bool { return ip == a.Addr() } } if len(addrs) == 2 { a, b := addrs[0], addrs[1] - return func(ip netaddr.IP) bool { return ip == a.Addr() || ip == b.Addr() } + return func(ip netip.Addr) bool { return ip == a.Addr() || ip == b.Addr() } } // General case: - m := map[netaddr.IP]bool{} + m := map[netip.Addr]bool{} for _, a := range addrs { m[a.Addr()] = true } - return func(ip netaddr.IP) bool { return m[ip] } + return func(ip netip.Addr) bool { return m[ip] } } // PrefixesContainsFunc reports whether f is true for any IPPrefix in // ipp. -func PrefixesContainsFunc(ipp []netaddr.IPPrefix, f func(netaddr.IPPrefix) bool) bool { +func PrefixesContainsFunc(ipp []netip.Prefix, f func(netip.Prefix) bool) bool { for _, v := range ipp { if f(v) { return true @@ -213,7 +213,7 @@ func PrefixesContainsFunc(ipp []netaddr.IPPrefix, f func(netaddr.IPPrefix) bool) } // PrefixesContainsIP reports whether any prefix in ipp contains ip. -func PrefixesContainsIP(ipp []netaddr.IPPrefix, ip netaddr.IP) bool { +func PrefixesContainsIP(ipp []netip.Prefix, ip netip.Addr) bool { for _, r := range ipp { if r.Contains(ip) { return true @@ -223,7 +223,7 @@ func PrefixesContainsIP(ipp []netaddr.IPPrefix, ip netaddr.IP) bool { } // IPsContainsFunc reports whether f is true for any IP in ips. -func IPsContainsFunc(ips []netaddr.IP, f func(netaddr.IP) bool) bool { +func IPsContainsFunc(ips []netip.Addr, f func(netip.Addr) bool) bool { for _, v := range ips { if f(v) { return true @@ -233,14 +233,14 @@ 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.Addr().Is4() } +func PrefixIs4(p netip.Prefix) bool { return p.Addr().Is4() } // PrefixIs6 reports whether p is an IPv6 prefix. -func PrefixIs6(p netaddr.IPPrefix) bool { return p.Addr().Is6() } +func PrefixIs6(p netip.Prefix) bool { return p.Addr().Is6() } // ContainsExitRoutes reports whether rr contains both the IPv4 and // IPv6 /0 route. -func ContainsExitRoutes(rr []netaddr.IPPrefix) bool { +func ContainsExitRoutes(rr []netip.Prefix) bool { var v4, v6 bool for _, r := range rr { if r == allIPv4 { @@ -258,18 +258,18 @@ func ContainsExitRoutes(rr []netaddr.IPPrefix) bool { ) // AllIPv4 returns 0.0.0.0/0. -func AllIPv4() netaddr.IPPrefix { return allIPv4 } +func AllIPv4() netip.Prefix { return allIPv4 } // AllIPv6 returns ::/0. -func AllIPv6() netaddr.IPPrefix { return allIPv6 } +func AllIPv6() netip.Prefix { return allIPv6 } // ExitRoutes returns a slice containing AllIPv4 and AllIPv6. -func ExitRoutes() []netaddr.IPPrefix { return []netaddr.IPPrefix{allIPv4, allIPv6} } +func ExitRoutes() []netip.Prefix { return []netip.Prefix{allIPv4, allIPv6} } // FilterPrefixes returns a new slice, not aliasing in, containing elements of // in that match f. -func FilterPrefixesCopy(in []netaddr.IPPrefix, f func(netaddr.IPPrefix) bool) []netaddr.IPPrefix { - var out []netaddr.IPPrefix +func FilterPrefixesCopy(in []netip.Prefix, f func(netip.Prefix) bool) []netip.Prefix { + var out []netip.Prefix for _, v := range in { if f(v) { out = append(out, v) @@ -280,7 +280,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 { +func IsViaPrefix(p netip.Prefix) bool { return TailscaleViaRange().Contains(p.Addr()) } @@ -288,16 +288,16 @@ func IsViaPrefix(p netaddr.IPPrefix) bool { // "via" IPv4-in-IPv6 address. // // If ip is not a via address, it returns ip unchanged. -func UnmapVia(ip netaddr.IP) netaddr.IP { +func UnmapVia(ip netip.Addr) netip.Addr { if TailscaleViaRange().Contains(ip) { a := ip.As16() - return netaddr.IPFrom4(*(*[4]byte)(a[12:16])) + return netip.AddrFrom4(*(*[4]byte)(a[12:16])) } return 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) { +func MapVia(siteID uint32, v4 netip.Prefix) (via netip.Prefix, err error) { if !v4.Addr().Is4() { return via, errors.New("want IPv4 CIDR with a site ID") } diff --git a/net/tsaddr/tsaddr_test.go b/net/tsaddr/tsaddr_test.go index cf306dd25..812475ac1 100644 --- a/net/tsaddr/tsaddr_test.go +++ b/net/tsaddr/tsaddr_test.go @@ -13,7 +13,7 @@ func TestInCrostiniRange(t *testing.T) { tests := []struct { - ip netaddr.IP + ip netip.Addr want bool }{ {netaddr.IPv4(192, 168, 0, 1), false}, @@ -53,25 +53,25 @@ func TestCGNATRange(t *testing.T) { } func TestNewContainsIPFunc(t *testing.T) { - f := NewContainsIPFunc([]netaddr.IPPrefix{netip.MustParsePrefix("10.0.0.0/8")}) + f := NewContainsIPFunc([]netip.Prefix{netip.MustParsePrefix("10.0.0.0/8")}) if f(netip.MustParseAddr("8.8.8.8")) { t.Fatal("bad") } if !f(netip.MustParseAddr("10.1.2.3")) { t.Fatal("bad") } - f = NewContainsIPFunc([]netaddr.IPPrefix{netip.MustParsePrefix("10.1.2.3/32")}) + f = NewContainsIPFunc([]netip.Prefix{netip.MustParsePrefix("10.1.2.3/32")}) if !f(netip.MustParseAddr("10.1.2.3")) { t.Fatal("bad") } - f = NewContainsIPFunc([]netaddr.IPPrefix{ + f = NewContainsIPFunc([]netip.Prefix{ netip.MustParsePrefix("10.1.2.3/32"), netip.MustParsePrefix("::2/128"), }) if !f(netip.MustParseAddr("::2")) { t.Fatal("bad") } - f = NewContainsIPFunc([]netaddr.IPPrefix{ + f = NewContainsIPFunc([]netip.Prefix{ netip.MustParsePrefix("10.1.2.3/32"), netip.MustParsePrefix("10.1.2.4/32"), netip.MustParsePrefix("::2/128"), @@ -81,7 +81,7 @@ func TestNewContainsIPFunc(t *testing.T) { } } -var sinkIP netaddr.IP +var sinkIP netip.Addr func BenchmarkTailscaleServiceAddr(b *testing.B) { b.ReportAllocs() diff --git a/net/tsdial/dnsmap.go b/net/tsdial/dnsmap.go index f56025f80..f98cb6011 100644 --- a/net/tsdial/dnsmap.go +++ b/net/tsdial/dnsmap.go @@ -13,7 +13,6 @@ "strconv" "strings" - "tailscale.com/net/netaddr" "tailscale.com/types/netmap" "tailscale.com/util/dnsname" ) @@ -23,7 +22,7 @@ // // Example keys are "foo.domain.tld.beta.tailscale.net" and "foo", // both without trailing dots, and both always lowercase. -type dnsMap map[string]netaddr.IP +type dnsMap map[string]netip.Addr // canonMapKey canonicalizes its input s to be a dnsMap map key. func canonMapKey(s string) string { @@ -98,15 +97,15 @@ func splitHostPort(addr string) (host string, port uint16, err error) { // // The error is [exactly] errUnresolved if the addr is a name that isn't known // in the map. -func (m dnsMap) resolveMemory(ctx context.Context, network, addr string) (_ netaddr.IPPort, err error) { +func (m dnsMap) resolveMemory(ctx context.Context, network, addr string) (_ netip.AddrPort, err error) { host, port, err := splitHostPort(addr) if err != nil { // addr malformed or invalid port. - return netaddr.IPPort{}, err + return netip.AddrPort{}, err } if ip, err := netip.ParseAddr(host); err == nil { // addr was literal ip:port. - return netaddr.IPPortFrom(ip, port), nil + return netip.AddrPortFrom(ip, port), nil } // Host is not an IP, so assume it's a DNS name. @@ -114,8 +113,8 @@ 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.IsValid() { - return netaddr.IPPortFrom(ip, port), nil + return netip.AddrPortFrom(ip, port), nil } - return netaddr.IPPort{}, errUnresolved + return netip.AddrPort{}, errUnresolved } diff --git a/net/tsdial/dnsmap_test.go b/net/tsdial/dnsmap_test.go index 4991688f1..afa315cfe 100644 --- a/net/tsdial/dnsmap_test.go +++ b/net/tsdial/dnsmap_test.go @@ -9,7 +9,6 @@ "reflect" "testing" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/netmap" ) @@ -26,7 +25,7 @@ func TestDNSMapFromNetworkMap(t *testing.T) { name: "self", nm: &netmap.NetworkMap{ Name: "foo.tailnet", - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ pfx("100.102.103.104/32"), pfx("100::123/128"), }, @@ -40,21 +39,21 @@ func TestDNSMapFromNetworkMap(t *testing.T) { name: "self_and_peers", nm: &netmap.NetworkMap{ Name: "foo.tailnet", - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ pfx("100.102.103.104/32"), pfx("100::123/128"), }, Peers: []*tailcfg.Node{ { Name: "a.tailnet", - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ pfx("100.0.0.201/32"), pfx("100::201/128"), }, }, { Name: "b.tailnet", - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ pfx("100::202/128"), }, }, @@ -73,20 +72,20 @@ func TestDNSMapFromNetworkMap(t *testing.T) { name: "self_has_v6_only", nm: &netmap.NetworkMap{ Name: "foo.tailnet", - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ pfx("100::123/128"), }, Peers: []*tailcfg.Node{ { Name: "a.tailnet", - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ pfx("100.0.0.201/32"), pfx("100::201/128"), }, }, { Name: "b.tailnet", - Addresses: []netaddr.IPPrefix{ + Addresses: []netip.Prefix{ pfx("100::202/128"), }, }, diff --git a/net/tsdial/tsdial.go b/net/tsdial/tsdial.go index 7edbca75b..4f5211361 100644 --- a/net/tsdial/tsdial.go +++ b/net/tsdial/tsdial.go @@ -38,11 +38,11 @@ type Dialer struct { Logf logger.Logf // UseNetstackForIP if non-nil is whether NetstackDialTCP (if // it's non-nil) should be used to dial the provided IP. - UseNetstackForIP func(netaddr.IP) bool + UseNetstackForIP func(netip.Addr) bool // NetstackDialTCP dials the provided IPPort using netstack. // If nil, it's not used. - NetstackDialTCP func(context.Context, netaddr.IPPort) (net.Conn, error) + NetstackDialTCP func(context.Context, netip.AddrPort) (net.Conn, error) peerDialControlFuncAtomic atomic.Value // of func() func(network, address string, c syscall.RawConn) error @@ -208,7 +208,7 @@ func (d *Dialer) SetNetMap(nm *netmap.NetworkMap) { d.dns = m } -func (d *Dialer) userDialResolve(ctx context.Context, network, addr string) (netaddr.IPPort, error) { +func (d *Dialer) userDialResolve(ctx context.Context, network, addr string) (netip.AddrPort, error) { d.mu.Lock() dns := d.dns exitDNSDoH := d.exitDNSDoHBase @@ -227,7 +227,7 @@ func (d *Dialer) userDialResolve(ctx context.Context, network, addr string) (net host, port, err := splitHostPort(addr) if err != nil { // addr is malformed. - return netaddr.IPPort{}, err + return netip.AddrPort{}, err } var r net.Resolver @@ -245,13 +245,13 @@ func (d *Dialer) userDialResolve(ctx context.Context, network, addr string) (net ips, err := r.LookupIP(ctx, ipNetOfNetwork(network), host) if err != nil { - return netaddr.IPPort{}, err + return netip.AddrPort{}, err } if len(ips) == 0 { - return netaddr.IPPort{}, fmt.Errorf("DNS lookup returned no results for %q", host) + return netip.AddrPort{}, fmt.Errorf("DNS lookup returned no results for %q", host) } ip, _ := netaddr.FromStdIP(ips[0]) - return netaddr.IPPortFrom(ip, port), nil + return netip.AddrPortFrom(ip, port), nil } // ipNetOfNetwork returns "ip", "ip4", or "ip6" corresponding diff --git a/net/tstun/tap_linux.go b/net/tstun/tap_linux.go index 9ff8a9029..e6b699aec 100644 --- a/net/tstun/tap_linux.go +++ b/net/tstun/tap_linux.go @@ -7,6 +7,7 @@ import ( "fmt" "net" + "net/netip" "os" "os/exec" @@ -246,8 +247,8 @@ func (t *Wrapper) handleDHCPRequest(ethBuf []byte) bool { pkt := packLayer2UDP( offer.ToBytes(), ourMAC, ethSrcMAC, - netaddr.IPPortFrom(netaddr.IPv4(100, 100, 100, 100), 67), // src - netaddr.IPPortFrom(netaddr.IPv4(255, 255, 255, 255), 68), // dst + netip.AddrPortFrom(netaddr.IPv4(100, 100, 100, 100), 67), // src + netip.AddrPortFrom(netaddr.IPv4(255, 255, 255, 255), 68), // dst ) n, err := t.tdev.Write(pkt, 0) if tapDebug { @@ -273,8 +274,8 @@ func (t *Wrapper) handleDHCPRequest(ethBuf []byte) bool { pkt := packLayer2UDP( ack.ToBytes(), ourMAC, ethSrcMAC, - netaddr.IPPortFrom(netaddr.IPv4(100, 100, 100, 100), 67), // src - netaddr.IPPortFrom(netaddr.IPv4(255, 255, 255, 255), 68), // dst + netip.AddrPortFrom(netaddr.IPv4(100, 100, 100, 100), 67), // src + netip.AddrPortFrom(netaddr.IPv4(255, 255, 255, 255), 68), // dst ) n, err := t.tdev.Write(pkt, 0) if tapDebug { @@ -288,7 +289,7 @@ func (t *Wrapper) handleDHCPRequest(ethBuf []byte) bool { return consumePacket } -func packLayer2UDP(payload []byte, srcMAC, dstMAC net.HardwareAddr, src, dst netaddr.IPPort) []byte { +func packLayer2UDP(payload []byte, srcMAC, dstMAC net.HardwareAddr, src, dst netip.AddrPort) []byte { buf := make([]byte, header.EthernetMinimumSize+header.UDPMinimumSize+header.IPv4MinimumSize+len(payload)) payloadStart := len(buf) - len(payload) copy(buf[payloadStart:], payload) diff --git a/net/tstun/wrap.go b/net/tstun/wrap.go index f4b678614..909340416 100644 --- a/net/tstun/wrap.go +++ b/net/tstun/wrap.go @@ -10,6 +10,7 @@ "errors" "fmt" "io" + "net/netip" "os" "strings" "sync" @@ -21,7 +22,6 @@ "golang.zx2c4.com/wireguard/tun" "gvisor.dev/gvisor/pkg/tcpip/stack" "tailscale.com/disco" - "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/tstime/mono" @@ -82,7 +82,7 @@ type Wrapper struct { // you might need to add a pad32.Four field here. lastActivityAtomic mono.Time // time of last send or receive - destIPActivity atomic.Value // of map[netaddr.IP]func() + destIPActivity atomic.Value // of map[netip.Addr]func() destMACAtomic atomic.Value // of [6]byte discoKey atomic.Value // of key.DiscoPublic @@ -158,7 +158,7 @@ type Wrapper struct { // PeerAPIPort, if non-nil, returns the peerapi port that's // running for the given IP address. - PeerAPIPort func(netaddr.IP) (port uint16, ok bool) + PeerAPIPort func(netip.Addr) (port uint16, ok bool) // disableFilter disables all filtering when set. This should only be used in tests. disableFilter bool @@ -222,7 +222,7 @@ func wrap(logf logger.Logf, tdev tun.Device, isTAP bool) *Wrapper { // destination (the map keys). // // The map ownership passes to the Wrapper. It must be non-nil. -func (t *Wrapper) SetDestIPActivityFuncs(m map[netaddr.IP]func()) { +func (t *Wrapper) SetDestIPActivityFuncs(m map[netip.Addr]func()) { t.destIPActivity.Store(m) } @@ -429,8 +429,8 @@ func (t *Wrapper) sendOutbound(r tunReadResult) { } var ( - magicDNSIPPort = netaddr.IPPortFrom(tsaddr.TailscaleServiceIP(), 0) // 100.100.100.100:0 - magicDNSIPPortv6 = netaddr.IPPortFrom(tsaddr.TailscaleServiceIPv6(), 0) + magicDNSIPPort = netip.AddrPortFrom(tsaddr.TailscaleServiceIP(), 0) // 100.100.100.100:0 + magicDNSIPPortv6 = netip.AddrPortFrom(tsaddr.TailscaleServiceIPv6(), 0) ) func (t *Wrapper) filterOut(p *packet.Parsed) filter.Response { @@ -544,7 +544,7 @@ func (t *Wrapper) Read(buf []byte, offset int) (int, error) { defer parsedPacketPool.Put(p) p.Decode(buf[offset : offset+n]) - if m, ok := t.destIPActivity.Load().(map[netaddr.IP]func()); ok { + if m, ok := t.destIPActivity.Load().(map[netip.Addr]func()); ok { if fn := m[p.Dst.Addr()]; fn != nil { fn() } diff --git a/net/tstun/wrap_test.go b/net/tstun/wrap_test.go index 412d95424..ccb155e51 100644 --- a/net/tstun/wrap_test.go +++ b/net/tstun/wrap_test.go @@ -77,7 +77,7 @@ func tcp4syn(src, dst string, sport, dport uint16) []byte { return both } -func nets(nets ...string) (ret []netaddr.IPPrefix) { +func nets(nets ...string) (ret []netip.Prefix) { for _, s := range nets { if i := strings.IndexByte(s, '/'); i == -1 { ip, err := netip.ParseAddr(s) @@ -88,7 +88,7 @@ func nets(nets ...string) (ret []netaddr.IPPrefix) { if ip.Is6() { bits = 128 } - ret = append(ret, netaddr.IPPrefixFrom(ip, bits)) + ret = append(ret, netip.PrefixFrom(ip, int(bits))) } else { pfx, err := netip.ParsePrefix(s) if err != nil { @@ -428,7 +428,7 @@ func TestAtomic64Alignment(t *testing.T) { func TestPeerAPIBypass(t *testing.T) { wrapperWithPeerAPI := &Wrapper{ - PeerAPIPort: func(ip netaddr.IP) (port uint16, ok bool) { + PeerAPIPort: func(ip netip.Addr) (port uint16, ok bool) { if ip == netip.MustParseAddr("100.64.1.2") { return 60000, true } @@ -446,7 +446,7 @@ func TestPeerAPIBypass(t *testing.T) { { name: "reject_nil_filter", w: &Wrapper{ - PeerAPIPort: func(netaddr.IP) (port uint16, ok bool) { + PeerAPIPort: func(netip.Addr) (port uint16, ok bool) { return 60000, true }, }, diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index 0d2c46517..7d6ad72e6 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -405,7 +405,7 @@ func (c *conn) sshPolicy() (_ *tailcfg.SSHPolicy, ok bool) { return nil, false } -func toIPPort(a net.Addr) (ipp netaddr.IPPort) { +func toIPPort(a net.Addr) (ipp netip.AddrPort) { ta, ok := a.(*net.TCPAddr) if !ok { return @@ -414,7 +414,7 @@ func toIPPort(a net.Addr) (ipp netaddr.IPPort) { if !ok { return } - return netaddr.IPPortFrom(tanetaddr, uint16(ta.Port)) + return netip.AddrPortFrom(tanetaddr, uint16(ta.Port)) } // connInfo returns a populated sshConnInfo from the provided arguments, @@ -1103,10 +1103,10 @@ type sshConnInfo struct { sshUser string // src is the Tailscale IP and port that the connection came from. - src netaddr.IPPort + src netip.AddrPort // dst is the Tailscale IP and port that the connection came for. - dst netaddr.IPPort + dst netip.AddrPort // node is srcIP's node. node *tailcfg.Node diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index ad36c0c77..b37293325 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -10,11 +10,11 @@ "encoding/hex" "errors" "fmt" + "net/netip" "reflect" "strings" "time" - "tailscale.com/net/netaddr" "tailscale.com/types/dnstype" "tailscale.com/types/key" "tailscale.com/types/opt" @@ -170,10 +170,10 @@ type Node struct { KeyExpiry time.Time Machine key.MachinePublic DiscoKey key.DiscoPublic - Addresses []netaddr.IPPrefix // IP addresses of this Node directly - AllowedIPs []netaddr.IPPrefix // range of IP addresses to route to this node - Endpoints []string `json:",omitempty"` // IP+port (public via STUN, and local LANs) - DERP string `json:",omitempty"` // DERP-in-IP:port ("127.3.3.40:N") endpoint + Addresses []netip.Prefix // IP addresses of this Node directly + AllowedIPs []netip.Prefix // range of IP addresses to route to this node + Endpoints []string `json:",omitempty"` // IP+port (public via STUN, and local LANs) + DERP string `json:",omitempty"` // DERP-in-IP:port ("127.3.3.40:N") endpoint Hostinfo HostinfoView Created time.Time @@ -190,7 +190,7 @@ type Node struct { // is currently the primary subnet router for, as determined // by the control plane. It does not include the self address // values from Addresses that are in AllowedIPs. - PrimaryRoutes []netaddr.IPPrefix `json:",omitempty"` + PrimaryRoutes []netip.Prefix `json:",omitempty"` // LastSeen is when the node was last online. It is not // updated when Online is true. It is nil if the current @@ -454,24 +454,24 @@ type Service struct { // Because it contains pointers (slices), this type should not be used // as a value type. type Hostinfo struct { - IPNVersion string `json:",omitempty"` // version of this code - FrontendLogID string `json:",omitempty"` // logtail ID of frontend instance - BackendLogID string `json:",omitempty"` // logtail ID of backend instance - OS string `json:",omitempty"` // operating system the client runs on (a version.OS value) - OSVersion string `json:",omitempty"` // operating system version, with optional distro prefix ("Debian 10.4", "Windows 10 Pro 10.0.19041") - Desktop opt.Bool `json:",omitempty"` // if a desktop was detected on Linux - Package string `json:",omitempty"` // Tailscale package to disambiguate ("choco", "appstore", etc; "" for unknown) - DeviceModel string `json:",omitempty"` // mobile phone model ("Pixel 3a", "iPhone12,3") - Hostname string `json:",omitempty"` // name of the host the client runs on - ShieldsUp bool `json:",omitempty"` // indicates whether the host is blocking incoming connections - ShareeNode bool `json:",omitempty"` // indicates this node exists in netmap because it's owned by a shared-to user - GoArch string `json:",omitempty"` // the host's GOARCH value (of the running binary) - RoutableIPs []netaddr.IPPrefix `json:",omitempty"` // set of IP ranges this client can route - RequestTags []string `json:",omitempty"` // set of ACL tags this node wants to claim - Services []Service `json:",omitempty"` // services advertised by this machine - NetInfo *NetInfo `json:",omitempty"` - SSH_HostKeys []string `json:"sshHostKeys,omitempty"` // if advertised - Cloud string `json:",omitempty"` + IPNVersion string `json:",omitempty"` // version of this code + FrontendLogID string `json:",omitempty"` // logtail ID of frontend instance + BackendLogID string `json:",omitempty"` // logtail ID of backend instance + OS string `json:",omitempty"` // operating system the client runs on (a version.OS value) + OSVersion string `json:",omitempty"` // operating system version, with optional distro prefix ("Debian 10.4", "Windows 10 Pro 10.0.19041") + Desktop opt.Bool `json:",omitempty"` // if a desktop was detected on Linux + Package string `json:",omitempty"` // Tailscale package to disambiguate ("choco", "appstore", etc; "" for unknown) + DeviceModel string `json:",omitempty"` // mobile phone model ("Pixel 3a", "iPhone12,3") + Hostname string `json:",omitempty"` // name of the host the client runs on + ShieldsUp bool `json:",omitempty"` // indicates whether the host is blocking incoming connections + ShareeNode bool `json:",omitempty"` // indicates this node exists in netmap because it's owned by a shared-to user + GoArch string `json:",omitempty"` // the host's GOARCH value (of the running binary) + RoutableIPs []netip.Prefix `json:",omitempty"` // set of IP ranges this client can route + RequestTags []string `json:",omitempty"` // set of ACL tags this node wants to claim + Services []Service `json:",omitempty"` // services advertised by this machine + NetInfo *NetInfo `json:",omitempty"` + SSH_HostKeys []string `json:"sshHostKeys,omitempty"` // if advertised + Cloud string `json:",omitempty"` // NOTE: any new fields containing pointers in this type // require changes to Hostinfo.Equal. @@ -854,7 +854,7 @@ func (et EndpointType) String() string { // broken up into two parallel slices in MapRequest, for compatibility // reasons. But this type is used in the codebase. type Endpoint struct { - Addr netaddr.IPPort + Addr netip.AddrPort Type EndpointType } @@ -946,7 +946,7 @@ type NetPortRange struct { type CapGrant struct { // Dsts are the destination IP ranges that this capabilty // grant matches. - Dsts []netaddr.IPPrefix + Dsts []netip.Prefix // Caps are the capabilities the source IP matched by // FilterRule.SrcIPs are granted to the destination IP, @@ -1059,7 +1059,7 @@ type DNSConfig struct { // MapRequest.Version >=9 and <14. // Nameservers are the IP addresses of the nameservers to use. - Nameservers []netaddr.IP `json:",omitempty"` + Nameservers []netip.Addr `json:",omitempty"` // PerDomain is not set by the control server, and does nothing. PerDomain bool `json:",omitempty"` @@ -1149,7 +1149,7 @@ type PingRequest struct { // IP is the ping target. // It is used in TSMP pings, if IP is invalid or empty then do a HEAD request to the URL. - IP netaddr.IP + IP netip.Addr } // PingResponse provides result information for a TSMP or Disco PingRequest. @@ -1446,7 +1446,7 @@ func eqStrings(a, b []string) bool { return true } -func eqCIDRs(a, b []netaddr.IPPrefix) bool { +func eqCIDRs(a, b []netip.Prefix) bool { if len(a) != len(b) || ((a == nil) != (b == nil)) { return false } diff --git a/tailcfg/tailcfg_test.go b/tailcfg/tailcfg_test.go index 829eaab69..28ecc7dbc 100644 --- a/tailcfg/tailcfg_test.go +++ b/tailcfg/tailcfg_test.go @@ -13,7 +13,6 @@ "testing" "time" - "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/types/key" "tailscale.com/version" @@ -40,7 +39,7 @@ func TestHostinfoEqual(t *testing.T) { have, hiHandles) } - nets := func(strs ...string) (ns []netaddr.IPPrefix) { + nets := func(strs ...string) (ns []netip.Prefix) { for _, s := range strs { n, err := netip.ParsePrefix(s) if err != nil { @@ -225,12 +224,12 @@ func TestHostinfoHowEqual(t *testing.T) { a: &Hostinfo{ IPNVersion: "1", ShieldsUp: false, - RoutableIPs: []netaddr.IPPrefix{netip.MustParsePrefix("1.2.3.0/24")}, + RoutableIPs: []netip.Prefix{netip.MustParsePrefix("1.2.3.0/24")}, }, b: &Hostinfo{ IPNVersion: "2", ShieldsUp: true, - RoutableIPs: []netaddr.IPPrefix{netip.MustParsePrefix("1.2.3.0/25")}, + RoutableIPs: []netip.Prefix{netip.MustParsePrefix("1.2.3.0/25")}, }, want: []string{"IPNVersion", "ShieldsUp", "RoutableIPs"}, }, @@ -403,23 +402,23 @@ func TestNodeEqual(t *testing.T) { true, }, { - &Node{Addresses: []netaddr.IPPrefix{}}, + &Node{Addresses: []netip.Prefix{}}, &Node{Addresses: nil}, false, }, { - &Node{Addresses: []netaddr.IPPrefix{}}, - &Node{Addresses: []netaddr.IPPrefix{}}, + &Node{Addresses: []netip.Prefix{}}, + &Node{Addresses: []netip.Prefix{}}, true, }, { - &Node{AllowedIPs: []netaddr.IPPrefix{}}, + &Node{AllowedIPs: []netip.Prefix{}}, &Node{AllowedIPs: nil}, false, }, { - &Node{Addresses: []netaddr.IPPrefix{}}, - &Node{Addresses: []netaddr.IPPrefix{}}, + &Node{Addresses: []netip.Prefix{}}, + &Node{Addresses: []netip.Prefix{}}, true, }, { @@ -566,8 +565,8 @@ func TestCloneNode(t *testing.T) { }{ {"nil_fields", &Node{}}, {"zero_fields", &Node{ - Addresses: make([]netaddr.IPPrefix, 0), - AllowedIPs: make([]netaddr.IPPrefix, 0), + Addresses: make([]netip.Prefix, 0), + AllowedIPs: make([]netip.Prefix, 0), Endpoints: make([]string, 0), }}, } diff --git a/tsnet/tsnet.go b/tsnet/tsnet.go index 62071c56f..0f8f1a03d 100644 --- a/tsnet/tsnet.go +++ b/tsnet/tsnet.go @@ -14,6 +14,7 @@ "log" "net" "net/http" + "net/netip" "os" "path/filepath" "strings" @@ -32,7 +33,6 @@ "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" @@ -272,11 +272,11 @@ func (s *Server) start() error { if err := ns.Start(); err != nil { return fmt.Errorf("failed to start netstack: %w", err) } - s.dialer.UseNetstackForIP = func(ip netaddr.IP) bool { + s.dialer.UseNetstackForIP = func(ip netip.Addr) bool { _, ok := eng.PeerForIP(ip) return ok } - s.dialer.NetstackDialTCP = func(ctx context.Context, dst netaddr.IPPort) (net.Conn, error) { + s.dialer.NetstackDialTCP = func(ctx context.Context, dst netip.AddrPort) (net.Conn, error) { return ns.DialContextTCP(ctx, dst) } diff --git a/tstest/integration/integration_test.go b/tstest/integration/integration_test.go index 75388e437..787bef758 100644 --- a/tstest/integration/integration_test.go +++ b/tstest/integration/integration_test.go @@ -34,7 +34,6 @@ "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" "tailscale.com/ipn/store" - "tailscale.com/net/netaddr" "tailscale.com/safesocket" "tailscale.com/tailcfg" "tailscale.com/tstest" @@ -814,10 +813,10 @@ func (n *testNode) AwaitListening() { } } -func (n *testNode) AwaitIPs() []netaddr.IP { +func (n *testNode) AwaitIPs() []netip.Addr { t := n.env.t t.Helper() - var addrs []netaddr.IP + var addrs []netip.Addr if err := tstest.WaitFor(20*time.Second, func() error { cmd := n.Tailscale("ip") cmd.Stdout = nil // in case --verbose-tailscale was set @@ -828,7 +827,7 @@ func (n *testNode) AwaitIPs() []netaddr.IP { } ips := string(out) ipslice := strings.Fields(ips) - addrs = make([]netaddr.IP, len(ipslice)) + addrs = make([]netip.Addr, len(ipslice)) for i, ip := range ipslice { netIP, err := netip.ParseAddr(ip) @@ -848,7 +847,7 @@ func (n *testNode) AwaitIPs() []netaddr.IP { } // AwaitIP returns the IP address of n. -func (n *testNode) AwaitIP() netaddr.IP { +func (n *testNode) AwaitIP() netip.Addr { t := n.env.t t.Helper() ips := n.AwaitIPs() diff --git a/tstest/integration/tailscaled_deps_test_darwin.go b/tstest/integration/tailscaled_deps_test_darwin.go index 60ee07949..b5250c39c 100644 --- a/tstest/integration/tailscaled_deps_test_darwin.go +++ b/tstest/integration/tailscaled_deps_test_darwin.go @@ -23,7 +23,6 @@ _ "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 abf79d8cb..37bf376c5 100644 --- a/tstest/integration/tailscaled_deps_test_freebsd.go +++ b/tstest/integration/tailscaled_deps_test_freebsd.go @@ -23,7 +23,6 @@ _ "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 60ee07949..b5250c39c 100644 --- a/tstest/integration/tailscaled_deps_test_linux.go +++ b/tstest/integration/tailscaled_deps_test_linux.go @@ -23,7 +23,6 @@ _ "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 abf79d8cb..37bf376c5 100644 --- a/tstest/integration/tailscaled_deps_test_openbsd.go +++ b/tstest/integration/tailscaled_deps_test_openbsd.go @@ -23,7 +23,6 @@ _ "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 a82637ac5..122c99528 100644 --- a/tstest/integration/tailscaled_deps_test_windows.go +++ b/tstest/integration/tailscaled_deps_test_windows.go @@ -28,7 +28,6 @@ _ "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 cf972488f..e20e41b75 100644 --- a/tstest/integration/testcontrol/testcontrol.go +++ b/tstest/integration/testcontrol/testcontrol.go @@ -312,7 +312,7 @@ func (s *Server) AddFakeNode() { r := nk.Raw32() id := int64(binary.LittleEndian.Uint64(r[:])) ip := netaddr.IPv4(r[0], r[1], r[2], r[3]) - addr := netaddr.IPPrefixFrom(ip, 32) + addr := netip.PrefixFrom(ip, 32) s.nodes[nk] = &tailcfg.Node{ ID: tailcfg.NodeID(id), StableID: tailcfg.StableNodeID(fmt.Sprintf("TESTCTRL%08x", id)), @@ -321,8 +321,8 @@ func (s *Server) AddFakeNode() { Key: nk, MachineAuthorized: true, DiscoKey: dk, - Addresses: []netaddr.IPPrefix{addr}, - AllowedIPs: []netaddr.IPPrefix{addr}, + Addresses: []netip.Prefix{addr}, + AllowedIPs: []netip.Prefix{addr}, } // TODO: send updates to other (non-fake?) nodes } @@ -475,10 +475,10 @@ 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.Addr()), 128) + v4Prefix := netip.PrefixFrom(netaddr.IPv4(100, 64, uint8(tailcfg.NodeID(user.ID)>>8), uint8(tailcfg.NodeID(user.ID))), 32) + v6Prefix := netip.PrefixFrom(tsaddr.Tailscale4To6(v4Prefix.Addr()), 128) - allowedIPs := []netaddr.IPPrefix{ + allowedIPs := []netip.Prefix{ v4Prefix, v6Prefix, } @@ -761,10 +761,10 @@ func (s *Server) MapResponse(req *tailcfg.MapRequest) (res *tailcfg.MapResponse, return res.Peers[i].ID < res.Peers[j].ID }) - 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.Addr()), 128) + v4Prefix := netip.PrefixFrom(netaddr.IPv4(100, 64, uint8(tailcfg.NodeID(user.ID)>>8), uint8(tailcfg.NodeID(user.ID))), 32) + v6Prefix := netip.PrefixFrom(tsaddr.Tailscale4To6(v4Prefix.Addr()), 128) - res.Node.Addresses = []netaddr.IPPrefix{ + res.Node.Addresses = []netip.Prefix{ v4Prefix, v6Prefix, } diff --git a/tstest/integration/vms/derive_bindhost_test.go b/tstest/integration/vms/derive_bindhost_test.go index eeac158f4..da793d5a0 100644 --- a/tstest/integration/vms/derive_bindhost_test.go +++ b/tstest/integration/vms/derive_bindhost_test.go @@ -6,11 +6,11 @@ import ( "io" + "net/netip" "runtime" "testing" "tailscale.com/net/interfaces" - "tailscale.com/net/netaddr" ) func deriveBindhost(t *testing.T) string { @@ -22,7 +22,7 @@ func deriveBindhost(t *testing.T) string { } var ret string - err = interfaces.ForeachInterfaceAddress(func(i interfaces.Interface, prefix netaddr.IPPrefix) { + err = interfaces.ForeachInterfaceAddress(func(i interfaces.Interface, prefix netip.Prefix) { if ret != "" || i.Name != ifName { return } diff --git a/tstest/integration/vms/harness_test.go b/tstest/integration/vms/harness_test.go index 6fb9cff2a..5785635cf 100644 --- a/tstest/integration/vms/harness_test.go +++ b/tstest/integration/vms/harness_test.go @@ -26,7 +26,6 @@ "golang.org/x/crypto/ssh" "golang.org/x/net/proxy" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstest/integration" "tailscale.com/tstest/integration/testcontrol" @@ -43,7 +42,7 @@ type Harness struct { signer ssh.Signer cs *testcontrol.Server loginServerURL string - testerV4 netaddr.IP + testerV4 netip.Addr ipMu *sync.Mutex ipMap map[string]ipMapping } @@ -240,6 +239,6 @@ func (h *Harness) makeTestNode(t *testing.T, controlURL string) { h.testerV4 = bytes2Netaddr(h.Tailscale(t, "ip", "-4")) } -func bytes2Netaddr(inp []byte) netaddr.IP { +func bytes2Netaddr(inp []byte) netip.Addr { return netip.MustParseAddr(string(bytes.TrimSpace(inp))) } diff --git a/tstest/integration/vms/vms_steps_test.go b/tstest/integration/vms/vms_steps_test.go index 684ceb3d2..5fb4b6b42 100644 --- a/tstest/integration/vms/vms_steps_test.go +++ b/tstest/integration/vms/vms_steps_test.go @@ -13,12 +13,12 @@ "fmt" "net" "net/http" + "net/netip" "strings" "testing" "time" "golang.org/x/crypto/ssh" - "tailscale.com/net/netaddr" ) const timeout = 15 * time.Second @@ -40,7 +40,7 @@ func retry(t *testing.T, fn func() error) { t.Fatalf("tried %d times, got: %v", tries, err) } -func (h *Harness) testPing(t *testing.T, ipAddr netaddr.IP, cli *ssh.Client) { +func (h *Harness) testPing(t *testing.T, ipAddr netip.Addr, cli *ssh.Client) { retry(t, func() error { sess := getSession(t, cli) cmd := fmt.Sprintf("tailscale ping --verbose %s", ipAddr) @@ -85,7 +85,7 @@ func getSession(t *testing.T, cli *ssh.Client) *ssh.Session { return sess } -func (h *Harness) testOutgoingTCP(t *testing.T, ipAddr netaddr.IP, cli *ssh.Client) { +func (h *Harness) testOutgoingTCP(t *testing.T, ipAddr netip.Addr, cli *ssh.Client) { const sendmsg = "this is a message that curl won't print" ctx, cancel := context.WithCancel(context.Background()) s := &http.Server{ diff --git a/tstest/integration/vms/vms_test.go b/tstest/integration/vms/vms_test.go index d9524c8d8..aaa29df4a 100644 --- a/tstest/integration/vms/vms_test.go +++ b/tstest/integration/vms/vms_test.go @@ -29,7 +29,6 @@ expect "github.com/tailscale/goexpect" "golang.org/x/crypto/ssh" "golang.org/x/sync/semaphore" - "tailscale.com/net/netaddr" "tailscale.com/tstest" "tailscale.com/tstest/integration" "tailscale.com/types/logger" @@ -441,7 +440,7 @@ func (h *Harness) testDistro(t *testing.T, d Distro, ipm ipMapping) { for _, tt := range []struct { ipProto string - addr netaddr.IP + addr netip.Addr }{ {"ipv4", h.testerV4}, } { diff --git a/tstest/natlab/firewall.go b/tstest/natlab/firewall.go index 2fc458d40..1e8cb4e67 100644 --- a/tstest/natlab/firewall.go +++ b/tstest/natlab/firewall.go @@ -9,8 +9,6 @@ "net/netip" "sync" "time" - - "tailscale.com/net/netaddr" ) // FirewallType is the type of filtering a stateful firewall @@ -38,8 +36,8 @@ // some fields, so in practice the key is either a 2-tuple (src only), // 3-tuple (src ip+port and dst ip) or 4-tuple (src+dst ip+port). type fwKey struct { - src netaddr.IPPort - dst netaddr.IPPort + src netip.AddrPort + dst netip.AddrPort } // key returns an fwKey for the given src and dst, trimmed according @@ -48,7 +46,7 @@ type fwKey struct { // world), it's the caller's responsibility to swap src and dst in the // call to key when processing packets inbound from the "untrusted" // world. -func (s FirewallType) key(src, dst netaddr.IPPort) fwKey { +func (s FirewallType) key(src, dst netip.AddrPort) fwKey { k := fwKey{src: src} switch s { case EndpointIndependentFirewall: diff --git a/tstest/natlab/nat.go b/tstest/natlab/nat.go index f6b8f46fb..88676d591 100644 --- a/tstest/natlab/nat.go +++ b/tstest/natlab/nat.go @@ -11,15 +11,13 @@ "net/netip" "sync" "time" - - "tailscale.com/net/netaddr" ) // mapping is the state of an allocated NAT session. type mapping struct { - lanSrc netaddr.IPPort - lanDst netaddr.IPPort - wanSrc netaddr.IPPort + lanSrc netip.AddrPort + lanDst netip.AddrPort + wanSrc netip.AddrPort deadline time.Time // pc is a PacketConn that reserves an outbound port on the NAT's @@ -55,10 +53,10 @@ type mapping struct { // fields, so in practice the key is either a 2-tuple (src only), // 3-tuple (src ip+port and dst ip) or 4-tuple (src+dst ip+port). type natKey struct { - src, dst netaddr.IPPort + src, dst netip.AddrPort } -func (t NATType) key(src, dst netaddr.IPPort) natKey { +func (t NATType) key(src, dst netip.AddrPort) natKey { k := natKey{src: src} switch t { case EndpointIndependentNAT: @@ -102,7 +100,7 @@ type SNAT44 struct { mu sync.Mutex byLAN map[natKey]*mapping // lookup by outbound packet tuple - byWAN map[netaddr.IPPort]*mapping // lookup by wan ip:port only + byWAN map[netip.AddrPort]*mapping // lookup by wan ip:port only } func (n *SNAT44) timeNow() time.Time { @@ -122,7 +120,7 @@ func (n *SNAT44) mappingTimeout() time.Duration { func (n *SNAT44) initLocked() { if n.byLAN == nil { n.byLAN = map[natKey]*mapping{} - n.byWAN = map[netaddr.IPPort]*mapping{} + n.byWAN = map[netip.AddrPort]*mapping{} } if n.ExternalInterface.Machine() != n.Machine { panic(fmt.Sprintf("NAT given interface %s that is not part of given machine %s", n.ExternalInterface, n.Machine.Name)) @@ -228,7 +226,7 @@ func (n *SNAT44) HandleForward(p *Packet, iif, oif *Interface) *Packet { } } -func (n *SNAT44) allocateMappedPort() (net.PacketConn, netaddr.IPPort) { +func (n *SNAT44) allocateMappedPort() (net.PacketConn, netip.AddrPort) { // Clean up old entries before trying to allocate, to free up any // expired ports. n.gc() @@ -238,7 +236,7 @@ func (n *SNAT44) allocateMappedPort() (net.PacketConn, netaddr.IPPort) { if err != nil { panic(fmt.Sprintf("ran out of NAT ports: %v", err)) } - addr := netaddr.IPPortFrom(ip, uint16(pc.LocalAddr().(*net.UDPAddr).Port)) + addr := netip.AddrPortFrom(ip, uint16(pc.LocalAddr().(*net.UDPAddr).Port)) return pc, addr } diff --git a/tstest/natlab/natlab.go b/tstest/natlab/natlab.go index 5f2ce9cbb..a55a2e485 100644 --- a/tstest/natlab/natlab.go +++ b/tstest/natlab/natlab.go @@ -31,7 +31,7 @@ // Packet represents a UDP packet flowing through the virtual network. type Packet struct { - Src, Dst netaddr.IPPort + Src, Dst netip.AddrPort Payload []byte // Prefix set by various internal methods of natlab, to locate @@ -80,7 +80,7 @@ func (p *Packet) setLocator(msg string, args ...any) { p.locator = fmt.Sprintf(" "+msg, args...) } -func mustPrefix(s string) netaddr.IPPrefix { +func mustPrefix(s string) netip.Prefix { ipp, err := netip.ParsePrefix(s) if err != nil { panic(err) @@ -100,14 +100,14 @@ func NewInternet() *Network { type Network struct { Name string - Prefix4 netaddr.IPPrefix - Prefix6 netaddr.IPPrefix + Prefix4 netip.Prefix + Prefix6 netip.Prefix mu sync.Mutex - machine map[netaddr.IP]*Interface + machine map[netip.Addr]*Interface defaultGW *Interface // optional - lastV4 netaddr.IP - lastV6 netaddr.IP + lastV4 netip.Addr + lastV6 netip.Addr } func (n *Network) SetDefaultGateway(gwIf *Interface) { @@ -119,21 +119,21 @@ func (n *Network) SetDefaultGateway(gwIf *Interface) { n.defaultGW = gwIf } -func (n *Network) addMachineLocked(ip netaddr.IP, iface *Interface) { +func (n *Network) addMachineLocked(ip netip.Addr, iface *Interface) { if iface == nil { return // for tests } if n.machine == nil { - n.machine = map[netaddr.IP]*Interface{} + n.machine = map[netip.Addr]*Interface{} } n.machine[ip] = iface } -func (n *Network) allocIPv4(iface *Interface) netaddr.IP { +func (n *Network) allocIPv4(iface *Interface) netip.Addr { n.mu.Lock() defer n.mu.Unlock() if !n.Prefix4.IsValid() { - return netaddr.IP{} + return netip.Addr{} } if !n.lastV4.IsValid() { n.lastV4 = n.Prefix4.Addr() @@ -148,11 +148,11 @@ func (n *Network) allocIPv4(iface *Interface) netaddr.IP { return n.lastV4 } -func (n *Network) allocIPv6(iface *Interface) netaddr.IP { +func (n *Network) allocIPv6(iface *Interface) netip.Addr { n.mu.Lock() defer n.mu.Unlock() if !n.Prefix6.IsValid() { - return netaddr.IP{} + return netip.Addr{} } if !n.lastV6.IsValid() { n.lastV6 = n.Prefix6.Addr() @@ -212,7 +212,7 @@ type Interface struct { machine *Machine net *Network name string // optional - ips []netaddr.IP // static; not mutated once created + ips []netip.Addr // static; not mutated once created } func (f *Interface) Machine() *Machine { @@ -224,18 +224,18 @@ func (f *Interface) Network() *Network { } // V4 returns the machine's first IPv4 address, or the zero value if none. -func (f *Interface) V4() netaddr.IP { return f.pickIP(netaddr.IP.Is4) } +func (f *Interface) V4() netip.Addr { return f.pickIP(netip.Addr.Is4) } // V6 returns the machine's first IPv6 address, or the zero value if none. -func (f *Interface) V6() netaddr.IP { return f.pickIP(netaddr.IP.Is6) } +func (f *Interface) V6() netip.Addr { return f.pickIP(netip.Addr.Is6) } -func (f *Interface) pickIP(pred func(netaddr.IP) bool) netaddr.IP { +func (f *Interface) pickIP(pred func(netip.Addr) bool) netip.Addr { for _, ip := range f.ips { if pred(ip) { return ip } } - return netaddr.IP{} + return netip.Addr{} } func (f *Interface) String() string { @@ -247,7 +247,7 @@ func (f *Interface) String() string { } // Contains reports whether f contains ip as an IP. -func (f *Interface) Contains(ip netaddr.IP) bool { +func (f *Interface) Contains(ip netip.Addr) bool { for _, v := range f.ips { if ip == v { return true @@ -257,7 +257,7 @@ func (f *Interface) Contains(ip netaddr.IP) bool { } type routeEntry struct { - prefix netaddr.IPPrefix + prefix netip.Prefix iface *Interface } @@ -341,11 +341,11 @@ type Machine struct { interfaces []*Interface routes []routeEntry // sorted by longest prefix to shortest - conns4 map[netaddr.IPPort]*conn // conns that want IPv4 packets - conns6 map[netaddr.IPPort]*conn // conns that want IPv6 packets + conns4 map[netip.AddrPort]*conn // conns that want IPv4 packets + conns6 map[netip.AddrPort]*conn // conns that want IPv6 packets } -func (m *Machine) isLocalIP(ip netaddr.IP) bool { +func (m *Machine) isLocalIP(ip netip.Addr) bool { m.mu.Lock() defer m.mu.Unlock() for _, intf := range m.interfaces { @@ -392,10 +392,10 @@ func (m *Machine) deliverLocalPacket(p *Packet, iface *Interface) { if p.Dst.Addr().Is6() { conns = m.conns6 } - possibleDsts := []netaddr.IPPort{ + possibleDsts := []netip.AddrPort{ p.Dst, - netaddr.IPPortFrom(v6unspec, p.Dst.Port()), - netaddr.IPPortFrom(v4unspec, p.Dst.Port()), + netip.AddrPortFrom(v6unspec, p.Dst.Port()), + netip.AddrPortFrom(v4unspec, p.Dst.Port()), } for _, dest := range possibleDsts { c, ok := conns[dest] @@ -443,7 +443,7 @@ func (m *Machine) forwardPacket(p *Packet, iif *Interface) { oif.net.write(p) } -func unspecOf(ip netaddr.IP) netaddr.IP { +func unspecOf(ip netip.Addr) netip.Addr { if ip.Is4() { return v4unspec } @@ -562,7 +562,7 @@ func (m *Machine) writePacket(p *Packet) (n int, err error) { return iface.net.write(p) } -func (m *Machine) interfaceForIP(ip netaddr.IP) (*Interface, error) { +func (m *Machine) interfaceForIP(ip netip.Addr) (*Interface, error) { m.mu.Lock() defer m.mu.Unlock() for _, re := range m.routes { @@ -642,12 +642,12 @@ func (m *Machine) unregisterConn6(c *conn) { delete(m.conns6, c.ipp) } -func registerConn(conns *map[netaddr.IPPort]*conn, c *conn) error { +func registerConn(conns *map[netip.AddrPort]*conn, c *conn) error { if _, ok := (*conns)[c.ipp]; ok { return fmt.Errorf("duplicate conn listening on %v", c.ipp) } if *conns == nil { - *conns = map[netaddr.IPPort]*conn{} + *conns = map[netip.AddrPort]*conn{} } (*conns)[c.ipp] = c return nil @@ -659,7 +659,7 @@ func (m *Machine) ListenPacket(ctx context.Context, network, address string) (ne // if udp4, udp6, etc... look at address IP vs unspec var ( fam uint8 - ip netaddr.IP + ip netip.Addr ) switch network { default: @@ -705,7 +705,7 @@ func (m *Machine) ListenPacket(ctx context.Context, network, address string) (ne return nil, nil } } - ipp := netaddr.IPPortFrom(ip, port) + ipp := netip.AddrPortFrom(ip, port) c := &conn{ m: m, @@ -738,7 +738,7 @@ func (m *Machine) ListenPacket(ctx context.Context, network, address string) (ne type conn struct { m *Machine fam uint8 // 0, 4, or 6 - ipp netaddr.IPPort + ipp netip.AddrPort mu sync.Mutex closed bool diff --git a/tstest/natlab/natlab_test.go b/tstest/natlab/natlab_test.go index c8896000b..8a1a9cdc0 100644 --- a/tstest/natlab/natlab_test.go +++ b/tstest/natlab/natlab_test.go @@ -12,15 +12,14 @@ "testing" "time" - "tailscale.com/net/netaddr" "tailscale.com/tstest" ) func TestAllocIPs(t *testing.T) { n := NewInternet() - saw := map[netaddr.IP]bool{} + saw := map[netip.Addr]bool{} for i := 0; i < 255; i++ { - for _, f := range []func(*Interface) netaddr.IP{n.allocIPv4, n.allocIPv6} { + for _, f := range []func(*Interface) netip.Addr{n.allocIPv4, n.allocIPv6} { ip := f(nil) if saw[ip] { t.Fatalf("got duplicate %v", ip) @@ -51,8 +50,8 @@ func TestSendPacket(t *testing.T) { ifFoo := foo.Attach("eth0", internet) ifBar := bar.Attach("enp0s1", internet) - fooAddr := netaddr.IPPortFrom(ifFoo.V4(), 123) - barAddr := netaddr.IPPortFrom(ifBar.V4(), 456) + fooAddr := netip.AddrPortFrom(ifFoo.V4(), 123) + barAddr := netip.AddrPortFrom(ifBar.V4(), 456) ctx := context.Background() fooPC, err := foo.ListenPacket(ctx, "udp4", fooAddr.String()) @@ -113,10 +112,10 @@ func TestMultiNetwork(t *testing.T) { t.Fatal(err) } - clientAddr := netaddr.IPPortFrom(ifClient.V4(), 123) - natLANAddr := netaddr.IPPortFrom(ifNATLAN.V4(), 456) - natWANAddr := netaddr.IPPortFrom(ifNATWAN.V4(), 456) - serverAddr := netaddr.IPPortFrom(ifServer.V4(), 789) + clientAddr := netip.AddrPortFrom(ifClient.V4(), 123) + natLANAddr := netip.AddrPortFrom(ifNATLAN.V4(), 456) + natWANAddr := netip.AddrPortFrom(ifNATWAN.V4(), 456) + serverAddr := netip.AddrPortFrom(ifServer.V4(), 789) const msg1, msg2 = "hello", "world" if _, err := natPC.WriteTo([]byte(msg1), net.UDPAddrFromAddrPort(clientAddr)); err != nil { @@ -151,7 +150,7 @@ func TestMultiNetwork(t *testing.T) { } type trivialNAT struct { - clientIP netaddr.IP + clientIP netip.Addr lanIf, wanIf *Interface } @@ -218,7 +217,7 @@ func TestPacketHandler(t *testing.T) { } const msg = "some message" - serverAddr := netaddr.IPPortFrom(ifServer.V4(), 456) + serverAddr := netip.AddrPortFrom(ifServer.V4(), 456) if _, err := clientPC.WriteTo([]byte(msg), net.UDPAddrFromAddrPort(serverAddr)); err != nil { t.Fatal(err) } @@ -232,7 +231,7 @@ func TestPacketHandler(t *testing.T) { if string(buf) != msg { t.Errorf("read %q; want %q", buf, msg) } - mappedAddr := netaddr.IPPortFrom(ifNATWAN.V4(), 123) + mappedAddr := netip.AddrPortFrom(ifNATWAN.V4(), 123) if addr.String() != mappedAddr.String() { t.Errorf("addr = %q; want %q", addr, mappedAddr) } @@ -318,7 +317,7 @@ func TestFirewall(t *testing.T) { type fwTest struct { iif, oif *Interface - src, dst netaddr.IPPort + src, dst netip.AddrPort ok bool } @@ -341,7 +340,7 @@ func testFirewall(t *testing.T, f *Firewall, tests []fwTest) { } } -func ipp(str string) netaddr.IPPort { +func ipp(str string) netip.AddrPort { ipp, err := netip.ParseAddrPort(str) if err != nil { panic(err) @@ -455,7 +454,7 @@ func TestNAT(t *testing.T) { } type natTest struct { - src, dst netaddr.IPPort + src, dst netip.AddrPort wantNewMapping bool } @@ -463,7 +462,7 @@ func testNAT(t *testing.T, n *SNAT44, lanIf, wanIf *Interface, tests []natTest) clock := &tstest.Clock{} n.TimeNow = clock.Now - mappings := map[netaddr.IPPort]bool{} + mappings := map[netip.AddrPort]bool{} for _, test := range tests { clock.Advance(time.Second) p := &Packet{ diff --git a/types/dnstype/dnstype.go b/types/dnstype/dnstype.go index 7eb41049f..9a3db4744 100644 --- a/types/dnstype/dnstype.go +++ b/types/dnstype/dnstype.go @@ -9,8 +9,6 @@ import ( "net/netip" - - "tailscale.com/net/netaddr" ) // Resolver is the configuration for one DNS resolver. @@ -29,20 +27,20 @@ type Resolver struct { // BootstrapResolution may be empty, in which case clients should // look up the DoT/DoH server using their local "classic" DNS // resolver. - BootstrapResolution []netaddr.IP `json:",omitempty"` + BootstrapResolution []netip.Addr `json:",omitempty"` } // IPPort returns r.Addr as an IP address and port if either // r.Addr is an IP address (the common case) or if r.Addr // is an IP:port (as done in tests). -func (r *Resolver) IPPort() (ipp netaddr.IPPort, ok bool) { +func (r *Resolver) IPPort() (ipp netip.AddrPort, ok bool) { if r.Addr == "" || r.Addr[0] == 'h' || r.Addr[0] == 't' { // Fast path to avoid ParseIP error allocation for obviously not IP // cases. return } if ip, err := netip.ParseAddr(r.Addr); err == nil { - return netaddr.IPPortFrom(ip, 53), true + return netip.AddrPortFrom(ip, 53), true } if ipp, err := netip.ParseAddrPort(r.Addr); err == nil { return ipp, true diff --git a/types/dnstype/dnstype_view.go b/types/dnstype/dnstype_view.go index 6c3345c5b..7a68f6381 100644 --- a/types/dnstype/dnstype_view.go +++ b/types/dnstype/dnstype_view.go @@ -9,8 +9,8 @@ import ( "encoding/json" "errors" + "net/netip" - "tailscale.com/net/netaddr" "tailscale.com/types/views" ) @@ -58,12 +58,12 @@ func (v *ResolverView) UnmarshalJSON(b []byte) error { } func (v ResolverView) Addr() string { return v.ж.Addr } -func (v ResolverView) BootstrapResolution() views.Slice[netaddr.IP] { +func (v ResolverView) BootstrapResolution() views.Slice[netip.Addr] { return views.SliceOf(v.ж.BootstrapResolution) } // A compilation failure here means this code must be regenerated, with the command at the top of this file. var _ResolverViewNeedsRegeneration = Resolver(struct { Addr string - BootstrapResolution []netaddr.IP + BootstrapResolution []netip.Addr }{}) diff --git a/types/netmap/netmap.go b/types/netmap/netmap.go index d56304544..27992eb8a 100644 --- a/types/netmap/netmap.go +++ b/types/netmap/netmap.go @@ -8,11 +8,11 @@ import ( "encoding/json" "fmt" + "net/netip" "reflect" "strings" "time" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" "tailscale.com/wgengine/filter" @@ -31,7 +31,7 @@ type NetworkMap struct { Expiry time.Time // Name is the DNS name assigned to this node. Name string - Addresses []netaddr.IPPrefix // same as tailcfg.Node.Addresses (IP addresses of this Node directly) + Addresses []netip.Prefix // same as tailcfg.Node.Addresses (IP addresses of this Node directly) MachineStatus tailcfg.MachineStatus MachineKey key.MachinePublic Peers []*tailcfg.Node // sorted by Node.ID @@ -74,7 +74,7 @@ type NetworkMap struct { // PeerByTailscaleIP returns a peer's Node based on its Tailscale IP. // // If nm is nil or no peer is found, ok is false. -func (nm *NetworkMap) PeerByTailscaleIP(ip netaddr.IP) (peer *tailcfg.Node, ok bool) { +func (nm *NetworkMap) PeerByTailscaleIP(ip netip.Addr) (peer *tailcfg.Node, ok bool) { // TODO(bradfitz): if nm == nil { return nil, false @@ -305,7 +305,7 @@ func eqStringsIgnoreNil(a, b []string) bool { // eqCIDRsIgnoreNil reports whether a and b have the same length and // contents, but ignore whether a or b are nil. -func eqCIDRsIgnoreNil(a, b []netaddr.IPPrefix) bool { +func eqCIDRsIgnoreNil(a, b []netip.Prefix) bool { if len(a) != len(b) { return false } diff --git a/types/netmap/netmap_test.go b/types/netmap/netmap_test.go index 41f0e12df..9bd54c980 100644 --- a/types/netmap/netmap_test.go +++ b/types/netmap/netmap_test.go @@ -6,6 +6,7 @@ import ( "encoding/hex" + "net/netip" "testing" "go4.org/mem" @@ -256,7 +257,7 @@ func TestConciseDiffFrom(t *testing.T) { DERP: "127.3.3.40:2", Endpoints: []string{"192.168.0.100:41641", "1.1.1.1:41641"}, DiscoKey: testDiscoKey("f00f00f00f"), - AllowedIPs: []netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.IPv4(100, 102, 103, 104), 32)}, + AllowedIPs: []netip.Prefix{netip.PrefixFrom(netaddr.IPv4(100, 102, 103, 104), 32)}, }, }, }, @@ -269,7 +270,7 @@ func TestConciseDiffFrom(t *testing.T) { DERP: "127.3.3.40:2", Endpoints: []string{"192.168.0.100:41641", "1.1.1.1:41641"}, DiscoKey: testDiscoKey("ba4ba4ba4b"), - AllowedIPs: []netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.IPv4(100, 102, 103, 104), 32)}, + AllowedIPs: []netip.Prefix{netip.PrefixFrom(netaddr.IPv4(100, 102, 103, 104), 32)}, }, }, }, diff --git a/types/views/views.go b/types/views/views.go index c0e20bb99..bfefbef4d 100644 --- a/types/views/views.go +++ b/types/views/views.go @@ -9,8 +9,8 @@ import ( "encoding/json" "errors" + "net/netip" - "tailscale.com/net/netaddr" "tailscale.com/net/tsaddr" ) @@ -169,13 +169,13 @@ func SliceContains[T comparable](v Slice[T], e T) bool { return false } -// IPPrefixSlice is a read-only accessor for a slice of netaddr.IPPrefix. +// IPPrefixSlice is a read-only accessor for a slice of netip.Prefix. type IPPrefixSlice struct { - ж Slice[netaddr.IPPrefix] + ж Slice[netip.Prefix] } // IPPrefixSliceOf returns a IPPrefixSlice for the provided slice. -func IPPrefixSliceOf(x []netaddr.IPPrefix) IPPrefixSlice { return IPPrefixSlice{SliceOf(x)} } +func IPPrefixSliceOf(x []netip.Prefix) IPPrefixSlice { return IPPrefixSlice{SliceOf(x)} } // IsNil reports whether the underlying slice is nil. func (v IPPrefixSlice) IsNil() bool { return v.ж.IsNil() } @@ -184,30 +184,30 @@ func (v IPPrefixSlice) IsNil() bool { return v.ж.IsNil() } func (v IPPrefixSlice) Len() int { return v.ж.Len() } // At returns the IPPrefix at index `i` of the slice. -func (v IPPrefixSlice) At(i int) netaddr.IPPrefix { return v.ж.At(i) } +func (v IPPrefixSlice) At(i int) netip.Prefix { return v.ж.At(i) } // AppendTo appends the underlying slice values to dst. -func (v IPPrefixSlice) AppendTo(dst []netaddr.IPPrefix) []netaddr.IPPrefix { +func (v IPPrefixSlice) AppendTo(dst []netip.Prefix) []netip.Prefix { return v.ж.AppendTo(dst) } -// Unwrap returns the underlying Slice[netaddr.IPPrefix]. -func (v IPPrefixSlice) Unwrap() Slice[netaddr.IPPrefix] { +// Unwrap returns the underlying Slice[netip.Prefix]. +func (v IPPrefixSlice) Unwrap() Slice[netip.Prefix] { return v.ж } // AsSlice returns a copy of underlying slice. -func (v IPPrefixSlice) AsSlice() []netaddr.IPPrefix { +func (v IPPrefixSlice) AsSlice() []netip.Prefix { return v.ж.AsSlice() } // PrefixesContainsIP reports whether any IPPrefix contains IP. -func (v IPPrefixSlice) ContainsIP(ip netaddr.IP) bool { +func (v IPPrefixSlice) ContainsIP(ip netip.Addr) bool { return tsaddr.PrefixesContainsIP(v.ж.ж, ip) } // PrefixesContainsFunc reports whether f is true for any IPPrefix in the slice. -func (v IPPrefixSlice) ContainsFunc(f func(netaddr.IPPrefix) bool) bool { +func (v IPPrefixSlice) ContainsFunc(f func(netip.Prefix) bool) bool { return tsaddr.PrefixesContainsFunc(v.ж.ж, f) } diff --git a/types/views/views_test.go b/types/views/views_test.go index a9242aca0..b22f253b3 100644 --- a/types/views/views_test.go +++ b/types/views/views_test.go @@ -13,11 +13,10 @@ "testing" qt "github.com/frankban/quicktest" - "tailscale.com/net/netaddr" ) func TestViewsJSON(t *testing.T) { - mustCIDR := func(cidrs ...string) (out []netaddr.IPPrefix) { + mustCIDR := func(cidrs ...string) (out []netip.Prefix) { for _, cidr := range cidrs { out = append(out, netip.MustParsePrefix(cidr)) } diff --git a/util/codegen/codegen.go b/util/codegen/codegen.go index 3c8151d68..61ec85de8 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", "net/netip.Addr", "net/netip.Prefix", "net/netip.AddrPort": + case "inet.af/netip.Addr", "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 8ceb19a9e..e7897d0cf 100644 --- a/util/deephash/deephash_test.go +++ b/util/deephash/deephash_test.go @@ -191,7 +191,7 @@ func getVal() []any { return []any{ &wgcfg.Config{ Name: "foo", - Addresses: []netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.IPFrom16([16]byte{3: 3}), 5)}, + Addresses: []netip.Prefix{netip.PrefixFrom(netaddr.IPFrom16([16]byte{3: 3}), 5)}, Peers: []wgcfg.Peer{ { PublicKey: key.NodePublic{}, @@ -199,12 +199,12 @@ func getVal() []any { }, }, &router.Config{ - Routes: []netaddr.IPPrefix{ + Routes: []netip.Prefix{ netip.MustParsePrefix("1.2.3.0/24"), netip.MustParsePrefix("1234::/64"), }, }, - map[dnsname.FQDN][]netaddr.IP{ + map[dnsname.FQDN][]netip.Addr{ dnsname.FQDN("a."): {netip.MustParseAddr("1.2.3.4"), netip.MustParseAddr("4.3.2.1")}, dnsname.FQDN("b."): {netip.MustParseAddr("8.8.8.8"), netip.MustParseAddr("9.9.9.9")}, dnsname.FQDN("c."): {netip.MustParseAddr("6.6.6.6"), netip.MustParseAddr("7.7.7.7")}, @@ -212,7 +212,7 @@ func getVal() []any { dnsname.FQDN("e."): {netip.MustParseAddr("6.8.6.6"), netip.MustParseAddr("7.7.7.9")}, dnsname.FQDN("f."): {netip.MustParseAddr("6.9.6.6"), netip.MustParseAddr("7.7.7.0")}, }, - map[dnsname.FQDN][]netaddr.IPPort{ + map[dnsname.FQDN][]netip.AddrPort{ dnsname.FQDN("a."): {netip.MustParseAddrPort("1.2.3.4:11"), netip.MustParseAddrPort("4.3.2.1:22")}, dnsname.FQDN("b."): {netip.MustParseAddrPort("8.8.8.8:11"), netip.MustParseAddrPort("9.9.9.9:22")}, dnsname.FQDN("c."): {netip.MustParseAddrPort("8.8.8.8:12"), netip.MustParseAddrPort("9.9.9.9:23")}, @@ -497,18 +497,18 @@ func TestGetTypeHasher(t *testing.T) { out32: "\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00*\v\x00\x00\x00\x00\x00\x00\x0010.1.3.4/32\v\x00\x00\x00\x00\x00\x00\x0010.0.0.0/24\x03\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x001.2.3.4/32\x01 \x00\x00\x00\x01\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x001.2.3.4/32\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00foo\x01\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x00\x00\x00\x00foooooooooo\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00baaaaaarrrrr\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x00\x00\x00\x00foooooooooo\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00baaaaaarrrrr\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x00\x00\x00\x00foooooooooo\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\f\x00\x00\x00\x00\x00\x00\x00baaaaaarrrrr\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", }, { - name: "netaddr.IP", + name: "netip.Addr", val: netip.MustParseAddr("fe80::123%foo"), out: "\r\x00\x00\x00\x00\x00\x00\x00fe80::123%foo", }, { - name: "ptr-netaddr.IP", + name: "ptr-netip.Addr", val: &someIP, out: "\x01\a\x00\x00\x00\x00\x00\x00\x001.2.3.4", }, { - name: "ptr-nil-netaddr.IP", - val: (*netaddr.IP)(nil), + name: "ptr-nil-netip.Addr", + val: (*netip.Addr)(nil), out: "\x00", }, { @@ -651,7 +651,7 @@ func ptrTo[T any](v T) *T { return &v } }}, IPProto: []int{1, 2, 3, 4}, CapGrant: []tailcfg.CapGrant{{ - Dsts: []netaddr.IPPrefix{netip.MustParsePrefix("1.2.3.4/32")}, + Dsts: []netip.Prefix{netip.MustParsePrefix("1.2.3.4/32")}, Caps: []string{"foo"}, }}, }, diff --git a/wf/firewall.go b/wf/firewall.go index bfc168137..e10f8d93b 100644 --- a/wf/firewall.go +++ b/wf/firewall.go @@ -85,7 +85,7 @@ type Firewall struct { sublayerID wf.SublayerID session *wf.Session - permittedRoutes map[netaddr.IPPrefix][]*wf.Rule + permittedRoutes map[netip.Prefix][]*wf.Rule } // New returns a new Firewall for the provdied interface ID. @@ -125,7 +125,7 @@ func New(luid uint64) (*Firewall, error) { session: session, providerID: providerID, sublayerID: sublayerID, - permittedRoutes: make(map[netaddr.IPPrefix][]*wf.Rule), + permittedRoutes: make(map[netip.Prefix][]*wf.Rule), } if err := f.enable(); err != nil { return nil, err @@ -188,16 +188,16 @@ func (f *Firewall) enable() error { // UpdatedPermittedRoutes adds rules to allow incoming and outgoing connections // from the provided prefixes. It will also remove rules for routes that were // previously added but have been removed. -func (f *Firewall) UpdatePermittedRoutes(newRoutes []netaddr.IPPrefix) error { - var routesToAdd []netaddr.IPPrefix - routeMap := make(map[netaddr.IPPrefix]bool) +func (f *Firewall) UpdatePermittedRoutes(newRoutes []netip.Prefix) error { + var routesToAdd []netip.Prefix + routeMap := make(map[netip.Prefix]bool) for _, r := range newRoutes { routeMap[r] = true if _, ok := f.permittedRoutes[r]; !ok { routesToAdd = append(routesToAdd, r) } } - var routesToRemove []netaddr.IPPrefix + var routesToRemove []netip.Prefix for r := range f.permittedRoutes { if !routeMap[r] { routesToRemove = append(routesToRemove, r) diff --git a/wgengine/bench/trafficgen.go b/wgengine/bench/trafficgen.go index 00de0b1f4..4038ff1da 100644 --- a/wgengine/bench/trafficgen.go +++ b/wgengine/bench/trafficgen.go @@ -8,10 +8,10 @@ "encoding/binary" "fmt" "log" + "net/netip" "sync" "time" - "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/types/ipproto" ) @@ -94,7 +94,7 @@ func NewTrafficGen(onFirstPacket func()) *TrafficGen { // Start starts the traffic generator. It assumes mu is already locked, // and unlocks it. -func (t *TrafficGen) Start(src, dst netaddr.IP, bytesPerPacket int, maxPackets int64) { +func (t *TrafficGen) Start(src, dst netip.Addr, bytesPerPacket int, maxPackets int64) { h12 := packet.ICMP4Header{ IP4Header: packet.IP4Header{ IPProto: ipproto.ICMPv4, diff --git a/wgengine/bench/wg.go b/wgengine/bench/wg.go index 410ff45c7..d5e8df1d1 100644 --- a/wgengine/bench/wg.go +++ b/wgengine/bench/wg.go @@ -8,12 +8,12 @@ "errors" "io" "log" + "net/netip" "os" "sync" "testing" "golang.zx2c4.com/wireguard/tun" - "tailscale.com/net/netaddr" "tailscale.com/net/dns" "tailscale.com/tailcfg" @@ -26,14 +26,14 @@ "tailscale.com/wgengine/wgcfg" ) -func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netaddr.IPPrefix) { +func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netip.Prefix) { l1 := logger.WithPrefix(logf, "e1: ") k1 := key.NewNode() c1 := wgcfg.Config{ Name: "e1", PrivateKey: k1, - Addresses: []netaddr.IPPrefix{a1}, + Addresses: []netip.Prefix{a1}, } t1 := &sourceTun{ logf: logger.WithPrefix(logf, "tun1: "), @@ -57,7 +57,7 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netadd c2 := wgcfg.Config{ Name: "e2", PrivateKey: k2, - Addresses: []netaddr.IPPrefix{a2}, + Addresses: []netip.Prefix{a2}, } t2 := &sinkTun{ logf: logger.WithPrefix(logf, "tun2: "), @@ -100,8 +100,8 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netadd n := tailcfg.Node{ ID: tailcfg.NodeID(0), Name: "n1", - Addresses: []netaddr.IPPrefix{a1}, - AllowedIPs: []netaddr.IPPrefix{a1}, + Addresses: []netip.Prefix{a1}, + AllowedIPs: []netip.Prefix{a1}, Endpoints: eps, } e2.SetNetworkMap(&netmap.NetworkMap{ @@ -112,7 +112,7 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netadd p := wgcfg.Peer{ PublicKey: c1.PrivateKey.Public(), - AllowedIPs: []netaddr.IPPrefix{a1}, + AllowedIPs: []netip.Prefix{a1}, } c2.Peers = []wgcfg.Peer{p} e2.Reconfig(&c2, &router.Config{}, new(dns.Config), nil) @@ -137,8 +137,8 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netadd n := tailcfg.Node{ ID: tailcfg.NodeID(0), Name: "n2", - Addresses: []netaddr.IPPrefix{a2}, - AllowedIPs: []netaddr.IPPrefix{a2}, + Addresses: []netip.Prefix{a2}, + AllowedIPs: []netip.Prefix{a2}, Endpoints: eps, } e1.SetNetworkMap(&netmap.NetworkMap{ @@ -149,7 +149,7 @@ func setupWGTest(b *testing.B, logf logger.Logf, traf *TrafficGen, a1, a2 netadd p := wgcfg.Peer{ PublicKey: c2.PrivateKey.Public(), - AllowedIPs: []netaddr.IPPrefix{a2}, + AllowedIPs: []netip.Prefix{a2}, } c1.Peers = []wgcfg.Peer{p} e1.Reconfig(&c1, &router.Config{}, new(dns.Config), nil) diff --git a/wgengine/filter/filter.go b/wgengine/filter/filter.go index 483642fea..e7faf8eaf 100644 --- a/wgengine/filter/filter.go +++ b/wgengine/filter/filter.go @@ -7,6 +7,7 @@ import ( "fmt" + "net/netip" "sync" "time" @@ -107,12 +108,12 @@ func (r Response) IsDrop() bool { // everything. Use in tests only, as it permits some kinds of spoofing // attacks to reach the OS network stack. func NewAllowAllForTest(logf logger.Logf) *Filter { - any4 := netaddr.IPPrefixFrom(netaddr.IPv4(0, 0, 0, 0), 0) - any6 := netaddr.IPPrefixFrom(netaddr.IPFrom16([16]byte{}), 0) + any4 := netip.PrefixFrom(netaddr.IPv4(0, 0, 0, 0), 0) + any6 := netip.PrefixFrom(netaddr.IPFrom16([16]byte{}), 0) ms := []Match{ { IPProto: []ipproto.Proto{ipproto.TCP, ipproto.UDP, ipproto.ICMPv4}, - Srcs: []netaddr.IPPrefix{any4}, + Srcs: []netip.Prefix{any4}, Dsts: []NetPortRange{ { Net: any4, @@ -125,7 +126,7 @@ func NewAllowAllForTest(logf logger.Logf) *Filter { }, { IPProto: []ipproto.Proto{ipproto.TCP, ipproto.UDP, ipproto.ICMPv6}, - Srcs: []netaddr.IPPrefix{any6}, + Srcs: []netip.Prefix{any6}, Dsts: []NetPortRange{ { Net: any6, @@ -180,10 +181,10 @@ func New(matches []Match, localNets *netipx.IPSet, logIPs *netipx.IPSet, shareSt } f := &Filter{ logf: logf, - matches4: matchesFamily(matches, netaddr.IP.Is4), - matches6: matchesFamily(matches, netaddr.IP.Is6), - cap4: capMatchesFunc(matches, netaddr.IP.Is4), - cap6: capMatchesFunc(matches, netaddr.IP.Is6), + matches4: matchesFamily(matches, netip.Addr.Is4), + matches6: matchesFamily(matches, netip.Addr.Is6), + cap4: capMatchesFunc(matches, netip.Addr.Is4), + cap6: capMatchesFunc(matches, netip.Addr.Is6), local: localNets, logIPs: logIPs, state: state, @@ -193,7 +194,7 @@ func New(matches []Match, localNets *netipx.IPSet, logIPs *netipx.IPSet, shareSt // matchesFamily returns the subset of ms for which keep(srcNet.IP) // and keep(dstNet.IP) are both true. -func matchesFamily(ms matches, keep func(netaddr.IP) bool) matches { +func matchesFamily(ms matches, keep func(netip.Addr) bool) matches { var ret matches for _, m := range ms { var retm Match @@ -217,7 +218,7 @@ func matchesFamily(ms matches, keep func(netaddr.IP) bool) matches { // capMatchesFunc returns a copy of the subset of ms for which keep(srcNet.IP) // and the match is a capability grant. -func capMatchesFunc(ms matches, keep func(netaddr.IP) bool) matches { +func capMatchesFunc(ms matches, keep func(netip.Addr) bool) matches { var ret matches for _, m := range ms { if len(m.Caps) == 0 { @@ -299,7 +300,7 @@ func (f *Filter) logRateLimit(runflags RunFlags, q *packet.Parsed, dir direction // CheckTCP determines whether TCP traffic from srcIP to dstIP:dstPort // is allowed. -func (f *Filter) CheckTCP(srcIP, dstIP netaddr.IP, dstPort uint16) Response { +func (f *Filter) CheckTCP(srcIP, dstIP netip.Addr, dstPort uint16) Response { pkt := &packet.Parsed{} pkt.Decode(dummyPacket) // initialize private fields switch { @@ -314,8 +315,8 @@ func (f *Filter) CheckTCP(srcIP, dstIP netaddr.IP, dstPort uint16) Response { default: panic("unreachable") } - pkt.Src = netaddr.IPPortFrom(srcIP, 0) - pkt.Dst = netaddr.IPPortFrom(dstIP, dstPort) + pkt.Src = netip.AddrPortFrom(srcIP, 0) + pkt.Dst = netip.AddrPortFrom(dstIP, dstPort) pkt.IPProto = ipproto.TCP pkt.TCPFlags = packet.TCPSyn @@ -324,7 +325,7 @@ func (f *Filter) CheckTCP(srcIP, dstIP netaddr.IP, dstPort uint16) Response { // AppendCaps appends to base the capabilities that srcIP has talking // to dstIP. -func (f *Filter) AppendCaps(base []string, srcIP, dstIP netaddr.IP) []string { +func (f *Filter) AppendCaps(base []string, srcIP, dstIP netip.Addr) []string { ret := base var mm matches switch { diff --git a/wgengine/filter/filter_test.go b/wgengine/filter/filter_test.go index 8a165e73a..9caf377e1 100644 --- a/wgengine/filter/filter_test.go +++ b/wgengine/filter/filter_test.go @@ -15,7 +15,6 @@ "github.com/google/go-cmp/cmp" "go4.org/netipx" - "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" @@ -32,7 +31,7 @@ testDeniedProto ipproto.Proto = 127 // CRUDP, appropriately cruddy ) -func m(srcs []netaddr.IPPrefix, dsts []NetPortRange, protos ...ipproto.Proto) Match { +func m(srcs []netip.Prefix, dsts []NetPortRange, protos ...ipproto.Proto) Match { if protos == nil { protos = defaultProtos } @@ -243,7 +242,7 @@ func TestParseIPSet(t *testing.T) { tests := []struct { host string bits int - want []netaddr.IPPrefix + want []netip.Prefix wantErr string }{ {"8.8.8.8", 24, pfx("8.8.8.8/24"), ""}, @@ -273,8 +272,8 @@ func TestParseIPSet(t *testing.T) { } t.Errorf("parseIPSet(%q, %v) error: %v; want error %q", tt.host, tt.bits, err, tt.wantErr) } - compareIP := cmp.Comparer(func(a, b netaddr.IP) bool { return a == b }) - compareIPPrefix := cmp.Comparer(func(a, b netaddr.IPPrefix) bool { return a == b }) + compareIP := cmp.Comparer(func(a, b netip.Addr) bool { return a == b }) + compareIPPrefix := cmp.Comparer(func(a, b netip.Prefix) bool { return a == b }) if diff := cmp.Diff(got, tt.want, compareIP, compareIPPrefix); diff != "" { t.Errorf("parseIPSet(%q, %v) = %s; want %s", tt.host, tt.bits, got, tt.want) continue @@ -446,10 +445,10 @@ func TestLoggingPrivacy(t *testing.T) { f.logIPs, _ = logB.IPSet() var ( - ts4 = netaddr.IPPortFrom(tsaddr.CGNATRange().Addr().Next(), 1234) - internet4 = netaddr.IPPortFrom(netip.MustParseAddr("8.8.8.8"), 1234) - ts6 = netaddr.IPPortFrom(tsaddr.TailscaleULARange().Addr().Next(), 1234) - internet6 = netaddr.IPPortFrom(netip.MustParseAddr("2001::1"), 1234) + ts4 = netip.AddrPortFrom(tsaddr.CGNATRange().Addr().Next(), 1234) + internet4 = netip.AddrPortFrom(netip.MustParseAddr("8.8.8.8"), 1234) + ts6 = netip.AddrPortFrom(tsaddr.TailscaleULARange().Addr().Next(), 1234) + internet6 = netip.AddrPortFrom(netip.MustParseAddr("2001::1"), 1234) ) tests := []struct { @@ -560,8 +559,8 @@ func parsed(proto ipproto.Proto, src, dst string, sport, dport uint16) packet.Pa var ret packet.Parsed ret.Decode(dummyPacket) ret.IPProto = proto - ret.Src = netaddr.IPPortFrom(sip, sport) - ret.Dst = netaddr.IPPortFrom(dip, dport) + ret.Src = netip.AddrPortFrom(sip, sport) + ret.Dst = netip.AddrPortFrom(dip, dport) ret.TCPFlags = packet.TCPSyn if sip.Is4() { @@ -657,7 +656,7 @@ func parseHexPkt(t *testing.T, h string) *packet.Parsed { return p } -func mustIPPort(s string) netaddr.IPPort { +func mustIPPort(s string) netip.AddrPort { ipp, err := netip.ParseAddrPort(s) if err != nil { panic(err) @@ -665,7 +664,7 @@ func mustIPPort(s string) netaddr.IPPort { return ipp } -func pfx(strs ...string) (ret []netaddr.IPPrefix) { +func pfx(strs ...string) (ret []netip.Prefix) { for _, s := range strs { pfx, err := netip.ParsePrefix(s) if err != nil { @@ -676,7 +675,7 @@ func pfx(strs ...string) (ret []netaddr.IPPrefix) { return ret } -func nets(nets ...string) (ret []netaddr.IPPrefix) { +func nets(nets ...string) (ret []netip.Prefix) { for _, s := range nets { if !strings.Contains(s, "/") { ip, err := netip.ParseAddr(s) @@ -687,7 +686,7 @@ func nets(nets ...string) (ret []netaddr.IPPrefix) { if ip.Is6() { bits = 128 } - ret = append(ret, netaddr.IPPrefixFrom(ip, bits)) + ret = append(ret, netip.PrefixFrom(ip, int(bits))) } else { pfx, err := netip.ParsePrefix(s) if err != nil { @@ -779,7 +778,7 @@ func TestMatchesFromFilterRules(t *testing.T) { Ports: PortRange{22, 22}, }, }, - Srcs: []netaddr.IPPrefix{ + Srcs: []netip.Prefix{ netip.MustParsePrefix("100.64.1.1/32"), }, Caps: []CapMatch{}, @@ -809,7 +808,7 @@ func TestMatchesFromFilterRules(t *testing.T) { Ports: PortRange{22, 22}, }, }, - Srcs: []netaddr.IPPrefix{ + Srcs: []netip.Prefix{ netip.MustParsePrefix("100.64.1.1/32"), }, Caps: []CapMatch{}, @@ -824,8 +823,8 @@ func TestMatchesFromFilterRules(t *testing.T) { t.Fatal(err) } - compareIP := cmp.Comparer(func(a, b netaddr.IP) bool { return a == b }) - compareIPPrefix := cmp.Comparer(func(a, b netaddr.IPPrefix) bool { return a == b }) + compareIP := cmp.Comparer(func(a, b netip.Addr) bool { return a == b }) + compareIPPrefix := cmp.Comparer(func(a, b netip.Prefix) bool { return a == b }) if diff := cmp.Diff(got, tt.want, compareIP, compareIPPrefix); diff != "" { t.Errorf("wrong (-got+want)\n%s", diff) } @@ -885,7 +884,7 @@ func TestCaps(t *testing.T) { { SrcIPs: []string{"*"}, CapGrant: []tailcfg.CapGrant{{ - Dsts: []netaddr.IPPrefix{ + Dsts: []netip.Prefix{ netip.MustParsePrefix("0.0.0.0/0"), }, Caps: []string{"is_ipv4"}, @@ -894,7 +893,7 @@ func TestCaps(t *testing.T) { { SrcIPs: []string{"*"}, CapGrant: []tailcfg.CapGrant{{ - Dsts: []netaddr.IPPrefix{ + Dsts: []netip.Prefix{ netip.MustParsePrefix("::/0"), }, Caps: []string{"is_ipv6"}, @@ -903,7 +902,7 @@ func TestCaps(t *testing.T) { { SrcIPs: []string{"100.199.0.0/16"}, CapGrant: []tailcfg.CapGrant{{ - Dsts: []netaddr.IPPrefix{ + Dsts: []netip.Prefix{ netip.MustParsePrefix("100.200.0.0/16"), }, Caps: []string{"some_super_admin"}, diff --git a/wgengine/filter/match.go b/wgengine/filter/match.go index a045163a9..10484ce41 100644 --- a/wgengine/filter/match.go +++ b/wgengine/filter/match.go @@ -6,9 +6,9 @@ import ( "fmt" + "net/netip" "strings" - "tailscale.com/net/netaddr" "tailscale.com/net/packet" "tailscale.com/types/ipproto" ) @@ -39,7 +39,7 @@ func (pr PortRange) contains(port uint16) bool { // NetPortRange combines an IP address prefix and PortRange. type NetPortRange struct { - Net netaddr.IPPrefix + Net netip.Prefix Ports PortRange } @@ -51,7 +51,7 @@ func (npr NetPortRange) String() string { type CapMatch struct { // Dst is the IP prefix that the destination IP address matches against // to get the capability. - Dst netaddr.IPPrefix + Dst netip.Prefix // Cap is the capability that's granted if the destination IP addresses // matches Dst. @@ -62,7 +62,7 @@ type CapMatch struct { // Dsts. type Match struct { IPProto []ipproto.Proto // required set (no default value at this layer) - Srcs []netaddr.IPPrefix + Srcs []netip.Prefix Dsts []NetPortRange // optional, if Srcs match Caps []CapMatch // optional, if Srcs match } @@ -152,7 +152,7 @@ func (ms matches) matchProtoAndIPsOnlyIfAllPorts(q *packet.Parsed) bool { return false } -func ipInList(ip netaddr.IP, netlist []netaddr.IPPrefix) bool { +func ipInList(ip netip.Addr, netlist []netip.Prefix) bool { for _, net := range netlist { if net.Contains(ip) { return true diff --git a/wgengine/filter/tailcfg.go b/wgengine/filter/tailcfg.go index 8e44de7b4..fea673f2f 100644 --- a/wgengine/filter/tailcfg.go +++ b/wgengine/filter/tailcfg.go @@ -34,7 +34,7 @@ func MatchesFromFilterRules(pf []tailcfg.FilterRule) ([]Match, error) { // of time in runtime.growslice. As such, we attempt to // pre-allocate some slices. Multipliers were chosen arbitrarily. m := Match{ - Srcs: make([]netaddr.IPPrefix, 0, len(r.SrcIPs)), + Srcs: make([]netip.Prefix, 0, len(r.SrcIPs)), Dsts: make([]NetPortRange, 0, 2*len(r.DstPorts)), Caps: make([]CapMatch, 0, 3*len(r.CapGrant)), } @@ -114,12 +114,12 @@ func MatchesFromFilterRules(pf []tailcfg.FilterRule) ([]Match, error) { // around, and ultimately use a new version of IPSet.ContainsFunc like // Contains16Func that works in [16]byte address, so we we can match // at runtime without allocating? -func parseIPSet(arg string, bits *int) ([]netaddr.IPPrefix, error) { +func parseIPSet(arg string, bits *int) ([]netip.Prefix, error) { if arg == "*" { // User explicitly requested wildcard. - return []netaddr.IPPrefix{ - netaddr.IPPrefixFrom(zeroIP4, 0), - netaddr.IPPrefixFrom(zeroIP6, 0), + return []netip.Prefix{ + netip.PrefixFrom(zeroIP4, 0), + netip.PrefixFrom(zeroIP6, 0), }, nil } if strings.Contains(arg, "/") { @@ -130,7 +130,7 @@ func parseIPSet(arg string, bits *int) ([]netaddr.IPPrefix, error) { if pfx != pfx.Masked() { return nil, fmt.Errorf("%v contains non-network bits set", pfx) } - return []netaddr.IPPrefix{pfx}, nil + return []netip.Prefix{pfx}, nil } if strings.Count(arg, "-") == 1 { ip1s, ip2s, _ := strings.Cut(arg, "-") @@ -159,5 +159,5 @@ func parseIPSet(arg string, bits *int) ([]netaddr.IPPrefix, error) { } bits8 = uint8(*bits) } - return []netaddr.IPPrefix{netaddr.IPPrefixFrom(ip, bits8)}, nil + return []netip.Prefix{netip.PrefixFrom(ip, int(bits8))}, nil } diff --git a/wgengine/magicsock/debughttp.go b/wgengine/magicsock/debughttp.go index 4094c6ff5..89164f21e 100644 --- a/wgengine/magicsock/debughttp.go +++ b/wgengine/magicsock/debughttp.go @@ -9,11 +9,11 @@ "html" "io" "net/http" + "net/netip" "sort" "strings" "time" - "tailscale.com/net/netaddr" "tailscale.com/tailcfg" "tailscale.com/tstime/mono" "tailscale.com/types/key" @@ -73,7 +73,7 @@ type D struct { fmt.Fprintf(w, "

# ip:port to endpoint