-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathtaptun.go
115 lines (99 loc) · 2.71 KB
/
taptun.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
// Package taptun provides an interface to the user level network
// TAP / TUN device.
//
// https://www.kernel.org/doc/Documentation/networking/tuntap.txt
package taptun
import (
"bytes"
"fmt"
"io"
"syscall"
"unsafe"
)
// NewTun creates a *Tun device with the specified name and returns the
// device connected to the tun interface.
//
// If an empty string ("") is specified for name, a tunN interface is
// created.
func NewTun(name string) (*Tun, error) {
n, f, err := openTun(name)
return &Tun{
ReadWriteCloser: f,
name: n,
}, err
}
// OpenTun creates a tunN interface and returns a *Tun device connected to
// the tun interface.
func OpenTun() (*Tun, error) {
return NewTun("")
}
// Tun represents a TUN Virtual Point-to-Point network device.
type Tun struct {
io.ReadWriteCloser
name string
}
func (t *Tun) String() string {
return t.name
}
func (t *Tun) Close() error {
if err := t.ReadWriteCloser.Close(); err != nil {
return err
}
return destroyInterface(t.name)
}
// NewTap creates a *Tap device with the specified name and returns the
// device connected to the tap interface.
//
// If an empty string ("") is specified for name, a tapN interface is
// created.
func NewTap(name string) (*Tap, error) {
n, f, err := openTap(name)
return &Tap{
ReadWriteCloser: f,
name: n,
}, err
}
// OpenTap creates a tapN interface and returns a *Tap device connected to
// the tap interface.
func OpenTap() (*Tap, error) {
return NewTap("")
}
// Tap represents a TAP Virtual Ethernet network device.
type Tap struct {
io.ReadWriteCloser
name string
}
func (t *Tap) String() string {
return t.name
}
func (t *Tap) Close() error {
if err := t.ReadWriteCloser.Close(); err != nil {
return err
}
return destroyInterface(t.name)
}
// ErrTruncated indicates the buffer supplied to ReadFrame was insufficient
// to hold the ingress frame.
type ErrTruncated struct {
length int
}
func (e ErrTruncated) Error() string {
return fmt.Sprintf("supplied buffer was not large enough, frame truncated at %v", e.length)
}
// ReadFrame reads a single frame from the tap device.
// The buffer supplied must be large enough to hold the whole frame including a 4 byte header returned by the kernel.
// If the buffer is not large enough to hold the entire frame and error of type ErrTruncated will be returned.
func ReadFrame(tap *Tap, buf []byte) ([]byte, error) {
n, err := tap.Read(buf)
return buf[:n], err
}
func ioctl(fd, request uintptr, argp unsafe.Pointer) error {
if _, _, e := syscall.Syscall6(syscall.SYS_IOCTL, fd, request, uintptr(argp), 0, 0, 0); e != 0 {
return e
}
return nil
}
func cstringToGoString(cstring []byte) string {
strs := bytes.Split(cstring, []byte{0x00})
return string(strs[0])
}