all: cleanup unused code, part 2 (#10670)

And enable U1000 check in staticcheck.

Updates #cleanup

Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
pull/10672/head
Andrew Lytvynov 4 months ago committed by GitHub
parent c9836b454d
commit 2716250ee8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -93,14 +93,6 @@ var infoMap = map[serveMode]commandInfo{
},
}
func buildShortUsage(subcmd string) string {
return strings.Join([]string{
subcmd + " [flags] <target> [off]",
subcmd + " status [--json]",
subcmd + " reset",
}, "\n ")
}
// errHelpFunc is standard error text that prompts users to
// run `$subcmd --help` for information on how to use serve.
var errHelpFunc = func(m serveMode) error {

@ -27,7 +27,6 @@ func TestServeDevConfigMutations(t *testing.T) {
command []string // serve args; nil means no command to run (only reset)
want *ipn.ServeConfig // non-nil means we want a save of this value
wantErr func(error) (badErrMsg string) // nil means no error is wanted
before func(t *testing.T)
}
// group is a group of steps that share the same
@ -1224,14 +1223,6 @@ func TestMessageForPort(t *testing.T) {
}
}
func unindent(s string) string {
lines := strings.Split(s, "\n")
for i, line := range lines {
lines[i] = strings.TrimSpace(line)
}
return strings.Join(lines, "\n")
}
func TestIsLegacyInvocation(t *testing.T) {
tests := []struct {
subcmd serveMode

@ -1044,18 +1044,6 @@ func exitNodeIP(p *ipn.Prefs, st *ipnstate.Status) (ip netip.Addr) {
return
}
func anyPeerAdvertisingRoutes(st *ipnstate.Status) bool {
for _, ps := range st.Peer {
if ps.PrimaryRoutes == nil {
continue
}
if ps.PrimaryRoutes.Len() > 0 {
return true
}
}
return false
}
func init() {
// Required to use our client API. We're fine with the instability since the
// client lives in the same repo as this code.

@ -283,7 +283,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/net/netknob from tailscale.com/net/netns+
tailscale.com/net/netmon from tailscale.com/cmd/tailscaled+
tailscale.com/net/netns from tailscale.com/derp/derphttp+
💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnauth+
W 💣 tailscale.com/net/netstat from tailscale.com/portlist
tailscale.com/net/netutil from tailscale.com/ipn/ipnlocal+
tailscale.com/net/packet from tailscale.com/net/tstun+
tailscale.com/net/packet/checksum from tailscale.com/net/tstun

@ -12,22 +12,6 @@ import (
"testing"
)
// defaultTestArgs contains the default values for all flags in the testing
// package. It is used to reset the flag values in testwrapper tests to allow
// parsing the flags again.
var defaultTestArgs map[string]string
// initDefaultTestArgs initializes defaultTestArgs.
func initDefaultTestArgs() {
if defaultTestArgs != nil {
return
}
defaultTestArgs = make(map[string]string)
flag.CommandLine.VisitAll(func(f *flag.Flag) {
defaultTestArgs[f.Name] = f.DefValue
})
}
// registerTestFlags registers all flags from the testing package with the
// provided flag set. It does so by calling testing.Init() and then iterating
// over all flags registered on flag.CommandLine.

@ -83,26 +83,6 @@ func fixEsbuildMetadataPaths(metadataStr string) ([]byte, error) {
return json.Marshal(metadata)
}
func cleanDist() error {
log.Printf("Cleaning %s...\n", *distDir)
files, err := os.ReadDir(*distDir)
if err != nil {
if os.IsNotExist(err) {
return os.MkdirAll(*distDir, 0755)
}
return err
}
for _, file := range files {
if file.Name() != "placeholder" {
if err := os.Remove(filepath.Join(*distDir, file.Name())); err != nil {
return err
}
}
}
return nil
}
func precompressDist(fastCompression bool) error {
log.Printf("Pre-compressing files in %s/...\n", *distDir)
return precompress.PrecompressDir(*distDir, precompress.Options{

@ -7,7 +7,6 @@ import (
"bufio"
"bytes"
"context"
"crypto/rand"
"encoding/binary"
"fmt"
"io"
@ -302,32 +301,6 @@ func TestConnMemoryOverhead(t *testing.T) {
}
}
// mkConns creates synthetic Noise Conns wrapping the given net.Conns.
// This function is for testing just the Conn transport logic without
// having to muck about with Noise handshakes.
func mkConns(s1, s2 net.Conn) (*Conn, *Conn) {
var k1, k2 [chp.KeySize]byte
if _, err := rand.Read(k1[:]); err != nil {
panic(err)
}
if _, err := rand.Read(k2[:]); err != nil {
panic(err)
}
ret1 := &Conn{
conn: s1,
tx: txState{cipher: newCHP(k1)},
rx: rxState{cipher: newCHP(k2)},
}
ret2 := &Conn{
conn: s2,
tx: txState{cipher: newCHP(k2)},
rx: rxState{cipher: newCHP(k1)},
}
return ret1, ret2
}
type readSink struct {
r io.Reader

@ -32,7 +32,6 @@ import (
"encoding/binary"
"hash"
"io"
"math"
"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/chacha20poly1305"
@ -105,10 +104,6 @@ var minNonce = uint32(0)
* UTILITY FUNCTIONS *
* ---------------------------------------------------------------- */
func getPublicKey(kp *keypair) [32]byte {
return kp.public_key
}
func isEmptyKey(k [32]byte) bool {
return subtle.ConstantTimeCompare(k[:], emptyKey[:]) == 1
}
@ -162,12 +157,6 @@ func generateKeypair() keypair {
return generateKeypair()
}
func generatePublicKey(private_key [32]byte) [32]byte {
var public_key [32]byte
curve25519.ScalarBaseMult(&public_key, &private_key)
return public_key
}
func encrypt(k [32]byte, n uint32, ad []byte, plaintext []byte) []byte {
var nonce [12]byte
var ciphertext []byte
@ -246,12 +235,6 @@ func decryptWithAd(cs *cipherstate, ad []byte, ciphertext []byte) (*cipherstate,
return cs, plaintext, valid
}
func reKey(cs *cipherstate) *cipherstate {
e := encrypt(cs.k, math.MaxUint32, []byte{}, emptyKey[:])
copy(cs.k[:], e)
return cs
}
/* SymmetricState */
func initializeSymmetric(protocolName []byte) symmetricstate {
@ -273,19 +256,6 @@ func mixHash(ss *symmetricstate, data []byte) *symmetricstate {
return ss
}
func mixKeyAndHash(ss *symmetricstate, ikm [32]byte) *symmetricstate {
var tempH [32]byte
var tempK [32]byte
ss.ck, tempH, tempK = getHkdf(ss.ck, ikm[:])
ss = mixHash(ss, tempH[:])
ss.cs = initializeKey(tempK)
return ss
}
func getHandshakeHash(ss *symmetricstate) [32]byte {
return ss.h
}
func encryptAndHash(ss *symmetricstate, plaintext []byte) (*symmetricstate, []byte) {
var ciphertext []byte
if hasKey(&ss.cs) {
@ -471,5 +441,3 @@ func RecvMessage(session *noisesession, message *messagebuffer) (*noisesession,
session.mc = session.mc + 1
return session, plaintext, valid
}
func main() {}

@ -252,14 +252,6 @@ func (c *Auto) updateControl() {
}
}
// cancelAuthCtx cancels the existing auth goroutine's context
// & creates a new one, causing it to restart.
func (c *Auto) cancelAuthCtx() {
c.mu.Lock()
defer c.mu.Unlock()
c.cancelAuthCtxLocked()
}
// cancelAuthCtxLocked is like cancelAuthCtx, but assumes the caller holds c.mu.
func (c *Auto) cancelAuthCtxLocked() {
if c.authCancel != nil {
@ -271,14 +263,6 @@ func (c *Auto) cancelAuthCtxLocked() {
}
}
// cancelMapCtx cancels the context for the existing mapPoll and liteUpdates
// goroutines and creates a new one, causing them to restart.
func (c *Auto) cancelMapCtx() {
c.mu.Lock()
defer c.mu.Unlock()
c.cancelMapCtxLocked()
}
// cancelMapCtxLocked is like cancelMapCtx, but assumes the caller holds c.mu.
func (c *Auto) cancelMapCtxLocked() {
if c.mapCancel != nil {

@ -8,7 +8,6 @@ import (
"encoding/json"
"fmt"
"net"
"net/netip"
"reflect"
"slices"
"sort"
@ -86,7 +85,6 @@ type mapSession struct {
lastDomainAuditLogID string
lastHealth []string
lastPopBrowserURL string
stickyDebug tailcfg.Debug // accumulated opt.Bool values
lastTKAInfo *tailcfg.TKAInfo
lastNetmapSummary string // from NetworkMap.VeryConcise
}
@ -790,43 +788,3 @@ func (ms *mapSession) netmap() *netmap.NetworkMap {
}
return nm
}
func nodesSorted(v []*tailcfg.Node) bool {
for i, n := range v {
if i > 0 && n.ID <= v[i-1].ID {
return false
}
}
return true
}
func sortNodes(v []*tailcfg.Node) {
sort.Slice(v, func(i, j int) bool { return v[i].ID < v[j].ID })
}
func cloneNodes(v1 []*tailcfg.Node) []*tailcfg.Node {
if v1 == nil {
return nil
}
v2 := make([]*tailcfg.Node, len(v1))
for i, n := range v1 {
v2[i] = n.Clone()
}
return v2
}
var debugSelfIPv6Only = envknob.RegisterBool("TS_DEBUG_SELF_V6_ONLY")
func filterSelfAddresses(in []netip.Prefix) (ret []netip.Prefix) {
switch {
default:
return in
case debugSelfIPv6Only():
for _, a := range in {
if a.Addr().Is6() {
ret = append(ret, a)
}
}
return ret
}
}

@ -753,12 +753,6 @@ func (s *Server) debugLogf(format string, v ...any) {
}
}
// for testing
var (
timeSleep = time.Sleep
timeNow = time.Now
)
// run serves the client until there's an error.
// If the client hangs up or the server is closed, run returns nil, otherwise run returns an error.
func (c *sclient) run(ctx context.Context) error {

@ -1,9 +1,9 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Package webhooks provides example consumer code for Tailscale
// Command webhooks provides example consumer code for Tailscale
// webhooks.
package webhooks
package main
import (
"crypto/hmac"

@ -26,6 +26,7 @@ func (Check) Run(_ context.Context, logf logger.Logf) error {
return permissionsImpl(logf)
}
//lint:ignore U1000 used in non-windows implementations.
func formatUserID[T constraints.Integer](id T) string {
idStr := fmt.Sprint(id)
if uu, err := user.LookupId(idStr); err != nil {
@ -35,6 +36,7 @@ func formatUserID[T constraints.Integer](id T) string {
}
}
//lint:ignore U1000 used in non-windows implementations.
func formatGroupID[T constraints.Integer](id T) string {
idStr := fmt.Sprint(id)
if g, err := user.LookupGroupId(idStr); err != nil {
@ -44,6 +46,7 @@ func formatGroupID[T constraints.Integer](id T) string {
}
}
//lint:ignore U1000 used in non-windows implementations.
func formatGroups[T constraints.Integer](groups []T) string {
var buf strings.Builder
for i, group := range groups {

@ -9,7 +9,6 @@ import (
"fmt"
"io"
"net"
"net/netip"
"os"
"os/user"
"runtime"
@ -18,7 +17,6 @@ import (
"inet.af/peercred"
"tailscale.com/envknob"
"tailscale.com/ipn"
"tailscale.com/net/netstat"
"tailscale.com/safesocket"
"tailscale.com/types/logger"
"tailscale.com/util/clientmetric"
@ -207,12 +205,3 @@ func isLocalAdmin(uid string) (bool, error) {
}
return groupmember.IsMemberOfGroup(adminGroup, u.Username)
}
func peerPid(entries []netstat.Entry, la, ra netip.AddrPort) int {
for _, e := range entries {
if e.Local == ra && e.Remote == la {
return e.Pid
}
}
return 0
}

@ -20,7 +20,7 @@ import (
// based on the user who owns the other end of the connection.
// If c is not backed by a named pipe, an error is returned.
func GetConnIdentity(logf logger.Logf, c net.Conn) (ci *ConnIdentity, err error) {
ci = &ConnIdentity{conn: c}
ci = &ConnIdentity{conn: c, notWindows: false}
wcc, ok := c.(*safesocket.WindowsClientConn)
if !ok {
return nil, fmt.Errorf("not a WindowsClientConn: %T", c)

@ -5324,15 +5324,6 @@ func (b *LocalBackend) DoNoiseRequest(req *http.Request) (*http.Response, error)
return cc.DoNoiseRequest(req)
}
// tailscaleSSHEnabled reports whether Tailscale SSH is currently enabled based
// on prefs. It returns false if there are no prefs set.
func (b *LocalBackend) tailscaleSSHEnabled() bool {
b.mu.Lock()
defer b.mu.Unlock()
p := b.pm.CurrentPrefs()
return p.Valid() && p.RunSSH()
}
func (b *LocalBackend) sshServerOrInit() (_ SSHServer, err error) {
b.mu.Lock()
defer b.mu.Unlock()

@ -62,10 +62,6 @@ type peerAPIServer struct {
taildrop *taildrop.Manager
}
var (
errNilPeerAPIServer = errors.New("peerapi unavailable; not listening")
)
func (s *peerAPIServer) listen(ip netip.Addr, ifState *interfaces.State) (ln net.Listener, err error) {
// Android for whatever reason often has problems creating the peerapi listener.
// But since we started intercepting it with netstack, it's not even important that

@ -114,7 +114,6 @@ func hexAll(v string) string {
}
func TestHandlePeerAPI(t *testing.T) {
const nodeFQDN = "self-node.tail-scale.ts.net."
tests := []struct {
name string
isSelf bool // the peer sending the request is owned by us

@ -217,3 +217,12 @@ func (b *LocalBackend) getSSHHostKeyPublicStrings() (ret []string) {
}
return ret
}
// tailscaleSSHEnabled reports whether Tailscale SSH is currently enabled based
// on prefs. It returns false if there are no prefs set.
func (b *LocalBackend) tailscaleSSHEnabled() bool {
b.mu.Lock()
defer b.mu.Unlock()
p := b.pm.CurrentPrefs()
return p.Valid() && p.RunSSH()
}

@ -240,15 +240,6 @@ func (t *strideTable[T]) tableDebugString() string {
return ret.String()
}
// treeDebugString returns the contents of t, formatted as a sparse tree. Each
// line is one entry, indented such that it is contained by all its parents, and
// non-overlapping with any of its siblings.
func (t *strideTable[T]) treeDebugString() string {
var ret bytes.Buffer
t.treeDebugStringRec(&ret, 1, 0) // index of 0/0, and 0 indent
return ret.String()
}
func (t *strideTable[T]) treeDebugStringRec(w io.Writer, idx, indent int) {
addr, len := inversePrefixIndex(idx)
if t.hasPrefixRootedAt(idx) {

@ -348,12 +348,6 @@ func (t *slowTable[T]) String() string {
return ret.String()
}
func (t *slowTable[T]) insert(addr uint8, prefixLen int, val T) {
t.delete(addr, prefixLen) // no-op if prefix doesn't exist
t.prefixes = append(t.prefixes, slowEntry[T]{addr, prefixLen, val})
}
func (t *slowTable[T]) delete(addr uint8, prefixLen int) {
pfx := make([]slowEntry[T], 0, len(t.prefixes))
for _, e := range t.prefixes {

@ -968,8 +968,6 @@ func BenchmarkTableDelete(b *testing.B) {
})
}
var addrSink netip.Addr
func BenchmarkTableGet(b *testing.B) {
forFamilyAndCount(b, func(b *testing.B, routes []slowPrefixEntry[int]) {
genAddr := randomAddr4
@ -1106,18 +1104,6 @@ type slowPrefixEntry[T any] struct {
val T
}
func (t *slowPrefixTable[T]) delete(pfx netip.Prefix) {
pfx = pfx.Masked()
ret := make([]slowPrefixEntry[T], 0, len(t.prefixes))
for _, ent := range t.prefixes {
if ent.pfx == pfx {
continue
}
ret = append(ret, ent)
}
t.prefixes = ret
}
func (t *slowPrefixTable[T]) insert(pfx netip.Prefix, val T) {
pfx = pfx.Masked()
for i, ent := range t.prefixes {
@ -1230,26 +1216,3 @@ func roundFloat64(f float64) float64 {
}
return ret
}
func minimize(pfxs []slowPrefixEntry[int], f func(skip map[netip.Prefix]bool) error) (map[netip.Prefix]bool, error) {
if f(nil) == nil {
return nil, nil
}
remove := map[netip.Prefix]bool{}
for lastLen := -1; len(remove) != lastLen; lastLen = len(remove) {
fmt.Println("len is ", len(remove))
for i, pfx := range pfxs {
if remove[pfx.pfx] {
continue
}
remove[pfx.pfx] = true
fmt.Printf("%d %d: trying without %s\n", i, len(remove), pfx.pfx)
if f(remove) == nil {
delete(remove, pfx.pfx)
}
}
}
return remove, f(remove)
}

@ -20,7 +20,6 @@ import (
"sync"
"time"
"tailscale.com/health"
"tailscale.com/net/dns/resolvconffile"
"tailscale.com/types/logger"
"tailscale.com/util/dnsname"
@ -50,6 +49,8 @@ func readResolv(r io.Reader) (OSConfig, error) {
// resolvOwner returns the apparent owner of the resolv.conf
// configuration in bs - one of "resolvconf", "systemd-resolved" or
// "NetworkManager", or "" if no known owner was found.
//
//lint:ignore U1000 used in linux and freebsd code
func resolvOwner(bs []byte) string {
likely := ""
b := bytes.NewBuffer(bs)
@ -130,11 +131,13 @@ type directManager struct {
ctx context.Context // valid until Close
ctxClose context.CancelFunc // closes ctx
mu sync.Mutex
wantResolvConf []byte // if non-nil, what we expect /etc/resolv.conf to contain
mu sync.Mutex
wantResolvConf []byte // if non-nil, what we expect /etc/resolv.conf to contain
//lint:ignore U1000 used in direct_linux.go
lastWarnContents []byte // last resolv.conf contents that we warned about
}
//lint:ignore U1000 used in manager_{freebsd,openbsd}.go
func newDirectManager(logf logger.Logf) *directManager {
return newDirectManagerOnFS(logf, directFS{})
}
@ -288,52 +291,6 @@ func (m *directManager) setWant(want []byte) {
m.wantResolvConf = want
}
var warnTrample = health.NewWarnable()
// checkForFileTrample checks whether /etc/resolv.conf has been trampled
// by another program on the system. (e.g. a DHCP client)
func (m *directManager) checkForFileTrample() {
m.mu.Lock()
want := m.wantResolvConf
lastWarn := m.lastWarnContents
m.mu.Unlock()
if want == nil {
return
}
cur, err := m.fs.ReadFile(resolvConf)
if err != nil {
m.logf("trample: read error: %v", err)
return
}
if bytes.Equal(cur, want) {
warnTrample.Set(nil)
if lastWarn != nil {
m.mu.Lock()
m.lastWarnContents = nil
m.mu.Unlock()
m.logf("trample: resolv.conf again matches expected content")
}
return
}
if bytes.Equal(cur, lastWarn) {
// We already logged about this, so not worth doing it again.
return
}
m.mu.Lock()
m.lastWarnContents = cur
m.mu.Unlock()
show := cur
if len(show) > 1024 {
show = show[:1024]
}
m.logf("trample: resolv.conf changed from what we expected. did some other program interfere? current contents: %q", show)
warnTrample.Set(errors.New("Linux DNS config not ideal. /etc/resolv.conf overwritten. See https://tailscale.com/s/dns-fight"))
}
func (m *directManager) SetDNS(config OSConfig) (err error) {
defer func() {
if err != nil && errors.Is(err, fs.ErrPermission) && runtime.GOOS == "linux" &&

@ -4,9 +4,12 @@
package dns
import (
"bytes"
"context"
"errors"
"github.com/illarion/gonotify"
"tailscale.com/health"
)
func (m *directManager) runFileWatcher() {
@ -55,6 +58,52 @@ func (m *directManager) runFileWatcher() {
}
}
var warnTrample = health.NewWarnable()
// checkForFileTrample checks whether /etc/resolv.conf has been trampled
// by another program on the system. (e.g. a DHCP client)
func (m *directManager) checkForFileTrample() {
m.mu.Lock()
want := m.wantResolvConf
lastWarn := m.lastWarnContents
m.mu.Unlock()
if want == nil {
return
}
cur, err := m.fs.ReadFile(resolvConf)
if err != nil {
m.logf("trample: read error: %v", err)
return
}
if bytes.Equal(cur, want) {
warnTrample.Set(nil)
if lastWarn != nil {
m.mu.Lock()
m.lastWarnContents = nil
m.mu.Unlock()
m.logf("trample: resolv.conf again matches expected content")
}
return
}
if bytes.Equal(cur, lastWarn) {
// We already logged about this, so not worth doing it again.
return
}
m.mu.Lock()
m.lastWarnContents = cur
m.mu.Unlock()
show := cur
if len(show) > 1024 {
show = show[:1024]
}
m.logf("trample: resolv.conf changed from what we expected. did some other program interfere? current contents: %q", show)
warnTrample.Set(errors.New("Linux DNS config not ideal. /etc/resolv.conf overwritten. See https://tailscale.com/s/dns-fight"))
}
func (m *directManager) closeInotifyOnDone(ctx context.Context, in *gonotify.Inotify) {
<-ctx.Done()
in.Close()

@ -40,18 +40,6 @@ const maxActiveQueries = 256
// the lint exception is necessary and on others it is not,
// and plain ignore complains if the exception is unnecessary.
// reconfigTimeout is the time interval within which Manager.{Up,Down} should complete.
//
// This is particularly useful because certain conditions can cause indefinite hangs
// (such as improper dbus auth followed by contextless dbus.Object.Call).
// Such operations should be wrapped in a timeout context.
const reconfigTimeout = time.Second
type response struct {
pkt []byte
to netip.AddrPort // response destination (request source)
}
// Manager manages system DNS settings.
type Manager struct {
logf logger.Logf

@ -69,13 +69,12 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (ret OSConfigurat
// newOSConfigEnv are the funcs newOSConfigurator needs, pulled out for testing.
type newOSConfigEnv struct {
fs wholeFileFS
dbusPing func(string, string) error
dbusReadString func(string, string, string, string) (string, error)
nmIsUsingResolved func() error
nmVersionBetween func(v1, v2 string) (safe bool, err error)
resolvconfStyle func() string
isResolvconfDebianVersion func() bool
fs wholeFileFS
dbusPing func(string, string) error
dbusReadString func(string, string, string, string) (string, error)
nmIsUsingResolved func() error
nmVersionBetween func(v1, v2 string) (safe bool, err error)
resolvconfStyle func() string
}
func dnsMode(logf logger.Logf, env newOSConfigEnv) (ret string, err error) {

@ -636,13 +636,6 @@ func mustIPs(strs ...string) (ret []netip.Addr) {
return ret
}
func mustIPPs(strs ...string) (ret []netip.AddrPort) {
for _, s := range strs {
ret = append(ret, netip.MustParseAddrPort(s))
}
return ret
}
func mustRes(strs ...string) (ret []*dnstype.Resolver) {
for _, s := range strs {
ret = append(ret, &dnstype.Resolver{Addr: s})
@ -681,26 +674,6 @@ func hosts(strs ...string) (ret map[dnsname.FQDN][]netip.Addr) {
return ret
}
func hostsR(strs ...string) (ret map[dnsname.FQDN][]dnstype.Resolver) {
var key dnsname.FQDN
ret = map[dnsname.FQDN][]dnstype.Resolver{}
for _, s := range strs {
if ip, err := netip.ParseAddr(s); err == nil {
if key == "" {
panic("IP provided before name")
}
ret[key] = append(ret[key], dnstype.Resolver{Addr: ip.String()})
} else {
fqdn, err := dnsname.ToFQDN(s)
if err != nil {
panic(err)
}
key = fqdn
}
}
return ret
}
func upstreams(strs ...string) (ret map[dnsname.FQDN][]*dnstype.Resolver) {
var key dnsname.FQDN
ret = map[dnsname.FQDN][]*dnstype.Resolver{}

@ -25,6 +25,13 @@ const (
lowerPriority = int32(200) // lower than all builtin auto priorities
)
// reconfigTimeout is the time interval within which Manager.{Up,Down} should complete.
//
// This is particularly useful because certain conditions can cause indefinite hangs
// (such as improper dbus auth followed by contextless dbus.Object.Call).
// Such operations should be wrapped in a timeout context.
const reconfigTimeout = time.Second
// nmManager uses the NetworkManager DBus API.
type nmManager struct {
interfaceName string

@ -163,13 +163,6 @@ func (r *Resolver) logf(format string, args ...any) {
r.Logf(format, args...)
}
func (r *Resolver) dlogf(format string, args ...any) {
if r.Logf == nil || !debug() {
return
}
r.Logf(format, args...)
}
func (r *Resolver) depthlogf(depth int, format string, args ...any) {
if r.Logf == nil || !debug() {
return

@ -7,7 +7,6 @@ package dns
import (
"context"
"errors"
"fmt"
"net"
"strings"
@ -17,32 +16,10 @@ import (
"golang.org/x/sys/unix"
"tailscale.com/health"
"tailscale.com/logtail/backoff"
"tailscale.com/net/netaddr"
"tailscale.com/types/logger"
"tailscale.com/util/dnsname"
)
// resolvedListenAddr is the listen address of the resolved stub resolver.
//
// We only consider resolved to be the system resolver if the stub resolver is;
// that is, if this address is the sole nameserver in /etc/resolved.conf.
// In other cases, resolved may be managing the system DNS configuration directly.
// Then the nameserver list will be a concatenation of those for all
// the interfaces that register their interest in being a default resolver with
//
// SetLinkDomains([]{{"~.", true}, ...})
//
// which includes at least the interface with the default route, i.e. not us.
// This does not work for us: there is a possibility of getting NXDOMAIN
// from the other nameservers before we are asked or get a chance to respond.
// We consider this case as lacking resolved support and fall through to dnsDirect.
//
// While it may seem that we need to read a config option to get at this,
// this address is, in fact, hard-coded into resolved.
var resolvedListenAddr = netaddr.IPv4(127, 0, 0, 53)
var errNotReady = errors.New("interface not ready")
// DBus entities we talk to.
//
// DBus is an RPC bus. In particular, the bus we're talking to is the

@ -189,8 +189,6 @@ type Resolver struct {
// closed signals all goroutines to stop.
closed chan struct{}
// wg signals when all goroutines have stopped.
wg sync.WaitGroup
// mu guards the following fields from being updated while used.
mu sync.Mutex
@ -609,6 +607,7 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netip.Addr,
}
}
// Not authoritative, signal that forwarding is advisable.
metricDNSResolveLocalErrorRefused.Add(1)
return netip.Addr{}, dns.RCodeRefused
}
@ -1248,6 +1247,7 @@ func (r *Resolver) respond(query []byte) ([]byte, error) {
resp := parser.response()
resp.Header.RCode = rcode
resp.IP = ip
metricDNSMagicDNSSuccessName.Add(1)
return marshalResponse(resp)
}
@ -1305,9 +1305,8 @@ var (
metricDNSFwdErrorContext = clientmetric.NewCounter("dns_query_fwd_error_context")
metricDNSFwdErrorContextGotError = clientmetric.NewCounter("dns_query_fwd_error_context_got_error")
metricDNSFwdErrorType = clientmetric.NewCounter("dns_query_fwd_error_type")
metricDNSFwdErrorParseAddr = clientmetric.NewCounter("dns_query_fwd_error_parse_addr")
metricDNSFwdTruncated = clientmetric.NewCounter("dns_query_fwd_truncated")
metricDNSFwdErrorType = clientmetric.NewCounter("dns_query_fwd_error_type")
metricDNSFwdTruncated = clientmetric.NewCounter("dns_query_fwd_truncated")
metricDNSFwdUDP = clientmetric.NewCounter("dns_query_fwd_udp") // on entry
metricDNSFwdUDPWrote = clientmetric.NewCounter("dns_query_fwd_udp_wrote") // sent UDP packet

@ -37,8 +37,6 @@ var (
testipv4Arpa = dnsname.FQDN("4.3.2.1.in-addr.arpa.")
testipv6Arpa = dnsname.FQDN("f.0.e.0.d.0.c.0.b.0.a.0.9.0.8.0.7.0.6.0.5.0.4.0.3.0.2.0.1.0.0.0.ip6.arpa.")
magicDNSv4Port = netip.MustParseAddrPort("100.100.100.100:53")
)
var dnsCfg = Config{

@ -656,8 +656,6 @@ func v6addrs(aa []netip.Addr) (ret []netip.Addr) {
return ret
}
var errTLSHandshakeTimeout = errors.New("timeout doing TLS handshake")
// TLSDialer is like Dialer but returns a func suitable for using with net/http.Transport.DialTLSContext.
// It returns a *tls.Conn type on success.
// On TLS cert validation failure, it can invoke a backup DNS resolution strategy.

@ -220,13 +220,6 @@ func (m *Monitor) RegisterRuleDeleteCallback(callback RuleDeleteCallback) (unreg
}
}
// isActive reports whether this monitor has been started and not yet closed.
func (m *Monitor) isActive() bool {
m.mu.Lock()
defer m.mu.Unlock()
return m.started && !m.closed
}
// Start starts the monitor.
// A monitor can only be started & closed once.
func (m *Monitor) Start() {

@ -181,3 +181,10 @@ func (m *winMon) somethingChanged(evt string) {
return
}
}
// isActive reports whether this monitor has been started and not yet closed.
func (m *Monitor) isActive() bool {
m.mu.Lock()
defer m.mu.Unlock()
return m.started && !m.closed
}

@ -53,12 +53,6 @@ func (ln *oneConnListener) Close() error {
return nil
}
type dummyListener struct{}
func (dummyListener) Close() error { return nil }
func (dummyListener) Addr() net.Addr { return dummyAddr("unused-address") }
func (dummyListener) Accept() (c net.Conn, err error) { return nil, io.EOF }
type dummyAddr string
func (a dummyAddr) Network() string { return string(a) }

@ -15,6 +15,7 @@ import (
)
var (
//lint:ignore U1000 used in routetable_linux_test.go and routetable_bsd_test.go
defaultRouteIPv4 = RouteDestination{Prefix: netip.PrefixFrom(netip.IPv4Unspecified(), 0)}
//lint:ignore U1000 used in routetable_bsd_test.go
defaultRouteIPv6 = RouteDestination{Prefix: netip.PrefixFrom(netip.IPv6Unspecified(), 0)}

@ -99,8 +99,9 @@ type Wrapper struct {
lastActivityAtomic mono.Time // time of last send or receive
destIPActivity syncs.AtomicValue[map[netip.Addr]func()]
destMACAtomic syncs.AtomicValue[[6]byte]
discoKey syncs.AtomicValue[key.DiscoPublic]
//lint:ignore U1000 used in tap_linux.go
destMACAtomic syncs.AtomicValue[[6]byte]
discoKey syncs.AtomicValue[key.DiscoPublic]
// timeNow, if non-nil, will be used to obtain the current time.
timeNow func() time.Time

@ -55,8 +55,6 @@ func isLoopbackAddr(s mem.RO) bool {
mem.HasPrefix(s, mem.S("::1."))
}
type nothing struct{}
// appendParsePortsNetstat appends to base listening ports
// from "netstat" output, read from br. See TestParsePortsNetstat
// for example input lines.

@ -10,7 +10,6 @@ import (
"fmt"
"net"
"runtime"
"syscall"
"time"
"github.com/tailscale/go-winio"
@ -26,13 +25,6 @@ func connect(path string) (net.Conn, error) {
return winio.DialPipeAccessImpLevel(ctx, path, windows.GENERIC_READ|windows.GENERIC_WRITE, winio.PipeImpLevelIdentification)
}
func setFlags(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
syscall.SetsockoptInt(syscall.Handle(fd), syscall.SOL_SOCKET,
syscall.SO_REUSEADDR, 1)
})
}
// windowsSDDL is the Security Descriptor set on the namedpipe.
// It provides read/write access to all users and the local system.
// It is a var for testing, do not change this value.

@ -14,4 +14,5 @@ checks = [
"QF1004", # Use `strings.ReplaceAll` instead of `strings.Replace` with `n == 1`
"QF1006", # Lift if+break into loop condition
"U1000", # catch unused code
]

@ -1,6 +1,8 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !windows && !plan9
package vms
import (

@ -1,6 +1,8 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build linux
package linuxfw
import (

@ -5,7 +5,7 @@
// support in upstream dependencies.
// TODO(#8502): add support for more architectures
//go:build !linux || (linux && !(arm64 || amd64))
//go:build linux && !(arm64 || amd64)
package linuxfw

@ -112,6 +112,7 @@ const (
type _RM_APP_STATUS uint32
const (
//lint:ignore U1000 maps to a win32 API
_RmStatusUnknown _RM_APP_STATUS = 0x0
_RmStatusRunning _RM_APP_STATUS = 0x1
_RmStatusStopped _RM_APP_STATUS = 0x2

@ -12,11 +12,9 @@ import (
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"testing"
"time"
)
// The code in this file is adapted from internal/testenv in the Go source tree
@ -52,15 +50,6 @@ func pathToTestProg(t *testing.T, binary string) string {
return exe
}
func runTestProg(t *testing.T, binary, name string, env ...string) string {
exe, err := buildTestProg(t, binary, "-buildvcs=false")
if err != nil {
t.Fatal(err)
}
return runBuiltTestProg(t, exe, name, env...)
}
func startTestProg(t *testing.T, binary, name string, env ...string) {
exe, err := buildTestProg(t, binary, "-buildvcs=false")
if err != nil {
@ -70,16 +59,6 @@ func startTestProg(t *testing.T, binary, name string, env ...string) {
startBuiltTestProg(t, exe, name, env...)
}
func runBuiltTestProg(t *testing.T, exe, name string, env ...string) string {
cmd := exec.Command(exe, name)
cmd.Env = append(cmd.Env, env...)
if testing.Short() {
cmd.Env = append(cmd.Env, "RUNTIME_TEST_SHORT=1")
}
out, _ := runWithTimeout(t, cmd)
return string(out)
}
func startBuiltTestProg(t *testing.T, exe, name string, env ...string) {
cmd := exec.Command(exe, name)
cmd.Env = append(cmd.Env, env...)
@ -276,20 +255,6 @@ func mustHaveGoBuild(t testing.TB) {
}
}
// hasGoRun reports whether the current system can run programs with “go run.”
func hasGoRun() bool {
// For now, having go run and having go build are the same.
return hasGoBuild()
}
// mustHaveGoRun checks that the current system can run programs with “go run.”
// If not, mustHaveGoRun calls t.Skip with an explanation.
func mustHaveGoRun(t testing.TB) {
if !hasGoRun() {
t.Skipf("skipping test: 'go run' not available on %s/%s", runtime.GOOS, runtime.GOARCH)
}
}
var (
gorootOnce sync.Once
gorootPath string
@ -366,57 +331,6 @@ func findGOROOT() (string, error) {
return gorootPath, gorootErr
}
// runWithTimeout runs cmd and returns its combined output. If the
// subprocess exits with a non-zero status, it will log that status
// and return a non-nil error, but this is not considered fatal.
func runWithTimeout(t testing.TB, cmd *exec.Cmd) ([]byte, error) {
args := cmd.Args
if args == nil {
args = []string{cmd.Path}
}
var b bytes.Buffer
cmd.Stdout = &b
cmd.Stderr = &b
if err := cmd.Start(); err != nil {
t.Fatalf("starting %s: %v", args, err)
}
// If the process doesn't complete within 1 minute,
// assume it is hanging and kill it to get a stack trace.
p := cmd.Process
done := make(chan bool)
go func() {
scale := 2
if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" {
if sc, err := strconv.Atoi(s); err == nil {
scale = sc
}
}
select {
case <-done:
case <-time.After(time.Duration(scale) * time.Minute):
p.Signal(os.Kill)
// If SIGQUIT doesn't do it after a little
// while, kill the process.
select {
case <-done:
case <-time.After(time.Duration(scale) * 30 * time.Second):
p.Signal(os.Kill)
}
}
}()
err := cmd.Wait()
if err != nil {
t.Logf("%s exit status: %v", args, err)
}
close(done)
return b.Bytes(), err
}
// start runs cmd asynchronously and returns immediately.
func start(t testing.TB, cmd *exec.Cmd) {
args := cmd.Args

@ -382,26 +382,6 @@ func CreateAppMutex(name string) (windows.Handle, error) {
return windows.CreateMutex(nil, false, windows.StringToUTF16Ptr(name))
}
// getTokenInfoVariableLen obtains variable-length token information. Use
// this function for information classes that output variable-length data.
func getTokenInfoVariableLen[T any](token windows.Token, infoClass uint32) (*T, error) {
var buf []byte
var desiredLen uint32
err := windows.GetTokenInformation(token, infoClass, nil, 0, &desiredLen)
for err == windows.ERROR_INSUFFICIENT_BUFFER {
buf = make([]byte, desiredLen)
err = windows.GetTokenInformation(token, infoClass, unsafe.SliceData(buf), desiredLen, &desiredLen)
}
if err != nil {
return nil, err
}
return (*T)(unsafe.Pointer(unsafe.SliceData(buf))), nil
}
// getTokenInfoFixedLen obtains known fixed-length token information. Use this
// function for information classes that output enumerations, BOOLs, integers etc.
func getTokenInfoFixedLen[T any](token windows.Token, infoClass uint32) (result T, err error) {

@ -53,8 +53,12 @@ var (
// discovery on UDP connections between peers. Currently (2023-09-05)
// this only turns on the don't fragment bit for the magicsock UDP
// sockets.
//
//lint:ignore U1000 used on Linux/Darwin only
debugEnablePMTUD = envknob.RegisterOptBool("TS_DEBUG_ENABLE_PMTUD")
// debugPMTUD prints extra debugging about peer MTU path discovery.
//
//lint:ignore U1000 used on Linux/Darwin only
debugPMTUD = envknob.RegisterBool("TS_DEBUG_PMTUD")
// Hey you! Adding a new debugknob? Make sure to stub it out in the
// debugknobs_stubs.go file too.

@ -169,6 +169,8 @@ type Conn struct {
port atomic.Uint32
// peerMTUEnabled is whether path MTU discovery to peers is enabled.
//
//lint:ignore U1000 used on Linux/Darwin only
peerMTUEnabled atomic.Bool
// stats maintains per-connection counters.
@ -2933,7 +2935,9 @@ var (
metricDERPHomeChange = clientmetric.NewCounter("derp_home_change")
// Disco packets received bpf read path
//lint:ignore U1000 used on Linux only
metricRecvDiscoPacketIPv4 = clientmetric.NewCounter("magicsock_disco_recv_bpf_ipv4")
//lint:ignore U1000 used on Linux only
metricRecvDiscoPacketIPv6 = clientmetric.NewCounter("magicsock_disco_recv_bpf_ipv6")
// metricMaxPeerMTUProbed is the largest peer path MTU we successfully probed.

@ -5,31 +5,6 @@
package magicsock
import (
"errors"
)
// setDontFragment sets the don't fragment sockopt on the underlying connection
// specified by network, which must be "udp4" or "udp6". See
// https://datatracker.ietf.org/doc/html/rfc3542#section-11.2 for details on
// IPv6 fragmentation.
//
// Return values:
// - an error if peer MTU is not supported on this OS
// - errNoActiveUDP if the underlying connection is not UDP
// - otherwise, the result of setting the don't fragment bit
func (c *Conn) setDontFragment(network string, enable bool) error {
return errors.New("peer path MTU discovery not supported on this OS")
}
// getDontFragment gets the don't fragment setting on the underlying connection
// specified by network, which must be "udp4" or "udp6". Returns true if the
// underlying connection is UDP and the don't fragment bit is set, otherwise
// false.
func (c *Conn) getDontFragment(network string) (bool, error) {
return false, nil
}
func (c *Conn) DontFragSetting() (bool, error) {
return false, nil
}

@ -9,7 +9,6 @@ import (
"errors"
"fmt"
"log"
"net"
"net/netip"
"slices"
"sort"
@ -28,8 +27,6 @@ import (
"tailscale.com/wgengine/winnet"
)
var wintunLinkLocal = netip.MustParseAddr("fe80::99d0:ec2d:b2e7:536b")
// monitorDefaultRoutes subscribes to route change events and updates
// the Tailscale tunnel interface's MTU to match that of the
// underlying default route.
@ -470,21 +467,6 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
return errAcc
}
// unwrapIP returns the shortest version of ip.
func unwrapIP(ip net.IP) net.IP {
if ip4 := ip.To4(); ip4 != nil {
return ip4
}
return ip
}
func v4Mask(m net.IPMask) net.IPMask {
if len(m) == 16 {
return m[12:]
}
return m
}
func netCompare(a, b netip.Prefix) int {
aip, bip := a.Addr().Unmap(), b.Addr().Unmap()
v := aip.Compare(bip)

@ -11,6 +11,7 @@ import (
"tailscale.com/types/preftype"
)
//lint:ignore U1000 used in Windows/Linux tests only
func mustCIDRs(ss ...string) []netip.Prefix {
var ret []netip.Prefix
for _, s := range ss {

Loading…
Cancel
Save