forked from SagerNet/sing-tun
-
Notifications
You must be signed in to change notification settings - Fork 21
/
tun_windows_gvisor.go
119 lines (101 loc) · 2.61 KB
/
tun_windows_gvisor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//go:build with_gvisor && windows
package tun
import (
"github.com/metacubex/gvisor/pkg/buffer"
"github.com/metacubex/gvisor/pkg/tcpip"
"github.com/metacubex/gvisor/pkg/tcpip/header"
"github.com/metacubex/gvisor/pkg/tcpip/stack"
)
var _ GVisorTun = (*NativeTun)(nil)
func (t *NativeTun) NewEndpoint() (stack.LinkEndpoint, error) {
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.options.MTU
}
func (e *WintunEndpoint) MaxHeaderLength() uint16 {
return 0
}
func (e *WintunEndpoint) LinkAddress() tcpip.LinkAddress {
return ""
}
func (e *WintunEndpoint) Capabilities() stack.LinkEndpointCapabilities {
return stack.CapabilityRXChecksumOffload
}
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() {
for {
var packetBuffer buffer.Buffer
err := e.tun.ReadFunc(func(b []byte) {
packetBuffer = buffer.MakeWithData(b)
})
if err != nil {
break
}
ihl, ok := packetBuffer.PullUp(0, 1)
if !ok {
packetBuffer.Release()
continue
}
var networkProtocol tcpip.NetworkProtocolNumber
switch header.IPVersion(ihl.AsSlice()) {
case header.IPv4Version:
networkProtocol = header.IPv4ProtocolNumber
case header.IPv6Version:
networkProtocol = header.IPv6ProtocolNumber
default:
e.tun.Write(packetBuffer.Flatten())
packetBuffer.Release()
continue
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Payload: packetBuffer,
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) ParseHeader(ptr *stack.PacketBuffer) bool {
return true
}
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
}