Fixed TUN interface implementation os OS X
This commit is contained in:
		
							parent
							
								
									c24b883c01
								
							
						
					
					
						commit
						89d0045214
					
				@ -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
 | 
			
		||||
var _ io.ReadWriteCloser = (*NativeTUN)(nil)
 | 
			
		||||
 | 
			
		||||
	rMu  sync.Mutex
 | 
			
		||||
	rBuf []byte
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user