-
Notifications
You must be signed in to change notification settings - Fork 37
/
config.go
148 lines (134 loc) · 3.92 KB
/
config.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package tap0901
import (
"syscall"
"net"
"encoding/binary"
"golang.org/x/sys/windows/registry"
"golang.org/x/sys/windows"
"fmt"
)
const IO_BUFFER_NUM = 1024
const MAX_PROCS = 1024
type Tun struct {
ID string
MTU uint32
DevicePath string
FD syscall.Handle
NetworkName string
received chan []byte
toSend chan []byte
readReqs chan event
reusedOverlapped syscall.Overlapped // reuse for write
reusedEvent syscall.Handle
listening bool
readHandler func(tun *Tun, data []byte)
closeWorker chan bool
procs int
}
// OpenTun function open the tap0901 device and set config
// Params: addr -> the localIPAddr
// network -> remoteNetwork
// mask -> remoteNetmask
// The function configure a network for later actions
// The tun will process those transmit between local ip
// and remote network
func OpenTun(addr, network, mask net.IP) (*Tun, error) {
id, err := getTuntapComponentId()
if err != nil {
return nil, err
}
reusedE, err := windows.CreateEvent(nil, 0, 0, nil)
if err != nil {
return nil, err
}
tun := &Tun{
ID: id,
DevicePath: fmt.Sprintf(USERMODEDEVICEDIR+"%s"+TAP_WIN_SUFFIX, id),
received: make(chan []byte, IO_BUFFER_NUM),
toSend: make(chan []byte, IO_BUFFER_NUM),
readReqs: make(chan event, IO_BUFFER_NUM),
closeWorker: make(chan bool, MAX_PROCS),
procs: 0,
reusedEvent: syscall.Handle(reusedE),
}
tun.reusedOverlapped.HEvent = tun.reusedEvent
fName := syscall.StringToUTF16(tun.DevicePath)
tun.FD, err = syscall.CreateFile(
&fName[0],
syscall.GENERIC_READ|syscall.GENERIC_WRITE,
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
nil,
syscall.OPEN_EXISTING,
syscall.FILE_ATTRIBUTE_SYSTEM|syscall.FILE_FLAG_OVERLAPPED,
0,
)
if err != nil {
return nil, err
}
var returnLen uint32
configTunParam := append(addr.To4(), network.To4()...)
configTunParam = append(configTunParam, mask.To4()...)
err = syscall.DeviceIoControl(tun.FD, tap_ioctl(TAP_WIN_IOCTL_CONFIG_TUN),
&configTunParam[0], uint32(len(configTunParam)),
&configTunParam[0], uint32(len(configTunParam)), // I think here can be nil
&returnLen, nil)
if err != nil {
return nil, err
}
return tun, nil
}
func (tun *Tun) GetMTU(refresh bool) (uint32) {
if !refresh && tun.MTU != 0 {
return tun.MTU
}
var returnLen uint32
var umtu = make([]byte, 4)
err := syscall.DeviceIoControl(tun.FD, tap_ioctl(TAP_WIN_IOCTL_GET_MTU),
&umtu[0], uint32(len(umtu)),
&umtu[0], uint32(len(umtu)),
&returnLen, nil)
if err != nil {
return 0
}
tun.MTU = binary.LittleEndian.Uint32(umtu)
return tun.MTU
}
func (tun *Tun) Connect() error {
var returnLen uint32
inBuffer := []byte("\x01\x00\x00\x00") // only means TRUE
err := syscall.DeviceIoControl(
tun.FD, tap_ioctl(TAP_WIN_IOCTL_SET_MEDIA_STATUS),
&inBuffer[0], uint32(len(inBuffer)),
&inBuffer[0], uint32(len(inBuffer)),
&returnLen, nil)
return err
}
func (tun *Tun) SetDHCPMasq(dhcpAddr, dhcpMask, serverIP, leaseTime net.IP) error {
var returnLen uint32
configTunParam := append(dhcpAddr.To4(), dhcpMask.To4()...)
configTunParam = append(configTunParam, serverIP.To4()...)
configTunParam = append(configTunParam, leaseTime.To4()...)
err := syscall.DeviceIoControl(tun.FD, tap_ioctl(TAP_WIN_IOCTL_CONFIG_DHCP_MASQ),
&configTunParam[0], uint32(len(configTunParam)),
&configTunParam[0], uint32(len(configTunParam)), // I think here can be nil
&returnLen, nil)
return err
}
func (tun *Tun) GetNetworkName(refresh bool) string {
if !refresh && tun.NetworkName != "" {
return tun.NetworkName
}
keyName := `SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\` +
tun.ID + `\Connection`
k, err := registry.OpenKey(registry.LOCAL_MACHINE, keyName, registry.ALL_ACCESS)
if err != nil {
return ""
}
szname, _, err := k.GetStringValue("Name")
if err != nil {
return ""
}
k.Close()
tun.NetworkName = szname
return szname
}