]> git.ipfire.org Git - thirdparty/wireguard-go.git/commitdiff
Fixed TUN interface implementation os OS X
authorMathias Hall-Andersen <mathias@hall-andersen.dk>
Sun, 3 Sep 2017 16:10:06 +0000 (18:10 +0200)
committerMathias Hall-Andersen <mathias@hall-andersen.dk>
Sun, 3 Sep 2017 16:10:06 +0000 (18:10 +0200)
src/tun_darwin.go
src/uapi_darwin.go
src/uapi_linux.go

index 146817d2c86874992c13208ea561bd0230c421d5..87f6af6b20e7e5f154b0cb8d2bad5c959e7d4d07 100644 (file)
@@ -14,8 +14,10 @@ import (
        "golang.org/x/net/ipv6"
        "golang.org/x/sys/unix"
        "io"
+       "net"
        "os"
        "sync"
+       "time"
        "unsafe"
 )
 
@@ -34,6 +36,23 @@ type sockaddrCtl struct {
        scReserved [5]uint32
 }
 
+// NativeTUN is a hack to work around the first 4 bytes "packet
+// information" because there doesn't seem to be an IFF_NO_PI for darwin.
+type NativeTUN struct {
+       name string
+       f    io.ReadWriteCloser
+       mtu  int
+
+       rMu  sync.Mutex
+       rBuf []byte
+
+       wMu  sync.Mutex
+       wBuf []byte
+
+       events chan TUNEvent
+       errors chan error
+}
+
 var sockaddrCtlSize uintptr = 32
 
 func CreateTUN(name string) (ifce TUNDevice, err error) {
@@ -110,12 +129,48 @@ func CreateTUN(name string) (ifce TUNDevice, err error) {
                return nil, fmt.Errorf("error in unix.Syscall6(unix.SYS_GETSOCKOPT, ...): %v", err)
        }
 
-       device := &tunReadCloser{
-               name: string(ifName.name[:ifNameSize-1 /* -1 is for \0 */]),
-               f:    os.NewFile(uintptr(fd), string(ifName.name[:])),
-               mtu:  1500,
+       device := &NativeTUN{
+               name:   string(ifName.name[:ifNameSize-1 /* -1 is for \0 */]),
+               f:      os.NewFile(uintptr(fd), string(ifName.name[:])),
+               mtu:    1500,
+               events: make(chan TUNEvent, 10),
+               errors: make(chan error, 1),
        }
 
+       // start listener
+
+       go func(native *NativeTUN) {
+               // TODO: Fix this very niave implementation
+               var (
+                       statusUp  bool
+                       statusMTU int
+               )
+
+               for ; ; time.Sleep(time.Second) {
+                       intr, err := net.InterfaceByName(device.name)
+                       if err != nil {
+                               native.errors <- err
+                               return
+                       }
+
+                       // Up / Down event
+                       up := (intr.Flags & net.FlagUp) != 0
+                       if up != statusUp && up {
+                               native.events <- TUNEventUp
+                       }
+                       if up != statusUp && !up {
+                               native.events <- TUNEventDown
+                       }
+                       statusUp = up
+
+                       // MTU changes
+                       if intr.MTU != statusMTU {
+                               native.events <- TUNEventMTUUpdate
+                       }
+                       statusMTU = intr.MTU
+               }
+       }(device)
+
        // set default MTU
 
        err = device.setMTU(DefaultMTU)
@@ -123,23 +178,13 @@ func CreateTUN(name string) (ifce TUNDevice, err error) {
        return device, err
 }
 
-// tunReadCloser is a hack to work around the first 4 bytes "packet
-// information" because there doesn't seem to be an IFF_NO_PI for darwin.
-type tunReadCloser struct {
-       name string
-       f    io.ReadWriteCloser
-       mtu  int
-
-       rMu  sync.Mutex
-       rBuf []byte
+var _ io.ReadWriteCloser = (*NativeTUN)(nil)
 
-       wMu  sync.Mutex
-       wBuf []byte
+func (t *NativeTUN) Events() chan TUNEvent {
+       return t.events
 }
 
-var _ io.ReadWriteCloser = (*tunReadCloser)(nil)
-
-func (t *tunReadCloser) Read(to []byte) (int, error) {
+func (t *NativeTUN) Read(to []byte) (int, error) {
        t.rMu.Lock()
        defer t.rMu.Unlock()
 
@@ -153,7 +198,7 @@ func (t *tunReadCloser) Read(to []byte) (int, error) {
        return n - 4, err
 }
 
-func (t *tunReadCloser) Write(from []byte) (int, error) {
+func (t *NativeTUN) Write(from []byte) (int, error) {
 
        if len(from) == 0 {
                return 0, unix.EIO
@@ -184,7 +229,7 @@ func (t *tunReadCloser) Write(from []byte) (int, error) {
        return n - 4, err
 }
 
-func (t *tunReadCloser) Close() error {
+func (t *NativeTUN) Close() error {
 
        // lock to make sure no read/write is in process.
 
@@ -197,11 +242,11 @@ func (t *tunReadCloser) Close() error {
        return t.f.Close()
 }
 
-func (t *tunReadCloser) Name() string {
+func (t *NativeTUN) Name() string {
        return t.name
 }
 
-func (t *tunReadCloser) setMTU(n int) error {
+func (t *NativeTUN) setMTU(n int) error {
 
        // open datagram socket
 
@@ -238,7 +283,7 @@ func (t *tunReadCloser) setMTU(n int) error {
        return nil
 }
 
-func (t *tunReadCloser) MTU() (int, error) {
+func (t *NativeTUN) MTU() (int, error) {
 
        // open datagram socket
 
index 9eee53c9fc943f403e69baf798b90795b43a1a18..13e5c4f1abb02336c8d1cbd6abf0823218b04607 100644 (file)
@@ -2,11 +2,22 @@ package main
 
 import (
        "fmt"
+       "golang.org/x/sys/unix"
        "net"
        "os"
+       "path"
        "time"
 )
 
+const (
+       ipcErrorIO         = -int64(unix.EIO)
+       ipcErrorNotDefined = -int64(unix.ENODEV)
+       ipcErrorProtocol   = -int64(unix.EPROTO)
+       ipcErrorInvalid    = -int64(unix.EINVAL)
+       socketDirectory    = "/var/run/wireguard"
+       socketName         = "%s.sock"
+)
+
 type UAPIListener struct {
        listener net.Listener // unix socket listener
        connNew  chan net.Conn
@@ -35,9 +46,20 @@ func (l *UAPIListener) Addr() net.Addr {
 
 func NewUAPIListener(name string) (net.Listener, error) {
 
+       // check if path exist
+
+       err := os.MkdirAll(socketDirectory, 077)
+       if err != nil && !os.IsExist(err) {
+               return nil, err
+       }
+
        // open UNIX socket
 
-       socketPath := fmt.Sprintf("/var/run/wireguard/%s.sock", name)
+       socketPath := path.Join(
+               socketDirectory,
+               fmt.Sprintf(socketName, name),
+       )
+
        listener, err := net.Listen("unix", socketPath)
        if err != nil {
                return nil, err
index b5dd663c867602a480eb18c08fad75b6e74752c6..db4f04018c62695a7e4f70ebcb1add4eecee129a 100644 (file)
@@ -18,12 +18,6 @@ const (
        socketName         = "%s.sock"
 )
 
-/* TODO:
- * This code can be improved by using fsnotify once:
- * https://github.com/fsnotify/fsnotify/pull/205
- * Is merged
- */
-
 type UAPIListener struct {
        listener  net.Listener // unix socket listener
        connNew   chan net.Conn