tailscale/net/tstun/tun.go
Will Norris 71029cea2d all: update copyright and license headers
This updates all source files to use a new standard header for copyright
and license declaration.  Notably, copyright no longer includes a date,
and we now use the standard SPDX-License-Identifier header.

This commit was done almost entirely mechanically with perl, and then
some minimal manual fixes.

Updates #6865

Signed-off-by: Will Norris <will@tailscale.com>
2023-01-27 15:36:29 -08:00

96 lines
2.6 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build !js
// Package tun creates a tuntap device, working around OS-specific
// quirks if necessary.
package tstun
import (
"errors"
"runtime"
"strings"
"time"
"github.com/tailscale/wireguard-go/tun"
"tailscale.com/envknob"
"tailscale.com/types/logger"
)
// createTAP is non-nil on Linux.
var createTAP func(tapName, bridgeName string) (tun.Device, error)
// New returns a tun.Device for the requested device name, along with
// the OS-dependent name that was allocated to the device.
func New(logf logger.Logf, tunName string) (tun.Device, string, error) {
var disableTUNOffload = envknob.Bool("TS_DISABLE_TUN_OFFLOAD")
var dev tun.Device
var err error
if strings.HasPrefix(tunName, "tap:") {
if runtime.GOOS != "linux" {
return nil, "", errors.New("tap only works on Linux")
}
if createTAP == nil { // if the ts_omit_tap tag is used
return nil, "", errors.New("tap is not supported in this build")
}
f := strings.Split(tunName, ":")
var tapName, bridgeName string
switch len(f) {
case 2:
tapName = f[1]
case 3:
tapName, bridgeName = f[1], f[2]
default:
return nil, "", errors.New("bogus tap argument")
}
dev, err = createTAP(tapName, bridgeName)
} else {
tunMTU := DefaultMTU
if mtu, ok := envknob.LookupInt("TS_DEBUG_MTU"); ok {
tunMTU = mtu
}
dev, err = tun.CreateTUN(tunName, tunMTU)
if err == nil && disableTUNOffload {
if do, ok := dev.(tun.DisableOffloader); ok {
do.DisableOffload()
}
}
}
if err != nil {
return nil, "", err
}
if err := waitInterfaceUp(dev, 90*time.Second, logf); err != nil {
dev.Close()
return nil, "", err
}
if err := setLinkAttrs(dev); err != nil {
logf("setting link attributes: %v", err)
}
name, err := interfaceName(dev)
if err != nil {
dev.Close()
return nil, "", err
}
return dev, name, nil
}
// tunDiagnoseFailure, if non-nil, does OS-specific diagnostics of why
// TUN failed to work.
var tunDiagnoseFailure func(tunName string, logf logger.Logf, err error)
// Diagnose tries to explain a tuntap device creation failure.
// It pokes around the system and logs some diagnostic info that might
// help debug why tun creation failed. Because device creation has
// already failed and the program's about to end, log a lot.
//
// The tunName is the name of the tun device that was requested but failed.
// The err error is how the tun creation failed.
func Diagnose(logf logger.Logf, tunName string, err error) {
if tunDiagnoseFailure != nil {
tunDiagnoseFailure(tunName, logf, err)
} else {
logf("no TUN failure diagnostics for OS %q", runtime.GOOS)
}
}