mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-03 20:07:40 +03:00
Improve build tags
This commit is contained in:
parent
4c11eaac36
commit
a937ff2d8d
18 changed files with 360 additions and 280 deletions
1
go.mod
1
go.mod
|
@ -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
8
go.sum
|
@ -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=
|
||||
|
|
23
gvisor.go
23
gvisor.go
|
@ -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() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//go:build !no_gvisor
|
||||
//go:build !(no_gvisor || !(linux || windows || darwin))
|
||||
|
||||
package tun
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//go:build !no_gvisor
|
||||
//go:build !(no_gvisor || !(linux || windows || darwin))
|
||||
|
||||
package tun
|
||||
|
||||
|
|
16
gvisor_other.go
Normal file
16
gvisor_other.go
Normal 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
16
gvisor_stub.go
Normal 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
10
gvisor_tun.go
Normal 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)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
//go:build !no_gvisor
|
||||
//go:build !(no_gvisor || !(linux || windows || darwin))
|
||||
|
||||
package tun
|
||||
|
||||
|
|
12
stack.go
Normal file
12
stack.go
Normal 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
5
tun.go
|
@ -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
|
||||
}
|
||||
|
|
135
tun_darwin.go
135
tun_darwin.go
|
@ -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
138
tun_darwin_gvisor.go
Normal 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
|
||||
}
|
11
tun_linux.go
11
tun_linux.go
|
@ -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
17
tun_linux_gvisor.go
Normal 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,
|
||||
})
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
//go:build no_gvisor
|
||||
|
||||
package tun
|
||||
|
||||
type Tun interface {
|
||||
Close() error
|
||||
}
|
114
tun_windows.go
114
tun_windows.go
|
@ -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
121
tun_windows_gvisor.go
Normal 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
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue