[Fixed] Configure tun interface on linux
This commit is contained in:
parent
46b2d3b0c1
commit
ef28fde9db
1 changed files with 78 additions and 1 deletions
|
@ -11,6 +11,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
@ -54,6 +55,12 @@ func OpenTunDevice(tunAddress string, autoRoute bool) (TunDevice, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = t.configInterface()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if autoRoute {
|
if autoRoute {
|
||||||
SetLinuxAutoRoute()
|
SetLinuxAutoRoute()
|
||||||
}
|
}
|
||||||
|
@ -128,7 +135,9 @@ func (t *tunLinux) openDeviceByName(name string) (TunDevice, error) {
|
||||||
if len(nameBytes) >= unix.IFNAMSIZ {
|
if len(nameBytes) >= unix.IFNAMSIZ {
|
||||||
return nil, errors.New("interface name too long")
|
return nil, errors.New("interface name too long")
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(ifr[:], nameBytes)
|
copy(ifr[:], nameBytes)
|
||||||
|
|
||||||
*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags
|
*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags
|
||||||
|
|
||||||
_, _, errno := unix.Syscall(
|
_, _, errno := unix.Syscall(
|
||||||
|
@ -140,11 +149,11 @@ func (t *tunLinux) openDeviceByName(name string) (TunDevice, error) {
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
}
|
}
|
||||||
|
|
||||||
err = unix.SetNonblock(nfd, true)
|
err = unix.SetNonblock(nfd, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that the above -- open,ioctl,nonblock -- must happen prior to handing it to netpoll as below this line.
|
// 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)
|
t.tunFile = os.NewFile(uintptr(nfd), cloneDevicePath)
|
||||||
|
@ -157,6 +166,74 @@ func (t *tunLinux) openDeviceByName(name string) (TunDevice, error) {
|
||||||
return t, nil
|
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) {
|
func (t *tunLinux) openDeviceByFd(fd int) (TunDevice, error) {
|
||||||
var ifr struct {
|
var ifr struct {
|
||||||
name [16]byte
|
name [16]byte
|
||||||
|
|
Loading…
Reference in a new issue