forked from mandelsoft/kubelink
-
Notifications
You must be signed in to change notification settings - Fork 0
/
taptun.go
133 lines (116 loc) · 3.43 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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
* Copyright 2020 Mandelsoft. All rights reserved.
* This file is licensed under the Apache Software License, v. 2 except as noted
* otherwise in the LICENSE file
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 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])
}