summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2017-09-03 18:10:06 +0200
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2017-09-03 18:10:06 +0200
commit89d00452144dd1f517e90b4ea4c72ca9ee12ba3b (patch)
treed9d6315b84a344c7042c2d7e6125ce017f0386a9
parentc24b883c01fc932dd28add1ac0319459a007d498 (diff)
Fixed TUN interface implementation os OS X
-rw-r--r--src/tun_darwin.go91
-rw-r--r--src/uapi_darwin.go24
-rw-r--r--src/uapi_linux.go6
3 files changed, 91 insertions, 30 deletions
diff --git a/src/tun_darwin.go b/src/tun_darwin.go
index 146817d..87f6af6 100644
--- a/src/tun_darwin.go
+++ b/src/tun_darwin.go
@@ -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
diff --git a/src/uapi_darwin.go b/src/uapi_darwin.go
index 9eee53c..13e5c4f 100644
--- a/src/uapi_darwin.go
+++ b/src/uapi_darwin.go
@@ -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
diff --git a/src/uapi_linux.go b/src/uapi_linux.go
index b5dd663..db4f040 100644
--- a/src/uapi_linux.go
+++ b/src/uapi_linux.go
@@ -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