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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
package socket
import (
"errors"
"fmt"
"golang.org/x/sys/unix"
"log"
"os"
"strings"
"sync"
"tunnel/pkg/pack"
"tunnel/pkg/server/env"
"tunnel/pkg/server/queue"
"unsafe"
)
const maxTunBufSize = 65535
var errPartialWrite = errors.New("partial write")
type ifReq struct {
name [unix.IFNAMSIZ]uint8
flags uint16
}
type tunSocket struct {
name string
}
type tunConn struct {
name string
s *tunSocket
fp *os.File
once sync.Once
}
func ioctl(fd int, req uintptr, ptr unsafe.Pointer) error {
_, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), req, uintptr(ptr))
if errno != 0 {
return errno
}
return nil
}
func newTunSocket(name string) (S, error) {
return &tunSocket{name: name}, nil
}
func (s *tunSocket) String() string {
return fmt.Sprintf("tun/%s", s.name)
}
func (s *tunSocket) Open(env.Env) (Conn, error) {
fd, err := unix.Open("/dev/net/tun", unix.O_RDWR, 0)
if err != nil {
return nil, err
}
ifr := &ifReq{}
copy(ifr.name[:], s.name)
ifr.flags = unix.IFF_TUN | unix.IFF_NO_PI
if err := ioctl(fd, unix.TUNSETIFF, unsafe.Pointer(ifr)); err != nil {
unix.Close(fd)
return nil, fmt.Errorf("ioctl TUNSETIFF %s: %w", s.name, err)
}
if err := unix.SetNonblock(fd, true); err != nil {
unix.Close(fd)
return nil, fmt.Errorf("set nonblock %s: %w", s.name, err)
}
c := &tunConn{
name: strings.Trim(string(ifr.name[:]), "\x00"),
fp: os.NewFile(uintptr(fd), "tun"),
}
return c, nil
}
func (s *tunSocket) Close() {
}
func (c *tunConn) Send(wq queue.Q) error {
buf := make([]byte, maxTunBufSize)
enc := pack.NewEncoder(wq.Writer())
for {
n, err := c.fp.Read(buf)
if err != nil {
return err
}
enc.Lps(buf[0:n])
}
}
func (c *tunConn) Recv(rq queue.Q) error {
dec := pack.NewDecoder(rq.Reader())
for {
b, err := dec.Lps()
if err != nil {
return err
}
n, err := c.fp.Write(b)
if err != nil {
return err
}
if n != len(b) {
return errPartialWrite
}
}
}
func (c *tunConn) String() string {
return "tun/" + c.name
}
func (c *tunConn) Close() error {
err := ErrAlreadyClosed
c.once.Do(func() {
log.Println("close", c)
err = c.fp.Close()
})
return err
}
|