]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
tun: use sysconn instead of .Fd with Go 1.12
authorJason A. Donenfeld <Jason@zx2c4.com>
Wed, 27 Feb 2019 00:06:43 +0000 (01:06 +0100)
committerJason A. Donenfeld <Jason@zx2c4.com>
Wed, 27 Feb 2019 00:34:11 +0000 (01:34 +0100)
README.md
tun/tun.go
tun/tun_darwin.go
tun/tun_freebsd.go
tun/tun_linux.go
tun/tun_openbsd.go

index cbdf4e3024696f6135ce719f8e39ff3ded06cbc5..b6a9f39c5879ed03da65f74aa9e414978a0e58c5 100644 (file)
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ This will run on OpenBSD. It does not yet support sticky sockets. Fwmark is mapp
 
 ## 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
index baf6fbb3e2a9bcd69d3576ae79c08b961c173de6..d9c3c151b058c42cdb1f2ea2fff1888f779eacc9 100644 (file)
@@ -5,7 +5,10 @@
 
 package tun
 
-import "os"
+import (
+       "fmt"
+       "os"
+)
 
 type TUNEvent int
 
@@ -24,3 +27,15 @@ type TUNDevice interface {
        Events() chan TUNEvent          // returns a constant channel of events related to the device
        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())
+       }
+}
\ No newline at end of file
index 9eef4e8c7385fd8c5e828cf1eebfe55c49a1b6b6..1190a9d91fd0c5788d0bb70d65e322a2d8fedc74 100644 (file)
@@ -8,9 +8,9 @@ package tun
 import (
        "errors"
        "fmt"
-       "golang.zx2c4.com/wireguard/rwcancel"
        "golang.org/x/net/ipv6"
        "golang.org/x/sys/unix"
+       "golang.zx2c4.com/wireguard/rwcancel"
        "io/ioutil"
        "net"
        "os"
@@ -36,7 +36,6 @@ type sockaddrCtl struct {
 type nativeTun struct {
        name        string
        tunFile     *os.File
-       fd          uintptr
        rwcancel    *rwcancel.RWCancel
        events      chan TUNEvent
        errors      chan error
@@ -168,10 +167,8 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
 }
 
 func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
-
        tun := &nativeTun{
                tunFile: file,
-               fd:      file.Fd(),
                events:  make(chan TUNEvent, 10),
                errors:  make(chan error, 1),
        }
@@ -194,7 +191,9 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
                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 {
                tun.tunFile.Close()
                return nil, err
@@ -218,19 +217,21 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
 }
 
 func (tun *nativeTun) Name() (string, error) {
-
        var ifName struct {
                name [16]byte
        }
        ifNameSize := uintptr(16)
 
-       _, _, errno := unix.Syscall6(
-               unix.SYS_GETSOCKOPT,
-               uintptr(tun.fd),
-               2, /* #define SYSPROTO_CONTROL 2 */
-               2, /* #define UTUN_OPT_IFNAME 2 */
-               uintptr(unsafe.Pointer(&ifName)),
-               uintptr(unsafe.Pointer(&ifNameSize)), 0)
+       var errno syscall.Errno
+       tun.operateOnFd(func(fd uintptr) {
+               _, _, errno = unix.Syscall6(
+                       unix.SYS_GETSOCKOPT,
+                       fd,
+                       2, /* #define SYSPROTO_CONTROL 2 */
+                       2, /* #define UTUN_OPT_IFNAME 2 */
+                       uintptr(unsafe.Pointer(&ifName)),
+                       uintptr(unsafe.Pointer(&ifNameSize)), 0)
+       })
 
        if errno != 0 {
                return "", fmt.Errorf("SYS_GETSOCKOPT: %v", errno)
index a2c456232c12806897abfbd16dc233da85c445f8..1aec123a3de734f8b13ec3587f0745d847f72d59 100644 (file)
@@ -9,9 +9,9 @@ import (
        "bytes"
        "errors"
        "fmt"
-       "golang.zx2c4.com/wireguard/rwcancel"
        "golang.org/x/net/ipv6"
        "golang.org/x/sys/unix"
+       "golang.zx2c4.com/wireguard/rwcancel"
        "net"
        "os"
        "syscall"
@@ -52,7 +52,6 @@ type ifstat struct {
 type nativeTun struct {
        name        string
        tunFile     *os.File
-       fd          uintptr
        rwcancel    *rwcancel.RWCancel
        events      chan TUNEvent
        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)
-
        if err != nil {
                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 {
                tunFile.Close()
                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
        ifheadmode := 1
-       _, _, errno := unix.Syscall(
-               unix.SYS_IOCTL,
-               uintptr(tunfd),
-               uintptr(_TUNSIFHEAD),
-               uintptr(unsafe.Pointer(&ifheadmode)),
-       )
+       var errno syscall.Errno
+       tun.operateOnFd(func(fd uintptr) {
+               _, _, errno = unix.Syscall(
+                       unix.SYS_IOCTL,
+                       fd,
+                       uintptr(_TUNSIFHEAD),
+                       uintptr(unsafe.Pointer(&ifheadmode)),
+               )
+       })
 
        if errno != 0 {
                return nil, fmt.Errorf("error %s", errno.Error())
@@ -306,7 +311,6 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
 
        tun := &nativeTun{
                tunFile: file,
-               fd:      file.Fd(),
                events:  make(chan TUNEvent, 10),
                errors:  make(chan error, 1),
        }
@@ -329,7 +333,9 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
                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 {
                tun.tunFile.Close()
                return nil, err
@@ -353,7 +359,11 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, 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 {
                return "", err
        }
index 7a0647f18c1fb2e7fb7edc90a0b12e4161cbf7f1..abdcce2a8331c1fe336e2657bb91ba93d513a0c3 100644 (file)
@@ -12,13 +12,14 @@ import (
        "bytes"
        "errors"
        "fmt"
-       "golang.zx2c4.com/wireguard/rwcancel"
        "golang.org/x/net/ipv6"
        "golang.org/x/sys/unix"
+       "golang.zx2c4.com/wireguard/rwcancel"
        "net"
        "os"
        "strconv"
        "sync"
+       "syscall"
        "time"
        "unsafe"
 )
@@ -30,7 +31,6 @@ const (
 
 type nativeTun struct {
        tunFile                 *os.File
-       fd                      uintptr
        fdCancel                *rwcancel.RWCancel
        index                   int32         // if index
        name                    string        // name of interface
@@ -52,9 +52,11 @@ func (tun *nativeTun) routineHackListener() {
        /* 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.
         */
-       fd := int(tun.fd)
        for {
-               _, err := unix.Write(fd, nil)
+               var err error
+               tun.operateOnFd(func(fd uintptr) {
+                       _, err = unix.Write(int(fd), nil)
+               })
                switch err {
                case unix.EINVAL:
                        tun.events <- TUNEventUp
@@ -162,16 +164,12 @@ func (tun *nativeTun) isUp() (bool, error) {
        return inter.Flags&net.FlagUp != 0, err
 }
 
-func getDummySock() (int, error) {
-       return unix.Socket(
+func getIFIndex(name string) (int32, error) {
+       fd, err := unix.Socket(
                unix.AF_INET,
                unix.SOCK_DGRAM,
                0,
        )
-}
-
-func getIFIndex(name string) (int32, error) {
-       fd, err := getDummySock()
        if err != nil {
                return 0, err
        }
@@ -195,9 +193,7 @@ func getIFIndex(name string) (int32, error) {
 }
 
 func (tun *nativeTun) setMTU(n int) error {
-
        // open datagram socket
-
        fd, err := unix.Socket(
                unix.AF_INET,
                unix.SOCK_DGRAM,
@@ -230,9 +226,7 @@ func (tun *nativeTun) setMTU(n int) error {
 }
 
 func (tun *nativeTun) MTU() (int, error) {
-
        // open datagram socket
-
        fd, err := unix.Socket(
                unix.AF_INET,
                unix.SOCK_DGRAM,
@@ -263,14 +257,16 @@ func (tun *nativeTun) MTU() (int, error) {
 }
 
 func (tun *nativeTun) Name() (string, error) {
-
        var ifr [ifReqSize]byte
-       _, _, errno := unix.Syscall(
-               unix.SYS_IOCTL,
-               tun.fd,
-               uintptr(unix.TUNGETIFF),
-               uintptr(unsafe.Pointer(&ifr[0])),
-       )
+       var errno syscall.Errno
+       tun.operateOnFd(func(fd uintptr) {
+               _, _, errno = unix.Syscall(
+                       unix.SYS_IOCTL,
+                       fd,
+                       uintptr(unix.TUNGETIFF),
+                       uintptr(unsafe.Pointer(&ifr[0])),
+               )
+       })
        if errno != 0 {
                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(
                unix.SYS_IOCTL,
-               fd.Fd(),
+               nfd,
                uintptr(unix.TUNSETIFF),
                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) {
        tun := &nativeTun{
                tunFile:                 file,
-               fd:                      file.Fd(),
                events:                  make(chan TUNEvent, 5),
                errors:                  make(chan error, 5),
                statusListenersShutdown: make(chan struct{}),
@@ -413,7 +408,9 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, 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 {
                tun.tunFile.Close()
                return nil, err
index ab4c87bf6a773face09ce970959f1a61668db2b2..b10c460c9eefeb05eadccaf49a313afd502926b9 100644 (file)
@@ -8,9 +8,9 @@ package tun
 import (
        "errors"
        "fmt"
-       "golang.zx2c4.com/wireguard/rwcancel"
        "golang.org/x/net/ipv6"
        "golang.org/x/sys/unix"
+       "golang.zx2c4.com/wireguard/rwcancel"
        "io/ioutil"
        "net"
        "os"
@@ -167,7 +167,9 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
                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 {
                tun.tunFile.Close()
                return nil, err