mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-25 11:05:45 +00:00
all: cleanup unused code, part 2 (#10670)
And enable U1000 check in staticcheck. Updates #cleanup Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
parent
c9836b454d
commit
2716250ee8
@ -93,14 +93,6 @@ type commandInfo struct {
|
||||
},
|
||||
}
|
||||
|
||||
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 @@ type step struct {
|
||||
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 @@
|
||||
"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 @@
|
||||
"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 @@
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"golang.org/x/crypto/blake2s"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
@ -105,10 +104,6 @@ type noisesession struct {
|
||||
* 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 @@
|
||||
"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 @@
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"os/user"
|
||||
"runtime"
|
||||
@ -18,7 +17,6 @@
|
||||
"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 @@
|
||||
// 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 @@
|
||||
"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 @@
|
||||
// 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 @@
|
||||
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 @@
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
@ -17,32 +16,10 @@
|
||||
"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 @@ func unARPA(a string) (ipStr string, ok bool) {
|
||||
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 @@
|
||||
|
||||
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 @@
|
||||
)
|
||||
|
||||
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 @@
|
||||
"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 @@ type _RM_UNIQUE_PROCESS struct {
|
||||
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 @@
|
||||
"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 @@
|
||||
// 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 @@ type discoInfo struct {
|
||||
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 @@
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/netip"
|
||||
"slices"
|
||||
"sort"
|
||||
@ -28,8 +27,6 @@
|
||||
"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 @@
|
||||
"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…
Reference in New Issue
Block a user