Improve build tags

This commit is contained in:
世界 2022-08-07 15:40:46 +08:00
parent 4c11eaac36
commit a937ff2d8d
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
18 changed files with 360 additions and 280 deletions

1
go.mod
View file

@ -3,6 +3,7 @@ module github.com/sagernet/sing-tun
go 1.18
require (
github.com/eycorsican/go-tun2socks v1.16.11
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc
golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48

8
go.sum
View file

@ -1,16 +1,24 @@
github.com/eycorsican/go-tun2socks v1.16.11 h1:+hJDNgisrYaGEqoSxhdikMgMJ4Ilfwm/IZDrWRrbaH8=
github.com/eycorsican/go-tun2socks v1.16.11/go.mod h1:wgB2BFT8ZaPKyKOQ/5dljMG/YIow+AIXyq4KBwJ5sGQ=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805 h1:hE+vtsjBCCPmxkRz9jZA+CicHgVkDT6H+Av5ZzskVxs=
github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc h1:x7H64IiqyrpxPWl/KrWkknzEK4GmpqgfZeVKFVw6E/M=
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
github.com/songgao/water v0.0.0-20190725173103-fd331bda3f4b/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48 h1:N9Vc/rorQUDes6B9CNdIxAn5jODGj2wzfrei2x4wNj4=
golang.org/x/net v0.0.0-20220805013720-a33c5aa5df48/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418 h1:9vYwv7OjYaky/tlAeD7C4oC9EsPTlaFl1H2jS++V+ME=
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
gvisor.dev/gvisor v0.0.0-20220801010827-addd1f7b3e97 h1:zncudP85ZlJelPsgxZXN00Rl5M5j7QuDK27L35Ez01M=

View file

@ -1,4 +1,4 @@
//go:build !no_gvisor
//go:build !(no_gvisor || !(linux || windows || darwin))
package tun
@ -24,9 +24,9 @@ import (
const defaultNIC tcpip.NICID = 1
type GVisorTun struct {
type GVisor struct {
ctx context.Context
tun Tun
tun GVisorTun
tunMtu uint32
endpointIndependentNat bool
endpointIndependentNatTimeout int64
@ -42,18 +42,23 @@ func NewGVisor(
endpointIndependentNat bool,
endpointIndependentNatTimeout int64,
handler Handler,
) *GVisorTun {
return &GVisorTun{
) (Stack, error) {
gTun, isGTun := tun.(GVisorTun)
if !isGTun {
return nil, ErrGVisorUnsupported
}
return &GVisor{
ctx: ctx,
tun: tun,
tun: gTun,
tunMtu: tunMtu,
endpointIndependentNat: endpointIndependentNat,
endpointIndependentNatTimeout: endpointIndependentNatTimeout,
handler: handler,
}
}, nil
}
func (t *GVisorTun) Start() error {
func (t *GVisor) Start() error {
linkEndpoint, err := t.tun.NewEndpoint()
if err != nil {
return err
@ -169,7 +174,7 @@ func (t *GVisorTun) Start() error {
return nil
}
func (t *GVisorTun) Close() error {
func (t *GVisor) Close() error {
t.endpoint.Attach(nil)
t.stack.Close()
for _, endpoint := range t.stack.CleanupEndpoints() {

View file

@ -1,4 +1,4 @@
//go:build !no_gvisor
//go:build !(no_gvisor || !(linux || windows || darwin))
package tun

View file

@ -1,4 +1,4 @@
//go:build !no_gvisor
//go:build !(no_gvisor || !(linux || windows || darwin))
package tun

16
gvisor_other.go Normal file
View file

@ -0,0 +1,16 @@
//go:build no_gvisor && !(linux || windows || darwin)
package tun
import "context"
func NewGVisor(
ctx context.Context,
tun Tun,
tunMtu uint32,
endpointIndependentNat bool,
endpointIndependentNatTimeout int64,
handler Handler,
) (Stack, error) {
return nil, ErrGVisorUnsupported
}

16
gvisor_stub.go Normal file
View file

@ -0,0 +1,16 @@
//go:build no_gvisor && (linux || windows || darwin)
package tun
import "context"
func NewGVisor(
ctx context.Context,
tun Tun,
tunMtu uint32,
endpointIndependentNat bool,
endpointIndependentNatTimeout int64,
handler Handler,
) (Stack, error) {
return nil, ErrGVisorNotIncluded
}

10
gvisor_tun.go Normal file
View file

@ -0,0 +1,10 @@
//go:build !(no_gvisor || !(linux || windows || darwin))
package tun
import "gvisor.dev/gvisor/pkg/tcpip/stack"
type GVisorTun interface {
Tun
NewEndpoint() (stack.LinkEndpoint, error)
}

View file

@ -1,4 +1,4 @@
//go:build !no_gvisor
//go:build !(no_gvisor || !(linux || windows || darwin))
package tun

12
stack.go Normal file
View file

@ -0,0 +1,12 @@
package tun
import E "github.com/sagernet/sing/common/exceptions"
var (
ErrGVisorNotIncluded = E.New("gVisor is disabled in current build, try build without -tags `no_gvisor`")
ErrGVisorUnsupported = E.New("gVisor stack is unsupported on current platform")
)
type Stack interface {
Close() error
}

5
tun.go
View file

@ -1,11 +1,7 @@
//go:build !no_gvisor
package tun
import (
N "github.com/sagernet/sing/common/network"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
type Handler interface {
@ -14,6 +10,5 @@ type Handler interface {
}
type Tun interface {
NewEndpoint() (stack.LinkEndpoint, error)
Close() error
}

View file

@ -9,23 +9,17 @@ import (
"unsafe"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/rw"
"golang.org/x/net/route"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
type NativeTun struct {
tunFd uintptr
tunFile *os.File
inet4Address tcpip.Address
inet6Address tcpip.Address
inet4Address string
inet6Address string
mtu uint32
}
@ -50,137 +44,16 @@ func Open(name string, inet4Address netip.Prefix, inet6Address netip.Prefix, mtu
return &NativeTun{
tunFd: uintptr(tunFd),
tunFile: os.NewFile(uintptr(tunFd), "utun"),
inet4Address: tcpip.Address(inet4Address.Addr().AsSlice()),
inet6Address: tcpip.Address(inet6Address.Addr().AsSlice()),
inet4Address: string(inet4Address.Addr().AsSlice()),
inet6Address: string(inet6Address.Addr().AsSlice()),
mtu: mtu,
}, nil
}
func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
return &DarwinEndpoint{tun: t}, nil
}
func (t *NativeTun) Close() error {
return t.tunFile.Close()
}
var _ stack.LinkEndpoint = (*DarwinEndpoint)(nil)
type DarwinEndpoint struct {
tun *NativeTun
dispatcher stack.NetworkDispatcher
}
func (e *DarwinEndpoint) MTU() uint32 {
return e.tun.mtu
}
func (e *DarwinEndpoint) MaxHeaderLength() uint16 {
return 0
}
func (e *DarwinEndpoint) LinkAddress() tcpip.LinkAddress {
return ""
}
func (e *DarwinEndpoint) Capabilities() stack.LinkEndpointCapabilities {
return stack.CapabilityNone
}
func (e *DarwinEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
if dispatcher == nil && e.dispatcher != nil {
e.dispatcher = nil
return
}
if dispatcher != nil && e.dispatcher == nil {
e.dispatcher = dispatcher
go e.dispatchLoop()
}
}
func (e *DarwinEndpoint) dispatchLoop() {
_buffer := buf.StackNewSize(int(e.tun.mtu) + 4)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
data := buffer.FreeBytes()
for {
n, err := e.tun.tunFile.Read(data)
if err != nil {
break
}
packet := data[4:n]
var networkProtocol tcpip.NetworkProtocolNumber
switch header.IPVersion(packet) {
case header.IPv4Version:
networkProtocol = header.IPv4ProtocolNumber
if header.IPv4(packet).DestinationAddress() == e.tun.inet4Address {
e.tun.tunFile.Write(data[:n])
continue
}
case header.IPv6Version:
networkProtocol = header.IPv6ProtocolNumber
if header.IPv6(packet).DestinationAddress() == e.tun.inet6Address {
e.tun.tunFile.Write(data[:n])
continue
}
default:
e.tun.tunFile.Write(data[:n])
continue
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: bufferv2.MakeWithData(data[4:n]),
IsForwardedPacket: true,
})
pkt.NetworkProtocolNumber = networkProtocol
dispatcher := e.dispatcher
if dispatcher == nil {
pkt.DecRef()
return
}
dispatcher.DeliverNetworkPacket(networkProtocol, pkt)
pkt.DecRef()
}
}
func (e *DarwinEndpoint) IsAttached() bool {
return e.dispatcher != nil
}
func (e *DarwinEndpoint) Wait() {
}
func (e *DarwinEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
func (e *DarwinEndpoint) AddHeader(buffer *stack.PacketBuffer) {
}
var (
packetHeader4 = [4]byte{0x00, 0x00, 0x00, unix.AF_INET}
packetHeader6 = [4]byte{0x00, 0x00, 0x00, unix.AF_INET6}
)
func (e *DarwinEndpoint) WritePackets(packetBufferList stack.PacketBufferList) (int, tcpip.Error) {
var n int
for _, packet := range packetBufferList.AsSlice() {
var packetHeader []byte
switch packet.NetworkProtocolNumber {
case header.IPv4ProtocolNumber:
packetHeader = packetHeader4[:]
case header.IPv6ProtocolNumber:
packetHeader = packetHeader6[:]
}
_, err := rw.WriteV(e.tun.tunFd, append([][]byte{packetHeader}, packet.AsSlices()...))
if err != nil {
return n, &tcpip.ErrAborted{}
}
n++
}
return n, nil
}
const utunControlName = "com.apple.net.utun_control"
const (

138
tun_darwin_gvisor.go Normal file
View file

@ -0,0 +1,138 @@
//go:build !no_gvisor && darwin
package tun
import (
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/rw"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var _ GVisorTun = (*NativeTun)(nil)
func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
return &DarwinEndpoint{tun: t}, nil
}
var _ stack.LinkEndpoint = (*DarwinEndpoint)(nil)
type DarwinEndpoint struct {
tun *NativeTun
dispatcher stack.NetworkDispatcher
}
func (e *DarwinEndpoint) MTU() uint32 {
return e.tun.mtu
}
func (e *DarwinEndpoint) MaxHeaderLength() uint16 {
return 0
}
func (e *DarwinEndpoint) LinkAddress() tcpip.LinkAddress {
return ""
}
func (e *DarwinEndpoint) Capabilities() stack.LinkEndpointCapabilities {
return stack.CapabilityNone
}
func (e *DarwinEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
if dispatcher == nil && e.dispatcher != nil {
e.dispatcher = nil
return
}
if dispatcher != nil && e.dispatcher == nil {
e.dispatcher = dispatcher
go e.dispatchLoop()
}
}
func (e *DarwinEndpoint) dispatchLoop() {
_buffer := buf.StackNewSize(int(e.tun.mtu) + 4)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
data := buffer.FreeBytes()
for {
n, err := e.tun.tunFile.Read(data)
if err != nil {
break
}
packet := data[4:n]
var networkProtocol tcpip.NetworkProtocolNumber
switch header.IPVersion(packet) {
case header.IPv4Version:
networkProtocol = header.IPv4ProtocolNumber
if header.IPv4(packet).DestinationAddress() == tcpip.Address(e.tun.inet4Address) {
e.tun.tunFile.Write(data[:n])
continue
}
case header.IPv6Version:
networkProtocol = header.IPv6ProtocolNumber
if header.IPv6(packet).DestinationAddress() == tcpip.Address(e.tun.inet6Address) {
e.tun.tunFile.Write(data[:n])
continue
}
default:
e.tun.tunFile.Write(data[:n])
continue
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: bufferv2.MakeWithData(data[4:n]),
IsForwardedPacket: true,
})
pkt.NetworkProtocolNumber = networkProtocol
dispatcher := e.dispatcher
if dispatcher == nil {
pkt.DecRef()
return
}
dispatcher.DeliverNetworkPacket(networkProtocol, pkt)
pkt.DecRef()
}
}
func (e *DarwinEndpoint) IsAttached() bool {
return e.dispatcher != nil
}
func (e *DarwinEndpoint) Wait() {
}
func (e *DarwinEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
func (e *DarwinEndpoint) AddHeader(buffer *stack.PacketBuffer) {
}
var (
packetHeader4 = [4]byte{0x00, 0x00, 0x00, unix.AF_INET}
packetHeader6 = [4]byte{0x00, 0x00, 0x00, unix.AF_INET6}
)
func (e *DarwinEndpoint) WritePackets(packetBufferList stack.PacketBufferList) (int, tcpip.Error) {
var n int
for _, packet := range packetBufferList.AsSlice() {
var packetHeader []byte
switch packet.NetworkProtocolNumber {
case header.IPv4ProtocolNumber:
packetHeader = packetHeader4[:]
case header.IPv6ProtocolNumber:
packetHeader = packetHeader6[:]
}
_, err := rw.WriteV(e.tun.tunFd, append([][]byte{packetHeader}, packet.AsSlices()...))
if err != nil {
return n, &tcpip.ErrAborted{}
}
n++
}
return n, nil
}

View file

@ -1,5 +1,3 @@
//go:build !no_gvisor
package tun
import (
@ -12,8 +10,6 @@ import (
"github.com/sagernet/sing/common/rw"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
type NativeTun struct {
@ -130,13 +126,6 @@ func (t *NativeTun) configure(tunLink netlink.Link) error {
return nil
}
func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
return fdbased.New(&fdbased.Options{
FDs: []int{t.fd},
MTU: t.mtu,
})
}
func (t *NativeTun) Close() error {
var errors []error
if t.autoRoute {

17
tun_linux_gvisor.go Normal file
View file

@ -0,0 +1,17 @@
//go:build !no_gvisor && linux
package tun
import (
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var _ GVisorTun = (*NativeTun)(nil)
func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
return fdbased.New(&fdbased.Options{
FDs: []int{t.fd},
MTU: t.mtu,
})
}

View file

@ -1,7 +0,0 @@
//go:build no_gvisor
package tun
type Tun interface {
Close() error
}

View file

@ -1,5 +1,3 @@
//go:build !no_gvisor
package tun
import (
@ -15,15 +13,9 @@ import (
"github.com/sagernet/sing-tun/internal/winipcfg"
"github.com/sagernet/sing-tun/internal/wintun"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
"golang.org/x/sys/windows"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var TunnelType = "sing-tun"
@ -143,16 +135,6 @@ func (t *NativeTun) configure() error {
return nil
}
func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
session, err := t.adapter.StartSession(0x800000)
if err != nil {
return nil, err
}
t.session = session
t.readWait = session.ReadWaitEvent()
return &WintunEndpoint{tun: t}, nil
}
func (t *NativeTun) Read(p []byte) (n int, err error) {
t.running.Add(1)
defer t.running.Done()
@ -272,99 +254,3 @@ const (
spinloopRateThreshold = 800000000 / 8 // 800mbps
spinloopDuration = uint64(time.Millisecond / 80 / time.Nanosecond) // ~1gbit/s
)
var _ stack.LinkEndpoint = (*WintunEndpoint)(nil)
type WintunEndpoint struct {
tun *NativeTun
dispatcher stack.NetworkDispatcher
}
func (e *WintunEndpoint) MTU() uint32 {
return e.tun.mtu
}
func (e *WintunEndpoint) MaxHeaderLength() uint16 {
return 0
}
func (e *WintunEndpoint) LinkAddress() tcpip.LinkAddress {
return ""
}
func (e *WintunEndpoint) Capabilities() stack.LinkEndpointCapabilities {
return stack.CapabilityNone
}
func (e *WintunEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
if dispatcher == nil && e.dispatcher != nil {
e.dispatcher = nil
return
}
if dispatcher != nil && e.dispatcher == nil {
e.dispatcher = dispatcher
go e.dispatchLoop()
}
}
func (e *WintunEndpoint) dispatchLoop() {
_buffer := buf.StackNewSize(int(e.tun.mtu))
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
data := buffer.FreeBytes()
for {
n, err := e.tun.Read(data)
if err != nil {
break
}
packet := data[:n]
var networkProtocol tcpip.NetworkProtocolNumber
switch header.IPVersion(packet) {
case header.IPv4Version:
networkProtocol = header.IPv4ProtocolNumber
case header.IPv6Version:
networkProtocol = header.IPv6ProtocolNumber
default:
e.tun.Write([][]byte{packet})
continue
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: bufferv2.MakeWithData(packet),
IsForwardedPacket: true,
})
dispatcher := e.dispatcher
if dispatcher == nil {
pkt.DecRef()
return
}
dispatcher.DeliverNetworkPacket(networkProtocol, pkt)
pkt.DecRef()
}
}
func (e *WintunEndpoint) IsAttached() bool {
return e.dispatcher != nil
}
func (e *WintunEndpoint) Wait() {
}
func (e *WintunEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
func (e *WintunEndpoint) AddHeader(buffer *stack.PacketBuffer) {
}
func (e *WintunEndpoint) WritePackets(packetBufferList stack.PacketBufferList) (int, tcpip.Error) {
var n int
for _, packet := range packetBufferList.AsSlice() {
_, err := e.tun.Write(packet.AsSlices())
if err != nil {
return n, &tcpip.ErrAborted{}
}
n++
}
return n, nil
}

121
tun_windows_gvisor.go Normal file
View file

@ -0,0 +1,121 @@
//go:build !no_gvisor && windows
package tun
import (
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var _ GVisorTun = (*NativeTun)(nil)
func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
session, err := t.adapter.StartSession(0x800000)
if err != nil {
return nil, err
}
t.session = session
t.readWait = session.ReadWaitEvent()
return &WintunEndpoint{tun: t}, nil
}
var _ stack.LinkEndpoint = (*WintunEndpoint)(nil)
type WintunEndpoint struct {
tun *NativeTun
dispatcher stack.NetworkDispatcher
}
func (e *WintunEndpoint) MTU() uint32 {
return e.tun.mtu
}
func (e *WintunEndpoint) MaxHeaderLength() uint16 {
return 0
}
func (e *WintunEndpoint) LinkAddress() tcpip.LinkAddress {
return ""
}
func (e *WintunEndpoint) Capabilities() stack.LinkEndpointCapabilities {
return stack.CapabilityNone
}
func (e *WintunEndpoint) Attach(dispatcher stack.NetworkDispatcher) {
if dispatcher == nil && e.dispatcher != nil {
e.dispatcher = nil
return
}
if dispatcher != nil && e.dispatcher == nil {
e.dispatcher = dispatcher
go e.dispatchLoop()
}
}
func (e *WintunEndpoint) dispatchLoop() {
_buffer := buf.StackNewSize(int(e.tun.mtu))
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
data := buffer.FreeBytes()
for {
n, err := e.tun.Read(data)
if err != nil {
break
}
packet := data[:n]
var networkProtocol tcpip.NetworkProtocolNumber
switch header.IPVersion(packet) {
case header.IPv4Version:
networkProtocol = header.IPv4ProtocolNumber
case header.IPv6Version:
networkProtocol = header.IPv6ProtocolNumber
default:
e.tun.Write([][]byte{packet})
continue
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: bufferv2.MakeWithData(packet),
IsForwardedPacket: true,
})
dispatcher := e.dispatcher
if dispatcher == nil {
pkt.DecRef()
return
}
dispatcher.DeliverNetworkPacket(networkProtocol, pkt)
pkt.DecRef()
}
}
func (e *WintunEndpoint) IsAttached() bool {
return e.dispatcher != nil
}
func (e *WintunEndpoint) Wait() {
}
func (e *WintunEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone
}
func (e *WintunEndpoint) AddHeader(buffer *stack.PacketBuffer) {
}
func (e *WintunEndpoint) WritePackets(packetBufferList stack.PacketBufferList) (int, tcpip.Error) {
var n int
for _, packet := range packetBufferList.AsSlice() {
_, err := e.tun.Write(packet.AsSlices())
if err != nil {
return n, &tcpip.ErrAborted{}
}
n++
}
return n, nil
}