mirror of
https://git.zx2c4.com/wireguard-go
synced 2024-11-15 01:05:15 +01:00
tun: use sysconn instead of .Fd with Go 1.12
This commit is contained in:
parent
66524c1f7e
commit
ab0f442daf
@ -48,7 +48,7 @@ This will run on OpenBSD. It does not yet support sticky sockets. Fwmark is mapp
|
|||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
This requires an installation of [go](https://golang.org) ≥ 1.11.
|
This requires an installation of [go](https://golang.org) ≥ 1.12.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git clone https://git.zx2c4.com/wireguard-go
|
$ git clone https://git.zx2c4.com/wireguard-go
|
||||||
|
17
tun/tun.go
17
tun/tun.go
@ -5,7 +5,10 @@
|
|||||||
|
|
||||||
package tun
|
package tun
|
||||||
|
|
||||||
import "os"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
type TUNEvent int
|
type TUNEvent int
|
||||||
|
|
||||||
@ -24,3 +27,15 @@ type TUNDevice interface {
|
|||||||
Events() chan TUNEvent // returns a constant channel of events related to the device
|
Events() chan TUNEvent // returns a constant channel of events related to the device
|
||||||
Close() error // stops the device and closes the event channel
|
Close() error // stops the device and closes the event channel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tun *nativeTun) operateOnFd(fn func(fd uintptr)) {
|
||||||
|
sysconn, err := tun.tunFile.SyscallConn()
|
||||||
|
if err != nil {
|
||||||
|
tun.errors <- fmt.Errorf("unable to find sysconn for tunfile: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = sysconn.Control(fn)
|
||||||
|
if err != nil {
|
||||||
|
tun.errors <- fmt.Errorf("unable to control sysconn for tunfile: %s", err.Error())
|
||||||
|
}
|
||||||
|
}
|
@ -8,9 +8,9 @@ package tun
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.zx2c4.com/wireguard/rwcancel"
|
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
"golang.zx2c4.com/wireguard/rwcancel"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@ -36,7 +36,6 @@ type sockaddrCtl struct {
|
|||||||
type nativeTun struct {
|
type nativeTun struct {
|
||||||
name string
|
name string
|
||||||
tunFile *os.File
|
tunFile *os.File
|
||||||
fd uintptr
|
|
||||||
rwcancel *rwcancel.RWCancel
|
rwcancel *rwcancel.RWCancel
|
||||||
events chan TUNEvent
|
events chan TUNEvent
|
||||||
errors chan error
|
errors chan error
|
||||||
@ -168,10 +167,8 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||||
|
|
||||||
tun := &nativeTun{
|
tun := &nativeTun{
|
||||||
tunFile: file,
|
tunFile: file,
|
||||||
fd: file.Fd(),
|
|
||||||
events: make(chan TUNEvent, 10),
|
events: make(chan TUNEvent, 10),
|
||||||
errors: make(chan error, 1),
|
errors: make(chan error, 1),
|
||||||
}
|
}
|
||||||
@ -194,7 +191,9 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tun.rwcancel, err = rwcancel.NewRWCancel(int(tun.fd))
|
tun.operateOnFd(func (fd uintptr) {
|
||||||
|
tun.rwcancel, err = rwcancel.NewRWCancel(int(fd))
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tun.tunFile.Close()
|
tun.tunFile.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -218,19 +217,21 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tun *nativeTun) Name() (string, error) {
|
func (tun *nativeTun) Name() (string, error) {
|
||||||
|
|
||||||
var ifName struct {
|
var ifName struct {
|
||||||
name [16]byte
|
name [16]byte
|
||||||
}
|
}
|
||||||
ifNameSize := uintptr(16)
|
ifNameSize := uintptr(16)
|
||||||
|
|
||||||
_, _, errno := unix.Syscall6(
|
var errno syscall.Errno
|
||||||
unix.SYS_GETSOCKOPT,
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
uintptr(tun.fd),
|
_, _, errno = unix.Syscall6(
|
||||||
2, /* #define SYSPROTO_CONTROL 2 */
|
unix.SYS_GETSOCKOPT,
|
||||||
2, /* #define UTUN_OPT_IFNAME 2 */
|
fd,
|
||||||
uintptr(unsafe.Pointer(&ifName)),
|
2, /* #define SYSPROTO_CONTROL 2 */
|
||||||
uintptr(unsafe.Pointer(&ifNameSize)), 0)
|
2, /* #define UTUN_OPT_IFNAME 2 */
|
||||||
|
uintptr(unsafe.Pointer(&ifName)),
|
||||||
|
uintptr(unsafe.Pointer(&ifNameSize)), 0)
|
||||||
|
})
|
||||||
|
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return "", fmt.Errorf("SYS_GETSOCKOPT: %v", errno)
|
return "", fmt.Errorf("SYS_GETSOCKOPT: %v", errno)
|
||||||
|
@ -9,9 +9,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.zx2c4.com/wireguard/rwcancel"
|
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
"golang.zx2c4.com/wireguard/rwcancel"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
@ -52,7 +52,6 @@ type ifstat struct {
|
|||||||
type nativeTun struct {
|
type nativeTun struct {
|
||||||
name string
|
name string
|
||||||
tunFile *os.File
|
tunFile *os.File
|
||||||
fd uintptr
|
|
||||||
rwcancel *rwcancel.RWCancel
|
rwcancel *rwcancel.RWCancel
|
||||||
events chan TUNEvent
|
events chan TUNEvent
|
||||||
errors chan error
|
errors chan error
|
||||||
@ -239,12 +238,15 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tunFile, err := os.OpenFile("/dev/tun", unix.O_RDWR, 0)
|
tunFile, err := os.OpenFile("/dev/tun", unix.O_RDWR, 0)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tunfd := tunFile.Fd()
|
|
||||||
assignedName, err := tunName(tunfd)
|
tun := nativeTun{tunFile: tunFile}
|
||||||
|
var assignedName string
|
||||||
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
|
assignedName, err = tunName(fd)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tunFile.Close()
|
tunFile.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -252,12 +254,15 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
|||||||
|
|
||||||
// Enable ifhead mode, otherwise tun will complain if it gets a non-AF_INET packet
|
// Enable ifhead mode, otherwise tun will complain if it gets a non-AF_INET packet
|
||||||
ifheadmode := 1
|
ifheadmode := 1
|
||||||
_, _, errno := unix.Syscall(
|
var errno syscall.Errno
|
||||||
unix.SYS_IOCTL,
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
uintptr(tunfd),
|
_, _, errno = unix.Syscall(
|
||||||
uintptr(_TUNSIFHEAD),
|
unix.SYS_IOCTL,
|
||||||
uintptr(unsafe.Pointer(&ifheadmode)),
|
fd,
|
||||||
)
|
uintptr(_TUNSIFHEAD),
|
||||||
|
uintptr(unsafe.Pointer(&ifheadmode)),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return nil, fmt.Errorf("error %s", errno.Error())
|
return nil, fmt.Errorf("error %s", errno.Error())
|
||||||
@ -306,7 +311,6 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
|||||||
|
|
||||||
tun := &nativeTun{
|
tun := &nativeTun{
|
||||||
tunFile: file,
|
tunFile: file,
|
||||||
fd: file.Fd(),
|
|
||||||
events: make(chan TUNEvent, 10),
|
events: make(chan TUNEvent, 10),
|
||||||
errors: make(chan error, 1),
|
errors: make(chan error, 1),
|
||||||
}
|
}
|
||||||
@ -329,7 +333,9 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tun.rwcancel, err = rwcancel.NewRWCancel(int(tun.fd))
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
|
tun.rwcancel, err = rwcancel.NewRWCancel(int(fd))
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tun.tunFile.Close()
|
tun.tunFile.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -353,7 +359,11 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tun *nativeTun) Name() (string, error) {
|
func (tun *nativeTun) Name() (string, error) {
|
||||||
name, err := tunName(tun.fd)
|
var name string
|
||||||
|
var err error
|
||||||
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
|
name, err = tunName(fd)
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,14 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.zx2c4.com/wireguard/rwcancel"
|
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
"golang.zx2c4.com/wireguard/rwcancel"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@ -30,7 +31,6 @@ const (
|
|||||||
|
|
||||||
type nativeTun struct {
|
type nativeTun struct {
|
||||||
tunFile *os.File
|
tunFile *os.File
|
||||||
fd uintptr
|
|
||||||
fdCancel *rwcancel.RWCancel
|
fdCancel *rwcancel.RWCancel
|
||||||
index int32 // if index
|
index int32 // if index
|
||||||
name string // name of interface
|
name string // name of interface
|
||||||
@ -52,9 +52,11 @@ func (tun *nativeTun) routineHackListener() {
|
|||||||
/* This is needed for the detection to work across network namespaces
|
/* This is needed for the detection to work across network namespaces
|
||||||
* If you are reading this and know a better method, please get in touch.
|
* If you are reading this and know a better method, please get in touch.
|
||||||
*/
|
*/
|
||||||
fd := int(tun.fd)
|
|
||||||
for {
|
for {
|
||||||
_, err := unix.Write(fd, nil)
|
var err error
|
||||||
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
|
_, err = unix.Write(int(fd), nil)
|
||||||
|
})
|
||||||
switch err {
|
switch err {
|
||||||
case unix.EINVAL:
|
case unix.EINVAL:
|
||||||
tun.events <- TUNEventUp
|
tun.events <- TUNEventUp
|
||||||
@ -162,16 +164,12 @@ func (tun *nativeTun) isUp() (bool, error) {
|
|||||||
return inter.Flags&net.FlagUp != 0, err
|
return inter.Flags&net.FlagUp != 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDummySock() (int, error) {
|
func getIFIndex(name string) (int32, error) {
|
||||||
return unix.Socket(
|
fd, err := unix.Socket(
|
||||||
unix.AF_INET,
|
unix.AF_INET,
|
||||||
unix.SOCK_DGRAM,
|
unix.SOCK_DGRAM,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
func getIFIndex(name string) (int32, error) {
|
|
||||||
fd, err := getDummySock()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -195,9 +193,7 @@ func getIFIndex(name string) (int32, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tun *nativeTun) setMTU(n int) error {
|
func (tun *nativeTun) setMTU(n int) error {
|
||||||
|
|
||||||
// open datagram socket
|
// open datagram socket
|
||||||
|
|
||||||
fd, err := unix.Socket(
|
fd, err := unix.Socket(
|
||||||
unix.AF_INET,
|
unix.AF_INET,
|
||||||
unix.SOCK_DGRAM,
|
unix.SOCK_DGRAM,
|
||||||
@ -230,9 +226,7 @@ func (tun *nativeTun) setMTU(n int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tun *nativeTun) MTU() (int, error) {
|
func (tun *nativeTun) MTU() (int, error) {
|
||||||
|
|
||||||
// open datagram socket
|
// open datagram socket
|
||||||
|
|
||||||
fd, err := unix.Socket(
|
fd, err := unix.Socket(
|
||||||
unix.AF_INET,
|
unix.AF_INET,
|
||||||
unix.SOCK_DGRAM,
|
unix.SOCK_DGRAM,
|
||||||
@ -263,14 +257,16 @@ func (tun *nativeTun) MTU() (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tun *nativeTun) Name() (string, error) {
|
func (tun *nativeTun) Name() (string, error) {
|
||||||
|
|
||||||
var ifr [ifReqSize]byte
|
var ifr [ifReqSize]byte
|
||||||
_, _, errno := unix.Syscall(
|
var errno syscall.Errno
|
||||||
unix.SYS_IOCTL,
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
tun.fd,
|
_, _, errno = unix.Syscall(
|
||||||
uintptr(unix.TUNGETIFF),
|
unix.SYS_IOCTL,
|
||||||
uintptr(unsafe.Pointer(&ifr[0])),
|
fd,
|
||||||
)
|
uintptr(unix.TUNGETIFF),
|
||||||
|
uintptr(unsafe.Pointer(&ifr[0])),
|
||||||
|
)
|
||||||
|
})
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return "", errors.New("failed to get name of TUN device: " + strconv.FormatInt(int64(errno), 10))
|
return "", errors.New("failed to get name of TUN device: " + strconv.FormatInt(int64(errno), 10))
|
||||||
}
|
}
|
||||||
@ -391,7 +387,7 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
|||||||
|
|
||||||
_, _, errno := unix.Syscall(
|
_, _, errno := unix.Syscall(
|
||||||
unix.SYS_IOCTL,
|
unix.SYS_IOCTL,
|
||||||
fd.Fd(),
|
nfd,
|
||||||
uintptr(unix.TUNSETIFF),
|
uintptr(unix.TUNSETIFF),
|
||||||
uintptr(unsafe.Pointer(&ifr[0])),
|
uintptr(unsafe.Pointer(&ifr[0])),
|
||||||
)
|
)
|
||||||
@ -405,7 +401,6 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
|||||||
func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||||
tun := &nativeTun{
|
tun := &nativeTun{
|
||||||
tunFile: file,
|
tunFile: file,
|
||||||
fd: file.Fd(),
|
|
||||||
events: make(chan TUNEvent, 5),
|
events: make(chan TUNEvent, 5),
|
||||||
errors: make(chan error, 5),
|
errors: make(chan error, 5),
|
||||||
statusListenersShutdown: make(chan struct{}),
|
statusListenersShutdown: make(chan struct{}),
|
||||||
@ -413,7 +408,9 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
|||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
tun.fdCancel, err = rwcancel.NewRWCancel(int(tun.fd))
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
|
tun.fdCancel, err = rwcancel.NewRWCancel(int(fd))
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tun.tunFile.Close()
|
tun.tunFile.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -8,9 +8,9 @@ package tun
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.zx2c4.com/wireguard/rwcancel"
|
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
|
"golang.zx2c4.com/wireguard/rwcancel"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@ -167,7 +167,9 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tun.rwcancel, err = rwcancel.NewRWCancel(int(file.Fd()))
|
tun.operateOnFd(func(fd uintptr) {
|
||||||
|
tun.rwcancel, err = rwcancel.NewRWCancel(int(fd))
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tun.tunFile.Close()
|
tun.tunFile.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Loading…
Reference in New Issue
Block a user