mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-23 03:17:43 +00:00
all: convert more code to use net/netip directly
perl -i -npe 's,netaddr.IPPrefixFrom,netip.PrefixFrom,' $(git grep -l -F netaddr.) perl -i -npe 's,netaddr.IPPortFrom,netip.AddrPortFrom,' $(git grep -l -F netaddr. ) perl -i -npe 's,netaddr.IPPrefix,netip.Prefix,g' $(git grep -l -F netaddr. ) perl -i -npe 's,netaddr.IPPort,netip.AddrPort,g' $(git grep -l -F netaddr. ) perl -i -npe 's,netaddr.IP\b,netip.Addr,g' $(git grep -l -F netaddr. ) perl -i -npe 's,netaddr.IPv6Raw\b,netip.AddrFrom16,g' $(git grep -l -F netaddr. ) goimports -w . Then delete some stuff from the net/netaddr shim package which is no longer neeed. Updates #5162 Change-Id: Ia7a86893fe21c7e3ee1ec823e8aba288d4566cd8 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
6a396731eb
commit
a12aad6b47
@@ -7,10 +7,10 @@ package dns
|
||||
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
|
||||
}
|
||||
|
@@ -13,6 +13,7 @@ import (
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"net/netip"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -21,7 +22,6 @@ import (
|
||||
"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 @@ const (
|
||||
)
|
||||
|
||||
// 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,
|
||||
|
@@ -16,7 +16,6 @@ import (
|
||||
"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 @@ search ts.net ts-dns.test
|
||||
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"),
|
||||
},
|
||||
},
|
||||
|
@@ -11,13 +11,13 @@ import (
|
||||
"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 @@ const reconfigTimeout = time.Second
|
||||
|
||||
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,
|
||||
|
@@ -8,11 +8,11 @@ import (
|
||||
"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{
|
||||
|
@@ -13,7 +13,6 @@ import (
|
||||
"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 == "" {
|
||||
|
@@ -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 @@ func (m windowsManager) getBasePrimaryResolver() (resolvers []netaddr.IP, err er
|
||||
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"),
|
||||
|
@@ -15,7 +15,6 @@ import (
|
||||
|
||||
"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)
|
||||
|
||||
|
@@ -16,7 +16,6 @@ import (
|
||||
|
||||
"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 @@ func (m *nmManager) GetBaseConfig() (OSConfig, error) {
|
||||
|
||||
var (
|
||||
ret OSConfig
|
||||
seenResolvers = map[netaddr.IP]bool{}
|
||||
seenResolvers = map[netip.Addr]bool{}
|
||||
seenSearch = map[string]bool{}
|
||||
)
|
||||
|
||||
|
@@ -6,8 +6,8 @@ package dns
|
||||
|
||||
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.
|
||||
|
@@ -9,31 +9,29 @@ package publicdns
|
||||
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)
|
||||
|
@@ -7,8 +7,6 @@ package publicdns
|
||||
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) {
|
||||
|
@@ -20,7 +20,6 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/util/dnsname"
|
||||
)
|
||||
|
||||
@@ -30,7 +29,7 @@ const Path = "/etc/resolv.conf"
|
||||
// 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
|
||||
|
@@ -10,7 +10,6 @@ import (
|
||||
"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"),
|
||||
},
|
||||
},
|
||||
|
@@ -15,6 +15,7 @@ import (
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"sort"
|
||||
@@ -28,7 +29,6 @@ import (
|
||||
"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
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ var (
|
||||
|
||||
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 @@ var errEmptyResolvConf = errors.New("resolv.conf has no nameservers")
|
||||
|
||||
// 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
|
||||
|
@@ -7,11 +7,11 @@ package resolver
|
||||
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 @@ import (
|
||||
// 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{
|
||||
|
@@ -43,7 +43,7 @@ var (
|
||||
)
|
||||
|
||||
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" {
|
||||
|
@@ -15,6 +15,7 @@ import (
|
||||
"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 @@ const fallbackDelay = 300 * time.Millisecond
|
||||
|
||||
// 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 @@ func (dc *dialCall) raceDial(ctx context.Context, ips []netaddr.IP) (net.Conn, e
|
||||
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 @@ func (dc *dialCall) raceDial(ctx context.Context, ips []netaddr.IP) (net.Conn, e
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
@@ -14,8 +14,6 @@ import (
|
||||
"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 @@ func TestDialCall_DNSWasTrustworthy(t *testing.T) {
|
||||
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"),
|
||||
|
@@ -22,21 +22,20 @@ import (
|
||||
"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 @@ func Lookup(ctx context.Context, host string) ([]netaddr.IP, error) {
|
||||
|
||||
// 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.
|
||||
|
@@ -13,16 +13,16 @@ package flowtrack
|
||||
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 {
|
||||
|
@@ -28,7 +28,7 @@ var LoginEndpointForProxyDetermination = "https://controlplane.tailscale.com/"
|
||||
// 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 @@ var getPAC func() string
|
||||
// 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 @@ var (
|
||||
|
||||
// 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
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ import (
|
||||
"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)
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"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)
|
||||
|
@@ -11,7 +11,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"go4.org/mem"
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/util/lineread"
|
||||
"tailscale.com/version"
|
||||
)
|
||||
@@ -42,7 +41,7 @@ default link#14 UCSI utun2
|
||||
...
|
||||
|
||||
*/
|
||||
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"
|
||||
|
@@ -46,7 +46,7 @@ Iface Destination Gateway Flags RefCnt Use Metric Mask
|
||||
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 {
|
||||
|
@@ -9,8 +9,6 @@ import (
|
||||
"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"),
|
||||
},
|
||||
},
|
||||
|
@@ -7,6 +7,7 @@ package interfaces
|
||||
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()
|
||||
|
@@ -15,14 +15,8 @@ import (
|
||||
"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
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
@@ -17,7 +18,6 @@ import (
|
||||
"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 {
|
||||
|
@@ -7,15 +7,14 @@ package netstat
|
||||
|
||||
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?
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"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 {
|
||||
|
@@ -8,6 +8,7 @@ package netutil
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@@ -16,19 +17,18 @@ import (
|
||||
"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":
|
||||
|
@@ -7,8 +7,8 @@ package packet
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net/netip"
|
||||
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/types/ipproto"
|
||||
)
|
||||
|
||||
@@ -19,8 +19,8 @@ const ip4HeaderLength = 20
|
||||
type IP4Header struct {
|
||||
IPProto ipproto.Proto
|
||||
IPID uint16
|
||||
Src netaddr.IP
|
||||
Dst netaddr.IP
|
||||
Src netip.Addr
|
||||
Dst netip.Addr
|
||||
}
|
||||
|
||||
// Len implements Header.
|
||||
|
@@ -6,8 +6,8 @@ package packet
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net/netip"
|
||||
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/types/ipproto"
|
||||
)
|
||||
|
||||
@@ -18,8 +18,8 @@ const ip6HeaderLength = 40
|
||||
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.
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -10,7 +10,6 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/tstest"
|
||||
"tailscale.com/types/ipproto"
|
||||
)
|
||||
@@ -27,7 +26,7 @@ const (
|
||||
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)
|
||||
|
@@ -14,9 +14,9 @@ import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
|
||||
"tailscale.com/net/flowtrack"
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/types/ipproto"
|
||||
)
|
||||
|
||||
@@ -36,10 +36,10 @@ import (
|
||||
// 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]
|
||||
|
@@ -9,8 +9,7 @@ package portmapper
|
||||
|
||||
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
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"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
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"tailscale.com/net/netaddr"
|
||||
@@ -49,9 +50,9 @@ const (
|
||||
|
||||
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
|
||||
|
@@ -57,7 +57,7 @@ const trustServiceStillAvailableDuration = 10 * time.Minute
|
||||
// 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 @@ var (
|
||||
// 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 @@ var wildcardIP = netip.MustParseAddr("0.0.0.0")
|
||||
//
|
||||
// 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
|
||||
|
@@ -24,7 +24,6 @@ import (
|
||||
"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 @@ import (
|
||||
// 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)
|
||||
|
@@ -17,7 +17,7 @@ import (
|
||||
// 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 @@ var chromeOSRange oncePrefix
|
||||
// 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 @@ var (
|
||||
// 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 @@ var (
|
||||
)
|
||||
|
||||
// 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")
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
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()
|
||||
|
@@ -13,7 +13,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/types/netmap"
|
||||
"tailscale.com/util/dnsname"
|
||||
)
|
||||
@@ -23,7 +22,7 @@ import (
|
||||
//
|
||||
// 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
|
||||
}
|
||||
|
@@ -9,7 +9,6 @@ import (
|
||||
"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"),
|
||||
},
|
||||
},
|
||||
|
@@ -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
|
||||
|
@@ -7,6 +7,7 @@ package tstun
|
||||
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)
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/netip"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -21,7 +22,6 @@ import (
|
||||
"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()
|
||||
}
|
||||
|
@@ -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
|
||||
},
|
||||
},
|
||||
|
Reference in New Issue
Block a user