|
@@ -21,28 +21,46 @@ type ifReq struct {
|
|
pad [0x28 - 0x10 - 2]byte
|
|
pad [0x28 - 0x10 - 2]byte
|
|
}
|
|
}
|
|
|
|
|
|
-func newTAP(ifName string) (ifce *Interface, err error) {
|
|
|
|
|
|
+func ioctl(fd uintptr, request int, argp uintptr) error {
|
|
|
|
+ _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(request), argp)
|
|
|
|
+ if errno != 0 {
|
|
|
|
+ return os.NewSyscallError("ioctl", errno)
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func newTAP(config Config) (ifce *Interface, err error) {
|
|
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
|
|
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
- name, err := createInterface(file.Fd(), ifName, cIFF_TAP|cIFF_NO_PI)
|
|
|
|
|
|
+ name, err := createInterface(file.Fd(), config.Name, cIFF_TAP|cIFF_NO_PI)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if err = setDeviceOptions(file.Fd(), config); err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
ifce = &Interface{isTAP: true, ReadWriteCloser: file, name: name}
|
|
ifce = &Interface{isTAP: true, ReadWriteCloser: file, name: name}
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
-func newTUN(ifName string) (ifce *Interface, err error) {
|
|
|
|
|
|
+func newTUN(config Config) (ifce *Interface, err error) {
|
|
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
|
|
file, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
- name, err := createInterface(file.Fd(), ifName, cIFF_TUN|cIFF_NO_PI)
|
|
|
|
|
|
+ name, err := createInterface(file.Fd(), config.Name, cIFF_TUN|cIFF_NO_PI)
|
|
if err != nil {
|
|
if err != nil {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if err = setDeviceOptions(file.Fd(), config); err != nil {
|
|
|
|
+ return nil, err
|
|
|
|
+ }
|
|
|
|
+
|
|
ifce = &Interface{isTAP: false, ReadWriteCloser: file, name: name}
|
|
ifce = &Interface{isTAP: false, ReadWriteCloser: file, name: name}
|
|
return
|
|
return
|
|
}
|
|
}
|
|
@@ -51,11 +69,37 @@ func createInterface(fd uintptr, ifName string, flags uint16) (createdIFName str
|
|
var req ifReq
|
|
var req ifReq
|
|
req.Flags = flags
|
|
req.Flags = flags
|
|
copy(req.Name[:], ifName)
|
|
copy(req.Name[:], ifName)
|
|
- _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TUNSETIFF), uintptr(unsafe.Pointer(&req)))
|
|
|
|
- if errno != 0 {
|
|
|
|
- err = errno
|
|
|
|
|
|
+
|
|
|
|
+ err = ioctl(fd, syscall.TUNSETIFF, uintptr(unsafe.Pointer(&req)))
|
|
|
|
+ if err != nil {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
+
|
|
createdIFName = strings.Trim(string(req.Name[:]), "\x00")
|
|
createdIFName = strings.Trim(string(req.Name[:]), "\x00")
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func setDeviceOptions(fd uintptr, config Config) (err error) {
|
|
|
|
+
|
|
|
|
+ // Device Permissions
|
|
|
|
+ if config.Permissions != nil {
|
|
|
|
+
|
|
|
|
+ // Set Owner
|
|
|
|
+ if err = ioctl(fd, syscall.TUNSETOWNER, uintptr(config.Permissions.Owner)); err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Set Group
|
|
|
|
+ if err = ioctl(fd, syscall.TUNSETGROUP, uintptr(config.Permissions.Group)); err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Set/Clear Persist Device Flag
|
|
|
|
+ value := 0
|
|
|
|
+ if config.Persist {
|
|
|
|
+ value = 1
|
|
|
|
+ }
|
|
|
|
+ return ioctl(fd, syscall.TUNSETPERSIST, uintptr(value))
|
|
|
|
+
|
|
|
|
+}
|