[Fixed] Configure tun interface on linux
This commit is contained in:
parent
9e44e21406
commit
69aef9cec0
1 changed files with 78 additions and 1 deletions
|
@ -11,6 +11,7 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
@ -54,6 +55,12 @@ func OpenTunDevice(tunAddress string, autoRoute bool) (TunDevice, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = t.configInterface()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if autoRoute {
|
||||
SetLinuxAutoRoute()
|
||||
}
|
||||
|
@ -128,7 +135,9 @@ func (t *tunLinux) openDeviceByName(name string) (TunDevice, error) {
|
|||
if len(nameBytes) >= unix.IFNAMSIZ {
|
||||
return nil, errors.New("interface name too long")
|
||||
}
|
||||
|
||||
copy(ifr[:], nameBytes)
|
||||
|
||||
*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags
|
||||
|
||||
_, _, errno := unix.Syscall(
|
||||
|
@ -140,11 +149,11 @@ func (t *tunLinux) openDeviceByName(name string) (TunDevice, error) {
|
|||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
err = unix.SetNonblock(nfd, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Note that the above -- open,ioctl,nonblock -- must happen prior to handing it to netpoll as below this line.
|
||||
|
||||
t.tunFile = os.NewFile(uintptr(nfd), cloneDevicePath)
|
||||
|
@ -157,6 +166,74 @@ func (t *tunLinux) openDeviceByName(name string) (TunDevice, error) {
|
|||
return t, nil
|
||||
}
|
||||
|
||||
func (t *tunLinux) configInterface() error {
|
||||
var ifr [ifReqSize]byte
|
||||
nameBytes := []byte(t.name)
|
||||
if len(nameBytes) >= unix.IFNAMSIZ {
|
||||
return errors.New("interface name too long")
|
||||
}
|
||||
|
||||
copy(ifr[:], nameBytes)
|
||||
|
||||
fd, _, errno := syscall.Syscall(unix.SYS_SOCKET, unix.AF_INET, unix.SOCK_STREAM, 0)
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
|
||||
// set addr for tun
|
||||
var ip []byte
|
||||
for _, num := range strings.Split(t.tunAddress, ".") {
|
||||
value, err := strconv.Atoi(num)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ip = append(ip, byte(value))
|
||||
}
|
||||
|
||||
*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint16(unix.AF_INET)
|
||||
|
||||
copy(ifr[unix.IFNAMSIZ+4:], ip)
|
||||
|
||||
_, _, errno = unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
fd,
|
||||
uintptr(unix.SIOCSIFADDR),
|
||||
uintptr(unsafe.Pointer(&ifr[0])))
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
|
||||
// set netmask for tun
|
||||
netmask := []byte{255, 255, 255, 0}
|
||||
copy(ifr[unix.IFNAMSIZ+4:], netmask)
|
||||
|
||||
_, _, errno = unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
fd,
|
||||
uintptr(unix.SIOCSIFNETMASK),
|
||||
uintptr(unsafe.Pointer(&ifr[0])))
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
|
||||
// interface up
|
||||
_, _, errno = syscall.Syscall(unix.SYS_IOCTL, fd, uintptr(unix.SIOCSIFFLAGS), uintptr(unsafe.Pointer(&ifr[0])))
|
||||
|
||||
var flags = uint16(unix.IFF_UP | unix.IFF_TUN | unix.IFF_MULTICAST | unix.IFF_RUNNING | unix.IFF_NOARP)
|
||||
*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags
|
||||
|
||||
_, _, errno = syscall.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
fd,
|
||||
uintptr(unix.SIOCSIFFLAGS),
|
||||
uintptr(unsafe.Pointer(&ifr[0])))
|
||||
if errno != 0 {
|
||||
return errno
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tunLinux) openDeviceByFd(fd int) (TunDevice, error) {
|
||||
var ifr struct {
|
||||
name [16]byte
|
||||
|
|
Loading…
Reference in a new issue