Update
This commit is contained in:
63
vendor/tailscale.com/net/tstun/linkattrs_linux.go
generated
vendored
63
vendor/tailscale.com/net/tstun/linkattrs_linux.go
generated
vendored
@@ -1,63 +0,0 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package tstun
|
||||
|
||||
import (
|
||||
"github.com/mdlayher/genetlink"
|
||||
"github.com/mdlayher/netlink"
|
||||
"github.com/tailscale/wireguard-go/tun"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// setLinkSpeed sets the advertised link speed of the TUN interface.
|
||||
func setLinkSpeed(iface tun.Device, mbps int) error {
|
||||
name, err := iface.Name()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn, err := genetlink.Dial(&netlink.Config{Strict: true})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
f, err := conn.GetFamily(unix.ETHTOOL_GENL_NAME)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ae := netlink.NewAttributeEncoder()
|
||||
ae.Nested(unix.ETHTOOL_A_LINKMODES_HEADER, func(nae *netlink.AttributeEncoder) error {
|
||||
nae.String(unix.ETHTOOL_A_HEADER_DEV_NAME, name)
|
||||
return nil
|
||||
})
|
||||
ae.Uint32(unix.ETHTOOL_A_LINKMODES_SPEED, uint32(mbps))
|
||||
|
||||
b, err := ae.Encode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = conn.Execute(
|
||||
genetlink.Message{
|
||||
Header: genetlink.Header{
|
||||
Command: unix.ETHTOOL_MSG_LINKMODES_SET,
|
||||
Version: unix.ETHTOOL_GENL_VERSION,
|
||||
},
|
||||
Data: b,
|
||||
},
|
||||
f.ID,
|
||||
netlink.Request|netlink.Acknowledge,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
// setLinkAttrs sets up link attributes that can be queried by external tools.
|
||||
// Its failure is non-fatal to interface bringup.
|
||||
func setLinkAttrs(iface tun.Device) error {
|
||||
// By default the link speed is 10Mbps, which is easily exceeded and causes monitoring tools to complain (#3933).
|
||||
return setLinkSpeed(iface, unix.SPEED_UNKNOWN)
|
||||
}
|
||||
12
vendor/tailscale.com/net/tstun/linkattrs_notlinux.go
generated
vendored
12
vendor/tailscale.com/net/tstun/linkattrs_notlinux.go
generated
vendored
@@ -1,12 +0,0 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !linux
|
||||
|
||||
package tstun
|
||||
|
||||
import "github.com/tailscale/wireguard-go/tun"
|
||||
|
||||
func setLinkAttrs(iface tun.Device) error {
|
||||
return nil
|
||||
}
|
||||
69
vendor/tailscale.com/net/tstun/netstack_disabled.go
generated
vendored
Normal file
69
vendor/tailscale.com/net/tstun/netstack_disabled.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build ts_omit_netstack
|
||||
|
||||
package tstun
|
||||
|
||||
type netstack_PacketBuffer struct {
|
||||
GSOOptions netstack_GSO
|
||||
}
|
||||
|
||||
func (*netstack_PacketBuffer) DecRef() { panic("unreachable") }
|
||||
func (*netstack_PacketBuffer) Size() int { panic("unreachable") }
|
||||
|
||||
type netstack_GSOType int
|
||||
|
||||
const (
|
||||
netstack_GSONone netstack_GSOType = iota
|
||||
netstack_GSOTCPv4
|
||||
netstack_GSOTCPv6
|
||||
netstack_GSOGvisor
|
||||
)
|
||||
|
||||
type netstack_GSO struct {
|
||||
// Type is one of GSONone, GSOTCPv4, etc.
|
||||
Type netstack_GSOType
|
||||
// NeedsCsum is set if the checksum offload is enabled.
|
||||
NeedsCsum bool
|
||||
// CsumOffset is offset after that to place checksum.
|
||||
CsumOffset uint16
|
||||
|
||||
// Mss is maximum segment size.
|
||||
MSS uint16
|
||||
// L3Len is L3 (IP) header length.
|
||||
L3HdrLen uint16
|
||||
|
||||
// MaxSize is maximum GSO packet size.
|
||||
MaxSize uint32
|
||||
}
|
||||
|
||||
func (p *netstack_PacketBuffer) NetworkHeader() slicer {
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (p *netstack_PacketBuffer) TransportHeader() slicer {
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (p *netstack_PacketBuffer) ToBuffer() netstack_Buffer { panic("unreachable") }
|
||||
|
||||
func (p *netstack_PacketBuffer) Data() asRanger {
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
type asRanger struct{}
|
||||
|
||||
func (asRanger) AsRange() toSlicer { panic("unreachable") }
|
||||
|
||||
type toSlicer struct{}
|
||||
|
||||
func (toSlicer) ToSlice() []byte { panic("unreachable") }
|
||||
|
||||
type slicer struct{}
|
||||
|
||||
func (s slicer) Slice() []byte { panic("unreachable") }
|
||||
|
||||
type netstack_Buffer struct{}
|
||||
|
||||
func (netstack_Buffer) Flatten() []byte { panic("unreachable") }
|
||||
22
vendor/tailscale.com/net/tstun/netstack_enabled.go
generated
vendored
Normal file
22
vendor/tailscale.com/net/tstun/netstack_enabled.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !ts_omit_netstack
|
||||
|
||||
package tstun
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
|
||||
type (
|
||||
netstack_PacketBuffer = stack.PacketBuffer
|
||||
netstack_GSO = stack.GSO
|
||||
)
|
||||
|
||||
const (
|
||||
netstack_GSONone = stack.GSONone
|
||||
netstack_GSOTCPv4 = stack.GSOTCPv4
|
||||
netstack_GSOTCPv6 = stack.GSOTCPv6
|
||||
netstack_GSOGvisor = stack.GSOGvisor
|
||||
)
|
||||
2
vendor/tailscale.com/net/tstun/tstun_stub.go
generated
vendored
2
vendor/tailscale.com/net/tstun/tstun_stub.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build plan9 || aix || solaris || illumos
|
||||
//go:build aix || solaris || illumos
|
||||
|
||||
package tstun
|
||||
|
||||
|
||||
72
vendor/tailscale.com/net/tstun/tun.go
generated
vendored
72
vendor/tailscale.com/net/tstun/tun.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !wasm && !plan9 && !tamago && !aix && !solaris && !illumos
|
||||
//go:build !wasm && !tamago && !aix && !solaris && !illumos
|
||||
|
||||
// Package tun creates a tuntap device, working around OS-specific
|
||||
// quirks if necessary.
|
||||
@@ -9,18 +9,28 @@ package tstun
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/tailscale/wireguard-go/tun"
|
||||
"tailscale.com/feature"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
// CrateTAP is the hook set by feature/tap.
|
||||
// CreateTAP is the hook maybe set by feature/tap.
|
||||
var CreateTAP feature.Hook[func(logf logger.Logf, tapName, bridgeName string) (tun.Device, error)]
|
||||
|
||||
// HookSetLinkAttrs is the hook maybe set by feature/linkspeed.
|
||||
var HookSetLinkAttrs feature.Hook[func(tun.Device) error]
|
||||
|
||||
// modprobeTunHook is a Linux-specific hook to run "/sbin/modprobe tun".
|
||||
var modprobeTunHook feature.Hook[func() 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) {
|
||||
@@ -45,7 +55,25 @@ func New(logf logger.Logf, tunName string) (tun.Device, string, error) {
|
||||
}
|
||||
dev, err = CreateTAP.Get()(logf, tapName, bridgeName)
|
||||
} else {
|
||||
dev, err = tun.CreateTUN(tunName, int(DefaultTUNMTU()))
|
||||
if runtime.GOOS == "plan9" {
|
||||
cleanUpPlan9Interfaces()
|
||||
}
|
||||
// Try to create the TUN device up to two times. If it fails
|
||||
// the first time and we're on Linux, try a desperate
|
||||
// "modprobe tun" to load the tun module and try again.
|
||||
for try := range 2 {
|
||||
dev, err = tun.CreateTUN(tunName, int(DefaultTUNMTU()))
|
||||
if err == nil || !modprobeTunHook.IsSet() {
|
||||
if try > 0 {
|
||||
logf("created TUN device %q after doing `modprobe tun`", tunName)
|
||||
}
|
||||
break
|
||||
}
|
||||
if modprobeTunHook.Get()() != nil {
|
||||
// modprobe failed; no point trying again.
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
@@ -54,8 +82,12 @@ func New(logf logger.Logf, tunName string) (tun.Device, string, error) {
|
||||
dev.Close()
|
||||
return nil, "", err
|
||||
}
|
||||
if err := setLinkAttrs(dev); err != nil {
|
||||
logf("setting link attributes: %v", err)
|
||||
if buildfeatures.HasLinkSpeed {
|
||||
if f, ok := HookSetLinkAttrs.GetOk(); ok {
|
||||
if err := f(dev); err != nil {
|
||||
logf("setting link attributes: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
name, err := interfaceName(dev)
|
||||
if err != nil {
|
||||
@@ -65,6 +97,36 @@ func New(logf logger.Logf, tunName string) (tun.Device, string, error) {
|
||||
return dev, name, nil
|
||||
}
|
||||
|
||||
func cleanUpPlan9Interfaces() {
|
||||
maybeUnbind := func(n int) {
|
||||
b, err := os.ReadFile(fmt.Sprintf("/net/ipifc/%d/status", n))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
status := string(b)
|
||||
if !(strings.HasPrefix(status, "device maxtu ") ||
|
||||
strings.Contains(status, "fd7a:115c:a1e0:")) {
|
||||
return
|
||||
}
|
||||
f, err := os.OpenFile(fmt.Sprintf("/net/ipifc/%d/ctl", n), os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
if _, err := fmt.Fprintf(f, "unbind\n"); err != nil {
|
||||
log.Printf("unbind interface %v: %v", n, err)
|
||||
return
|
||||
}
|
||||
log.Printf("tun: unbound stale interface %v", n)
|
||||
}
|
||||
|
||||
// A common case: after unclean shutdown we might leave interfaces
|
||||
// behind. Look for our straggler(s) and clean them up.
|
||||
for n := 2; n < 5; n++ {
|
||||
maybeUnbind(n)
|
||||
}
|
||||
}
|
||||
|
||||
// tunDiagnoseFailure, if non-nil, does OS-specific diagnostics of why
|
||||
// TUN failed to work.
|
||||
var tunDiagnoseFailure func(tunName string, logf logger.Logf, err error)
|
||||
|
||||
10
vendor/tailscale.com/net/tstun/tun_linux.go
generated
vendored
10
vendor/tailscale.com/net/tstun/tun_linux.go
generated
vendored
@@ -17,6 +17,14 @@ import (
|
||||
|
||||
func init() {
|
||||
tunDiagnoseFailure = diagnoseLinuxTUNFailure
|
||||
modprobeTunHook.Set(func() error {
|
||||
_, err := modprobeTun()
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func modprobeTun() ([]byte, error) {
|
||||
return exec.Command("/sbin/modprobe", "tun").CombinedOutput()
|
||||
}
|
||||
|
||||
func diagnoseLinuxTUNFailure(tunName string, logf logger.Logf, createErr error) {
|
||||
@@ -36,7 +44,7 @@ func diagnoseLinuxTUNFailure(tunName string, logf logger.Logf, createErr error)
|
||||
kernel := utsReleaseField(&un)
|
||||
logf("Linux kernel version: %s", kernel)
|
||||
|
||||
modprobeOut, err := exec.Command("/sbin/modprobe", "tun").CombinedOutput()
|
||||
modprobeOut, err := modprobeTun()
|
||||
if err == nil {
|
||||
logf("'modprobe tun' successful")
|
||||
// Either tun is currently loaded, or it's statically
|
||||
|
||||
144
vendor/tailscale.com/net/tstun/wrap.go
generated
vendored
144
vendor/tailscale.com/net/tstun/wrap.go
generated
vendored
@@ -22,10 +22,8 @@ import (
|
||||
"github.com/tailscale/wireguard-go/device"
|
||||
"github.com/tailscale/wireguard-go/tun"
|
||||
"go4.org/mem"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
"tailscale.com/disco"
|
||||
tsmetrics "tailscale.com/metrics"
|
||||
"tailscale.com/net/connstats"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/net/packet"
|
||||
"tailscale.com/net/packet/checksum"
|
||||
"tailscale.com/net/tsaddr"
|
||||
@@ -34,7 +32,9 @@ import (
|
||||
"tailscale.com/types/ipproto"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/types/netlogfunc"
|
||||
"tailscale.com/util/clientmetric"
|
||||
"tailscale.com/util/eventbus"
|
||||
"tailscale.com/util/usermetric"
|
||||
"tailscale.com/wgengine/filter"
|
||||
"tailscale.com/wgengine/netstack/gro"
|
||||
@@ -204,17 +204,20 @@ type Wrapper struct {
|
||||
// disableTSMPRejected disables TSMP rejected responses. For tests.
|
||||
disableTSMPRejected bool
|
||||
|
||||
// stats maintains per-connection counters.
|
||||
stats atomic.Pointer[connstats.Statistics]
|
||||
// connCounter maintains per-connection counters.
|
||||
connCounter syncs.AtomicValue[netlogfunc.ConnectionCounter]
|
||||
|
||||
captureHook syncs.AtomicValue[packet.CaptureCallback]
|
||||
|
||||
metrics *metrics
|
||||
|
||||
eventClient *eventbus.Client
|
||||
discoKeyAdvertisementPub *eventbus.Publisher[DiscoKeyAdvertisement]
|
||||
}
|
||||
|
||||
type metrics struct {
|
||||
inboundDroppedPacketsTotal *tsmetrics.MultiLabelMap[usermetric.DropLabels]
|
||||
outboundDroppedPacketsTotal *tsmetrics.MultiLabelMap[usermetric.DropLabels]
|
||||
inboundDroppedPacketsTotal *usermetric.MultiLabelMap[usermetric.DropLabels]
|
||||
outboundDroppedPacketsTotal *usermetric.MultiLabelMap[usermetric.DropLabels]
|
||||
}
|
||||
|
||||
func registerMetrics(reg *usermetric.Registry) *metrics {
|
||||
@@ -228,7 +231,7 @@ func registerMetrics(reg *usermetric.Registry) *metrics {
|
||||
type tunInjectedRead struct {
|
||||
// Only one of packet or data should be set, and are read in that order of
|
||||
// precedence.
|
||||
packet *stack.PacketBuffer
|
||||
packet *netstack_PacketBuffer
|
||||
data []byte
|
||||
}
|
||||
|
||||
@@ -255,15 +258,15 @@ func (w *Wrapper) Start() {
|
||||
close(w.startCh)
|
||||
}
|
||||
|
||||
func WrapTAP(logf logger.Logf, tdev tun.Device, m *usermetric.Registry) *Wrapper {
|
||||
return wrap(logf, tdev, true, m)
|
||||
func WrapTAP(logf logger.Logf, tdev tun.Device, m *usermetric.Registry, bus *eventbus.Bus) *Wrapper {
|
||||
return wrap(logf, tdev, true, m, bus)
|
||||
}
|
||||
|
||||
func Wrap(logf logger.Logf, tdev tun.Device, m *usermetric.Registry) *Wrapper {
|
||||
return wrap(logf, tdev, false, m)
|
||||
func Wrap(logf logger.Logf, tdev tun.Device, m *usermetric.Registry, bus *eventbus.Bus) *Wrapper {
|
||||
return wrap(logf, tdev, false, m, bus)
|
||||
}
|
||||
|
||||
func wrap(logf logger.Logf, tdev tun.Device, isTAP bool, m *usermetric.Registry) *Wrapper {
|
||||
func wrap(logf logger.Logf, tdev tun.Device, isTAP bool, m *usermetric.Registry, bus *eventbus.Bus) *Wrapper {
|
||||
logf = logger.WithPrefix(logf, "tstun: ")
|
||||
w := &Wrapper{
|
||||
logf: logf,
|
||||
@@ -284,6 +287,9 @@ func wrap(logf logger.Logf, tdev tun.Device, isTAP bool, m *usermetric.Registry)
|
||||
metrics: registerMetrics(m),
|
||||
}
|
||||
|
||||
w.eventClient = bus.Client("net.tstun")
|
||||
w.discoKeyAdvertisementPub = eventbus.Publish[DiscoKeyAdvertisement](w.eventClient)
|
||||
|
||||
w.vectorBuffer = make([][]byte, tdev.BatchSize())
|
||||
for i := range w.vectorBuffer {
|
||||
w.vectorBuffer[i] = make([]byte, maxBufferSize)
|
||||
@@ -312,7 +318,9 @@ func (t *Wrapper) now() time.Time {
|
||||
//
|
||||
// The map ownership passes to the Wrapper. It must be non-nil.
|
||||
func (t *Wrapper) SetDestIPActivityFuncs(m map[netip.Addr]func()) {
|
||||
t.destIPActivity.Store(m)
|
||||
if buildfeatures.HasLazyWG {
|
||||
t.destIPActivity.Store(m)
|
||||
}
|
||||
}
|
||||
|
||||
// SetDiscoKey sets the current discovery key.
|
||||
@@ -356,6 +364,7 @@ func (t *Wrapper) Close() error {
|
||||
close(t.vectorOutbound)
|
||||
t.outboundMu.Unlock()
|
||||
err = t.tdev.Close()
|
||||
t.eventClient.Close()
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -948,12 +957,14 @@ func (t *Wrapper) Read(buffs [][]byte, sizes []int, offset int) (int, error) {
|
||||
for _, data := range res.data {
|
||||
p.Decode(data[res.dataOffset:])
|
||||
|
||||
if m := t.destIPActivity.Load(); m != nil {
|
||||
if fn := m[p.Dst.Addr()]; fn != nil {
|
||||
fn()
|
||||
if buildfeatures.HasLazyWG {
|
||||
if m := t.destIPActivity.Load(); m != nil {
|
||||
if fn := m[p.Dst.Addr()]; fn != nil {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
}
|
||||
if captHook != nil {
|
||||
if buildfeatures.HasCapture && captHook != nil {
|
||||
captHook(packet.FromLocal, t.now(), p.Buffer(), p.CaptureMeta)
|
||||
}
|
||||
if !t.disableFilter {
|
||||
@@ -964,6 +975,11 @@ func (t *Wrapper) Read(buffs [][]byte, sizes []int, offset int) (int, error) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if buildfeatures.HasNetLog {
|
||||
if update := t.connCounter.Load(); update != nil {
|
||||
updateConnCounter(update, p.Buffer(), false)
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure to do SNAT after filtering, so that any flow tracking in
|
||||
// the filter sees the original source address. See #12133.
|
||||
@@ -973,9 +989,6 @@ func (t *Wrapper) Read(buffs [][]byte, sizes []int, offset int) (int, error) {
|
||||
panic(fmt.Sprintf("short copy: %d != %d", n, len(data)-res.dataOffset))
|
||||
}
|
||||
sizes[buffsPos] = n
|
||||
if stats := t.stats.Load(); stats != nil {
|
||||
stats.UpdateTxVirtual(p.Buffer())
|
||||
}
|
||||
buffsPos++
|
||||
}
|
||||
if buffsGRO != nil {
|
||||
@@ -998,7 +1011,10 @@ const (
|
||||
minTCPHeaderSize = 20
|
||||
)
|
||||
|
||||
func stackGSOToTunGSO(pkt []byte, gso stack.GSO) (tun.GSOOptions, error) {
|
||||
func stackGSOToTunGSO(pkt []byte, gso netstack_GSO) (tun.GSOOptions, error) {
|
||||
if !buildfeatures.HasNetstack {
|
||||
panic("unreachable")
|
||||
}
|
||||
options := tun.GSOOptions{
|
||||
CsumStart: gso.L3HdrLen,
|
||||
CsumOffset: gso.CsumOffset,
|
||||
@@ -1006,12 +1022,12 @@ func stackGSOToTunGSO(pkt []byte, gso stack.GSO) (tun.GSOOptions, error) {
|
||||
NeedsCsum: gso.NeedsCsum,
|
||||
}
|
||||
switch gso.Type {
|
||||
case stack.GSONone:
|
||||
case netstack_GSONone:
|
||||
options.GSOType = tun.GSONone
|
||||
return options, nil
|
||||
case stack.GSOTCPv4:
|
||||
case netstack_GSOTCPv4:
|
||||
options.GSOType = tun.GSOTCPv4
|
||||
case stack.GSOTCPv6:
|
||||
case netstack_GSOTCPv6:
|
||||
options.GSOType = tun.GSOTCPv6
|
||||
default:
|
||||
return tun.GSOOptions{}, fmt.Errorf("unsupported gVisor GSOType: %v", gso.Type)
|
||||
@@ -1034,7 +1050,10 @@ func stackGSOToTunGSO(pkt []byte, gso stack.GSO) (tun.GSOOptions, error) {
|
||||
// both before and after partial checksum updates where later checksum
|
||||
// offloading still expects a partial checksum.
|
||||
// TODO(jwhited): plumb partial checksum awareness into net/packet/checksum.
|
||||
func invertGSOChecksum(pkt []byte, gso stack.GSO) {
|
||||
func invertGSOChecksum(pkt []byte, gso netstack_GSO) {
|
||||
if !buildfeatures.HasNetstack {
|
||||
panic("unreachable")
|
||||
}
|
||||
if gso.NeedsCsum != true {
|
||||
return
|
||||
}
|
||||
@@ -1048,10 +1067,13 @@ func invertGSOChecksum(pkt []byte, gso stack.GSO) {
|
||||
|
||||
// injectedRead handles injected reads, which bypass filters.
|
||||
func (t *Wrapper) injectedRead(res tunInjectedRead, outBuffs [][]byte, sizes []int, offset int) (n int, err error) {
|
||||
var gso stack.GSO
|
||||
var gso netstack_GSO
|
||||
|
||||
pkt := outBuffs[0][offset:]
|
||||
if res.packet != nil {
|
||||
if !buildfeatures.HasNetstack {
|
||||
panic("unreachable")
|
||||
}
|
||||
bufN := copy(pkt, res.packet.NetworkHeader().Slice())
|
||||
bufN += copy(pkt[bufN:], res.packet.TransportHeader().Slice())
|
||||
bufN += copy(pkt[bufN:], res.packet.Data().AsRange().ToSlice())
|
||||
@@ -1074,9 +1096,11 @@ func (t *Wrapper) injectedRead(res tunInjectedRead, outBuffs [][]byte, sizes []i
|
||||
pc.snat(p)
|
||||
invertGSOChecksum(pkt, gso)
|
||||
|
||||
if m := t.destIPActivity.Load(); m != nil {
|
||||
if fn := m[p.Dst.Addr()]; fn != nil {
|
||||
fn()
|
||||
if buildfeatures.HasLazyWG {
|
||||
if m := t.destIPActivity.Load(); m != nil {
|
||||
if fn := m[p.Dst.Addr()]; fn != nil {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,9 +1113,11 @@ func (t *Wrapper) injectedRead(res tunInjectedRead, outBuffs [][]byte, sizes []i
|
||||
n, err = tun.GSOSplit(pkt, gsoOptions, outBuffs, sizes, offset)
|
||||
}
|
||||
|
||||
if stats := t.stats.Load(); stats != nil {
|
||||
for i := 0; i < n; i++ {
|
||||
stats.UpdateTxVirtual(outBuffs[i][offset : offset+sizes[i]])
|
||||
if buildfeatures.HasNetLog {
|
||||
if update := t.connCounter.Load(); update != nil {
|
||||
for i := 0; i < n; i++ {
|
||||
updateConnCounter(update, outBuffs[i][offset:offset+sizes[i]], false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1100,6 +1126,13 @@ func (t *Wrapper) injectedRead(res tunInjectedRead, outBuffs [][]byte, sizes []i
|
||||
return n, err
|
||||
}
|
||||
|
||||
// DiscoKeyAdvertisement is a TSMP message used for distributing disco keys.
|
||||
// This struct is used an an event on the [eventbus.Bus].
|
||||
type DiscoKeyAdvertisement struct {
|
||||
Src netip.Addr // Src field is populated by the IP header of the packet, not from the payload itself.
|
||||
Key key.DiscoPublic
|
||||
}
|
||||
|
||||
func (t *Wrapper) filterPacketInboundFromWireGuard(p *packet.Parsed, captHook packet.CaptureCallback, pc *peerConfigTable, gro *gro.GRO) (filter.Response, *gro.GRO) {
|
||||
if captHook != nil {
|
||||
captHook(packet.FromPeer, t.now(), p.Buffer(), p.CaptureMeta)
|
||||
@@ -1110,6 +1143,12 @@ func (t *Wrapper) filterPacketInboundFromWireGuard(p *packet.Parsed, captHook pa
|
||||
t.noteActivity()
|
||||
t.injectOutboundPong(p, pingReq)
|
||||
return filter.DropSilently, gro
|
||||
} else if discoKeyAdvert, ok := p.AsTSMPDiscoAdvertisement(); ok {
|
||||
t.discoKeyAdvertisementPub.Publish(DiscoKeyAdvertisement{
|
||||
Src: discoKeyAdvert.Src,
|
||||
Key: discoKeyAdvert.Key,
|
||||
})
|
||||
return filter.DropSilently, gro
|
||||
} else if data, ok := p.AsTSMPPong(); ok {
|
||||
if f := t.OnTSMPPongReceived; f != nil {
|
||||
f(data)
|
||||
@@ -1257,9 +1296,11 @@ func (t *Wrapper) Write(buffs [][]byte, offset int) (int, error) {
|
||||
}
|
||||
|
||||
func (t *Wrapper) tdevWrite(buffs [][]byte, offset int) (int, error) {
|
||||
if stats := t.stats.Load(); stats != nil {
|
||||
for i := range buffs {
|
||||
stats.UpdateRxVirtual((buffs)[i][offset:])
|
||||
if buildfeatures.HasNetLog {
|
||||
if update := t.connCounter.Load(); update != nil {
|
||||
for i := range buffs {
|
||||
updateConnCounter(update, buffs[i][offset:], true)
|
||||
}
|
||||
}
|
||||
}
|
||||
return t.tdev.Write(buffs, offset)
|
||||
@@ -1297,7 +1338,10 @@ func (t *Wrapper) SetJailedFilter(filt *filter.Filter) {
|
||||
//
|
||||
// This path is typically used to deliver synthesized packets to the
|
||||
// host networking stack.
|
||||
func (t *Wrapper) InjectInboundPacketBuffer(pkt *stack.PacketBuffer, buffs [][]byte, sizes []int) error {
|
||||
func (t *Wrapper) InjectInboundPacketBuffer(pkt *netstack_PacketBuffer, buffs [][]byte, sizes []int) error {
|
||||
if !buildfeatures.HasNetstack {
|
||||
panic("unreachable")
|
||||
}
|
||||
buf := buffs[0][PacketStartOffset:]
|
||||
|
||||
bufN := copy(buf, pkt.NetworkHeader().Slice())
|
||||
@@ -1436,7 +1480,10 @@ func (t *Wrapper) InjectOutbound(pkt []byte) error {
|
||||
// InjectOutboundPacketBuffer logically behaves as InjectOutbound. It takes ownership of one
|
||||
// reference count on the packet, and the packet may be mutated. The packet refcount will be
|
||||
// decremented after the injected buffer has been read.
|
||||
func (t *Wrapper) InjectOutboundPacketBuffer(pkt *stack.PacketBuffer) error {
|
||||
func (t *Wrapper) InjectOutboundPacketBuffer(pkt *netstack_PacketBuffer) error {
|
||||
if !buildfeatures.HasNetstack {
|
||||
panic("unreachable")
|
||||
}
|
||||
size := pkt.Size()
|
||||
if size > MaxPacketSize {
|
||||
pkt.DecRef()
|
||||
@@ -1472,10 +1519,12 @@ func (t *Wrapper) Unwrap() tun.Device {
|
||||
return t.tdev
|
||||
}
|
||||
|
||||
// SetStatistics specifies a per-connection statistics aggregator.
|
||||
// SetConnectionCounter specifies a per-connection statistics aggregator.
|
||||
// Nil may be specified to disable statistics gathering.
|
||||
func (t *Wrapper) SetStatistics(stats *connstats.Statistics) {
|
||||
t.stats.Store(stats)
|
||||
func (t *Wrapper) SetConnectionCounter(fn netlogfunc.ConnectionCounter) {
|
||||
if buildfeatures.HasNetLog {
|
||||
t.connCounter.Store(fn)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -1491,5 +1540,18 @@ var (
|
||||
)
|
||||
|
||||
func (t *Wrapper) InstallCaptureHook(cb packet.CaptureCallback) {
|
||||
if !buildfeatures.HasCapture {
|
||||
return
|
||||
}
|
||||
t.captureHook.Store(cb)
|
||||
}
|
||||
|
||||
func updateConnCounter(update netlogfunc.ConnectionCounter, b []byte, receive bool) {
|
||||
var p packet.Parsed
|
||||
p.Decode(b)
|
||||
if receive {
|
||||
update(p.IPProto, p.Dst, p.Src, 1, len(b), true)
|
||||
} else {
|
||||
update(p.IPProto, p.Src, p.Dst, 1, len(b), false)
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/tailscale.com/net/tstun/wrap_linux.go
generated
vendored
2
vendor/tailscale.com/net/tstun/wrap_linux.go
generated
vendored
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build linux && !ts_omit_gro
|
||||
|
||||
package tstun
|
||||
|
||||
import (
|
||||
|
||||
2
vendor/tailscale.com/net/tstun/wrap_noop.go
generated
vendored
2
vendor/tailscale.com/net/tstun/wrap_noop.go
generated
vendored
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !linux
|
||||
//go:build !linux || ts_omit_gro
|
||||
|
||||
package tstun
|
||||
|
||||
|
||||
Reference in New Issue
Block a user