From 258a9223b9ab18a973c44b238e029a0dc5640102 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 3 May 2018 04:49:35 +0200 Subject: [PATCH 1/7] Start to dust off Darwin --- daemon_linux.go => daemon.go | 9 +- daemon_darwin.go | 9 -- daemon_windows.go | 34 ------ main.go | 2 + tun_darwin.go | 194 +++++++++++++++-------------------- uapi_darwin.go | 79 +++++++++++--- warning_default.go | 19 ++++ warning_linux.go | 39 +++++++ 8 files changed, 206 insertions(+), 179 deletions(-) rename daemon_linux.go => daemon.go (55%) delete mode 100644 daemon_darwin.go delete mode 100644 daemon_windows.go create mode 100644 warning_default.go create mode 100644 warning_linux.go diff --git a/daemon_linux.go b/daemon.go similarity index 55% rename from daemon_linux.go rename to daemon.go index e1aaede..e2ded87 100644 --- a/daemon_linux.go +++ b/daemon.go @@ -2,17 +2,10 @@ package main import ( "os" - "os/exec" ) -/* Daemonizes the process on linux - * - * This is done by spawning and releasing a copy with the --foreground flag - */ func Daemonize(attr *os.ProcAttr) error { - // I would like to use os.Executable, - // however this means dropping support for Go <1.8 - path, err := exec.LookPath(os.Args[0]) + path, err := os.Executable() if err != nil { return err } diff --git a/daemon_darwin.go b/daemon_darwin.go deleted file mode 100644 index 913af0e..0000000 --- a/daemon_darwin.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "errors" -) - -func Daemonize() error { - return errors.New("Not implemented on OSX") -} diff --git a/daemon_windows.go b/daemon_windows.go deleted file mode 100644 index 527718a..0000000 --- a/daemon_windows.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "os" -) - -/* Daemonizes the process on windows - * - * This is done by spawning and releasing a copy with the --foreground flag - */ - -func Daemonize() error { - argv := []string{os.Args[0], "--foreground"} - argv = append(argv, os.Args[1:]...) - attr := &os.ProcAttr{ - Dir: ".", - Env: os.Environ(), - Files: []*os.File{ - os.Stdin, - nil, - nil, - }, - } - process, err := os.StartProcess( - argv[0], - argv, - attr, - ) - if err != nil { - return err - } - process.Release() - return nil -} diff --git a/main.go b/main.go index 7742eef..3358469 100644 --- a/main.go +++ b/main.go @@ -25,6 +25,8 @@ func printUsage() { func main() { + Warning() + // parse arguments var foreground bool diff --git a/tun_darwin.go b/tun_darwin.go index 87f6af6..d03ff48 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -1,22 +1,12 @@ -/* Copyright (c) 2016, Song Gao - * All rights reserved. - * - * Code from https://github.com/songgao/water - */ - package main import ( "encoding/binary" - "errors" "fmt" - "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" "golang.org/x/sys/unix" - "io" "net" "os" - "sync" "time" "unsafe" ) @@ -36,26 +26,20 @@ type sockaddrCtl struct { scReserved [5]uint32 } -// NativeTUN is a hack to work around the first 4 bytes "packet +// 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 { +type NativeTun struct { name string - f io.ReadWriteCloser + fd *os.File 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) { +func CreateTUN(name string) (TUNDevice, error) { ifIndex := -1 fmt.Sscanf(name, "utun%d", &ifIndex) if ifIndex < 0 { @@ -65,7 +49,7 @@ func CreateTUN(name string) (ifce TUNDevice, err error) { fd, err := unix.Socket(unix.AF_SYSTEM, unix.SOCK_DGRAM, 2) if err != nil { - return nil, fmt.Errorf("error in unix.Socket: %v", err) + return nil, err } var ctlInfo = &struct { @@ -83,8 +67,7 @@ func CreateTUN(name string) (ifce TUNDevice, err error) { ) if errno != 0 { - err = errno - return nil, fmt.Errorf("error in unix.Syscall(unix.SYS_IOTL, ...): %v", err) + return nil, fmt.Errorf("_CTLIOCGINFO: %v", errno) } sc := sockaddrCtl{ @@ -105,148 +88,133 @@ func CreateTUN(name string) (ifce TUNDevice, err error) { ) if errno != 0 { - err = errno - return nil, fmt.Errorf("error in unix.RawSyscall(unix.SYS_CONNECT, ...): %v", err) + return nil, fmt.Errorf("SYS_CONNECT: %v", errno) } - // read (new) name of interface + return CreateTUNFromFile(os.NewFile(uintptr(fd), "")) +} - var ifName struct { - name [16]byte - } - ifNameSize := uintptr(16) +func CreateTUNFromFile(file *os.File) (TUNDevice, error) { - _, _, errno = unix.Syscall6( - unix.SYS_GETSOCKOPT, - uintptr(fd), - 2, /* #define SYSPROTO_CONTROL 2 */ - 2, /* #define UTUN_OPT_IFNAME 2 */ - uintptr(unsafe.Pointer(&ifName)), - uintptr(unsafe.Pointer(&ifNameSize)), 0) - - if errno != 0 { - err = errno - return nil, fmt.Errorf("error in unix.Syscall6(unix.SYS_GETSOCKOPT, ...): %v", err) - } - - device := &NativeTUN{ - name: string(ifName.name[:ifNameSize-1 /* -1 is for \0 */]), - f: os.NewFile(uintptr(fd), string(ifName.name[:])), + tun := &NativeTun{ + fd: file, mtu: 1500, events: make(chan TUNEvent, 10), errors: make(chan error, 1), } - // start listener + _, err := tun.Name() + if err != nil { + return nil, err + } - go func(native *NativeTUN) { - // TODO: Fix this very niave implementation + // TODO: Fix this very naive implementation + go func(tun *NativeTun) { var ( statusUp bool statusMTU int ) for ; ; time.Sleep(time.Second) { - intr, err := net.InterfaceByName(device.name) + intr, err := net.InterfaceByName(tun.name) if err != nil { - native.errors <- err + tun.errors <- err return } // Up / Down event up := (intr.Flags & net.FlagUp) != 0 if up != statusUp && up { - native.events <- TUNEventUp + tun.events <- TUNEventUp } if up != statusUp && !up { - native.events <- TUNEventDown + tun.events <- TUNEventDown } statusUp = up // MTU changes if intr.MTU != statusMTU { - native.events <- TUNEventMTUUpdate + tun.events <- TUNEventMTUUpdate } statusMTU = intr.MTU } - }(device) + }(tun) // set default MTU + err = tun.setMTU(DefaultMTU) - err = device.setMTU(DefaultMTU) - - return device, err + return tun, err } -var _ io.ReadWriteCloser = (*NativeTUN)(nil) +func (tun *NativeTun) Name() (string, error) { -func (t *NativeTUN) Events() chan TUNEvent { - return t.events -} - -func (t *NativeTUN) Read(to []byte) (int, error) { - t.rMu.Lock() - defer t.rMu.Unlock() - - if cap(t.rBuf) < len(to)+4 { - t.rBuf = make([]byte, len(to)+4) + var ifName struct { + name [16]byte } - t.rBuf = t.rBuf[:len(to)+4] + ifNameSize := uintptr(16) - n, err := t.f.Read(t.rBuf) - copy(to, t.rBuf[4:]) + _, _, errno := unix.Syscall6( + unix.SYS_GETSOCKOPT, + uintptr(tun.fd.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) + } + + tun.name = string(ifName.name[:ifNameSize-1]) + return tun.name, nil +} + +func (tun *NativeTun) File() *os.File { + return tun.fd +} + +func (tun *NativeTun) Events() chan TUNEvent { + return tun.events +} + +func (tun *NativeTun) Read(buff []byte, offset int) (int, error) { + + buff = buff[offset-4:] + n, err := tun.fd.Read(buff[:]) + if n < 4 { + return 0, err + } return n - 4, err } -func (t *NativeTUN) Write(from []byte) (int, error) { +func (tun *NativeTun) Write(buff []byte, offset int) (int, error) { - if len(from) == 0 { - return 0, unix.EIO - } + // reserve space for header - t.wMu.Lock() - defer t.wMu.Unlock() + buff = buff[offset-4:] - if cap(t.wBuf) < len(from)+4 { - t.wBuf = make([]byte, len(from)+4) - } - t.wBuf = t.wBuf[:len(from)+4] + // add packet information header - // determine the IP Family for the NULL L2 Header + buff[0] = 0x00 + buff[1] = 0x00 + buff[2] = 0x00 - ipVer := from[0] >> 4 - if ipVer == ipv4.Version { - t.wBuf[3] = unix.AF_INET - } else if ipVer == ipv6.Version { - t.wBuf[3] = unix.AF_INET6 + if buff[4]>>4 == ipv6.Version { + buff[3] = unix.AF_INET6 } else { - return 0, errors.New("Unable to determine IP version from packet.") + buff[3] = unix.AF_INET } - copy(t.wBuf[4:], from) + // write - n, err := t.f.Write(t.wBuf) - return n - 4, err + return tun.fd.Write(buff) } -func (t *NativeTUN) Close() error { - - // lock to make sure no read/write is in process. - - t.rMu.Lock() - defer t.rMu.Unlock() - - t.wMu.Lock() - defer t.wMu.Unlock() - - return t.f.Close() +func (tun *NativeTun) Close() error { + return tun.fd.Close() } -func (t *NativeTUN) Name() string { - return t.name -} - -func (t *NativeTUN) setMTU(n int) error { +func (tun *NativeTun) setMTU(n int) error { // open datagram socket @@ -267,7 +235,7 @@ func (t *NativeTUN) setMTU(n int) error { // do ioctl call var ifr [32]byte - copy(ifr[:], t.name) + copy(ifr[:], tun.name) binary.LittleEndian.PutUint32(ifr[16:20], uint32(n)) _, _, errno := unix.Syscall( unix.SYS_IOCTL, @@ -277,13 +245,13 @@ func (t *NativeTUN) setMTU(n int) error { ) if errno != 0 { - return fmt.Errorf("Failed to set MTU on %s", t.name) + return fmt.Errorf("Failed to set MTU on %s", tun.name) } return nil } -func (t *NativeTUN) MTU() (int, error) { +func (tun *NativeTun) MTU() (int, error) { // open datagram socket @@ -302,7 +270,7 @@ func (t *NativeTUN) MTU() (int, error) { // do ioctl call var ifr [64]byte - copy(ifr[:], t.name) + copy(ifr[:], tun.name) _, _, errno := unix.Syscall( unix.SYS_IOCTL, uintptr(fd), @@ -310,7 +278,7 @@ func (t *NativeTUN) MTU() (int, error) { uintptr(unsafe.Pointer(&ifr[0])), ) if errno != 0 { - return 0, fmt.Errorf("Failed to get MTU on %s", t.name) + return 0, fmt.Errorf("Failed to get MTU on %s", tun.name) } // convert result to signed 32-bit int diff --git a/uapi_darwin.go b/uapi_darwin.go index 2850184..4cb4e62 100644 --- a/uapi_darwin.go +++ b/uapi_darwin.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "golang.org/x/sys/unix" "net" @@ -44,23 +45,11 @@ func (l *UAPIListener) Addr() net.Addr { return nil } -func NewUAPIListener(name string) (net.Listener, error) { +func UAPIListen(name string, file *os.File) (net.Listener, error) { - // check if path exist + // wrap file in listener - err := os.MkdirAll(socketDirectory, 077) - if err != nil && !os.IsExist(err) { - return nil, err - } - - // open UNIX socket - - socketPath := path.Join( - socketDirectory, - fmt.Sprintf(socketName, name), - ) - - listener, err := net.Listen("unix", socketPath) + listener, err := net.FileListener(file) if err != nil { return nil, err } @@ -73,6 +62,13 @@ func NewUAPIListener(name string) (net.Listener, error) { // watch for deletion of socket + socketPath := path.Join( + socketDirectory, + fmt.Sprintf(socketName, name), + ) + + // watch for deletion of socket + go func(l *UAPIListener) { for ; ; time.Sleep(time.Second) { if _, err := os.Stat(socketPath); os.IsNotExist(err) { @@ -97,3 +93,56 @@ func NewUAPIListener(name string) (net.Listener, error) { return uapi, nil } + +func UAPIOpen(name string) (*os.File, error) { + + // check if path exist + + err := os.MkdirAll(socketDirectory, 0600) + if err != nil && !os.IsExist(err) { + return nil, err + } + + // open UNIX socket + + socketPath := path.Join( + socketDirectory, + fmt.Sprintf(socketName, name), + ) + + addr, err := net.ResolveUnixAddr("unix", socketPath) + if err != nil { + return nil, err + } + + listener, err := func() (*net.UnixListener, error) { + + // initial connection attempt + + listener, err := net.ListenUnix("unix", addr) + if err == nil { + return listener, nil + } + + // check if socket already active + + _, err = net.Dial("unix", socketPath) + if err == nil { + return nil, errors.New("unix socket in use") + } + + // cleanup & attempt again + + err = os.Remove(socketPath) + if err != nil { + return nil, err + } + return net.ListenUnix("unix", addr) + }() + + if err != nil { + return nil, err + } + + return listener.File() +} diff --git a/warning_default.go b/warning_default.go new file mode 100644 index 0000000..92d1b1d --- /dev/null +++ b/warning_default.go @@ -0,0 +1,19 @@ +// +build !linux + +package main + +import ( + "fmt" + "os" +) + +func Warning() { + fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "W This is alpha software. It will very likely not G") + fmt.Fprintln(os.Stderr, "W do what it is supposed to do, and things may go G") + fmt.Fprintln(os.Stderr, "W horribly wrong. You have been warned. Proceed G") + fmt.Fprintln(os.Stderr, "W at your own risk. G") + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") +} diff --git a/warning_linux.go b/warning_linux.go new file mode 100644 index 0000000..d82805f --- /dev/null +++ b/warning_linux.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "os" +) + +func Warning() { + shouldQuit := os.Getenv("WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD") != "1" + + fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "W This is alpha software. It will very likely not G") + fmt.Fprintln(os.Stderr, "W do what it is supposed to do, and things may go G") + fmt.Fprintln(os.Stderr, "W horribly wrong. You have been warned. Proceed G") + fmt.Fprintln(os.Stderr, "W at your own risk. G") + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "W Furthermore, you are running this software on a G") + fmt.Fprintln(os.Stderr, "W Linux kernel, which is probably unnecessary and G") + fmt.Fprintln(os.Stderr, "W foolish. This is because the Linux kernel has G") + fmt.Fprintln(os.Stderr, "W built-in first class support for WireGuard, and G") + fmt.Fprintln(os.Stderr, "W this support is much more refined than this G") + fmt.Fprintln(os.Stderr, "W program. For more information on installing the G") + fmt.Fprintln(os.Stderr, "W kernel module, please visit: G") + fmt.Fprintln(os.Stderr, "W https://www.wireguard.com/install G") + if shouldQuit { + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "W If you still want to use this program, against G") + fmt.Fprintln(os.Stderr, "W the sage advice here, please first export this G") + fmt.Fprintln(os.Stderr, "W environment variable: G") + fmt.Fprintln(os.Stderr, "W WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1 G") + } + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") + + if shouldQuit { + os.Exit(1) + } +} From 209dd22ea0c6ea06aca47cb53f68ae2cf0d40831 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 3 May 2018 14:50:57 +0200 Subject: [PATCH 2/7] Daemonize with environment variable --- daemon.go | 25 ------------------------- main.go | 25 +++++++++++++++++++------ 2 files changed, 19 insertions(+), 31 deletions(-) delete mode 100644 daemon.go diff --git a/daemon.go b/daemon.go deleted file mode 100644 index e2ded87..0000000 --- a/daemon.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - "os" -) - -func Daemonize(attr *os.ProcAttr) error { - path, err := os.Executable() - if err != nil { - return err - } - - argv := []string{os.Args[0], "--foreground"} - argv = append(argv, os.Args[1:]...) - process, err := os.StartProcess( - path, - argv, - attr, - ) - if err != nil { - return err - } - process.Release() - return nil -} diff --git a/main.go b/main.go index 3358469..f0705c8 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,6 @@ import ( "fmt" "os" "os/signal" - "runtime" "strconv" ) @@ -16,6 +15,7 @@ const ( const ( ENV_WG_TUN_FD = "WG_TUN_FD" ENV_WG_UAPI_FD = "WG_UAPI_FD" + ENV_WG_PROCESS_FOREGROUND = "WG_PROCESS_FOREGROUND" ) func printUsage() { @@ -55,6 +55,10 @@ func main() { interfaceName = os.Args[1] } + if !foreground { + foreground = os.Getenv(ENV_WG_PROCESS_FOREGROUND) == "1" + } + // get log level (default: info) logLevel := func() int { @@ -129,6 +133,7 @@ func main() { env := os.Environ() env = append(env, fmt.Sprintf("%s=3", ENV_WG_TUN_FD)) env = append(env, fmt.Sprintf("%s=4", ENV_WG_UAPI_FD)) + env = append(env, fmt.Sprintf("%s=1", ENV_WG_PROCESS_FOREGROUND)) attr := &os.ProcAttr{ Files: []*os.File{ nil, // stdin @@ -140,18 +145,26 @@ func main() { Dir: ".", Env: env, } - err = Daemonize(attr) + + path, err := os.Executable() + if err != nil { + logger.Error.Println("Failed to determine executable:", err) + os.Exit(ExitSetupFailed) + } + + process, err := os.StartProcess( + path, + os.Args, + attr, + ) if err != nil { logger.Error.Println("Failed to daemonize:", err) os.Exit(ExitSetupFailed) } + process.Release() return } - // increase number of go workers (for Go <1.5) - - runtime.GOMAXPROCS(runtime.NumCPU()) - // create wireguard device device := NewDevice(tun, logger) From a040786645ec980059937fd6a1a361b160c1a809 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 3 May 2018 15:04:00 +0200 Subject: [PATCH 3/7] global: Add SPDX tags and copyright header Mathias should probably add his copyright headers to each file too. --- bind_test.go | 5 +++++ conn.go | 5 +++++ conn_default.go | 5 +++++ conn_linux.go | 4 +++- constants.go | 5 +++++ cookie.go | 5 +++++ cookie_test.go | 5 +++++ device.go | 5 +++++ device_test.go | 5 +++++ endpoint_test.go | 5 +++++ helper_test.go | 5 +++++ index.go | 5 +++++ ip.go | 5 +++++ kdf_test.go | 5 +++++ keypair.go | 5 +++++ logger.go | 5 +++++ main.go | 5 +++++ misc.go | 5 +++++ noise-helpers.go | 5 +++++ noise-protocol.go | 5 +++++ noise-types.go | 5 +++++ noise_test.go | 5 +++++ peer.go | 5 +++++ ratelimiter/ratelimiter.go | 9 +++++---- ratelimiter/ratelimiter_test.go | 5 +++++ receive.go | 5 +++++ replay.go | 5 +++++ replay_test.go | 5 +++++ routing.go | 5 +++++ send.go | 5 +++++ signal.go | 5 +++++ tai64n/tai64n.go | 5 +++++ tai64n/tai64n_test.go | 5 +++++ timer.go | 5 +++++ timers.go | 5 +++++ trie.go | 5 +++++ trie_rand_test.go | 5 +++++ trie_test.go | 5 +++++ tun.go | 5 +++++ tun_darwin.go | 5 +++++ tun_linux.go | 5 +++++ tun_windows.go | 5 +++++ uapi.go | 5 +++++ uapi_darwin.go | 5 +++++ uapi_linux.go | 5 +++++ uapi_windows.go | 5 +++++ warning_default.go | 5 +++++ warning_linux.go | 5 +++++ xchacha20poly1305/xchacha20.go | 8 +++++--- xchacha20poly1305/xchacha20_test.go | 5 +++++ 50 files changed, 248 insertions(+), 8 deletions(-) diff --git a/bind_test.go b/bind_test.go index 41c4225..47f5492 100644 --- a/bind_test.go +++ b/bind_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import "errors" diff --git a/conn.go b/conn.go index 6bb262c..082bbca 100644 --- a/conn.go +++ b/conn.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/conn_default.go b/conn_default.go index 5b73c90..047d5f6 100644 --- a/conn_default.go +++ b/conn_default.go @@ -1,5 +1,10 @@ // +build !linux +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/conn_linux.go b/conn_linux.go index ff3c483..a428138 100644 --- a/conn_linux.go +++ b/conn_linux.go @@ -1,4 +1,6 @@ -/* Copyright 2017-2018 Jason A. Donenfeld . All Rights Reserved. +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. * * This implements userspace semantics of "sticky sockets", modeled after * WireGuard's kernelspace implementation. This is more or less a straight port diff --git a/constants.go b/constants.go index 8835f92..04b75d7 100644 --- a/constants.go +++ b/constants.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/cookie.go b/cookie.go index 813ddab..cfee367 100644 --- a/cookie.go +++ b/cookie.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/cookie_test.go b/cookie_test.go index d745fe7..34c8ad4 100644 --- a/cookie_test.go +++ b/cookie_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/device.go b/device.go index dddb547..8b0d2a5 100644 --- a/device.go +++ b/device.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/device_test.go b/device_test.go index abd0208..7af52b2 100644 --- a/device_test.go +++ b/device_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main /* Create two device instances and simulate full WireGuard interaction diff --git a/endpoint_test.go b/endpoint_test.go index 7021e48..5dd6cb4 100644 --- a/endpoint_test.go +++ b/endpoint_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/helper_test.go b/helper_test.go index 41e6b72..a8adcd7 100644 --- a/helper_test.go +++ b/helper_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/index.go b/index.go index 1ba040e..c309f23 100644 --- a/index.go +++ b/index.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/ip.go b/ip.go index 752a404..7be9337 100644 --- a/ip.go +++ b/ip.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/kdf_test.go b/kdf_test.go index a89dacc..fa4a2d2 100644 --- a/kdf_test.go +++ b/kdf_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/keypair.go b/keypair.go index 1ab0649..eaf30b2 100644 --- a/keypair.go +++ b/keypair.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/logger.go b/logger.go index 0872ef9..784235c 100644 --- a/logger.go +++ b/logger.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/main.go b/main.go index f0705c8..4b8299a 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/misc.go b/misc.go index 80e33f6..f94a617 100644 --- a/misc.go +++ b/misc.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/noise-helpers.go b/noise-helpers.go index 1e2de5f..6e23d83 100644 --- a/noise-helpers.go +++ b/noise-helpers.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/noise-protocol.go b/noise-protocol.go index 6440c97..b880ede 100644 --- a/noise-protocol.go +++ b/noise-protocol.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/noise-types.go b/noise-types.go index 1a944df..58aa0c2 100644 --- a/noise-types.go +++ b/noise-types.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/noise_test.go b/noise_test.go index 5e9d44b..958a4ef 100644 --- a/noise_test.go +++ b/noise_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/peer.go b/peer.go index ec411b2..9703b58 100644 --- a/peer.go +++ b/peer.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/ratelimiter/ratelimiter.go b/ratelimiter/ratelimiter.go index 006900a..1aa6813 100644 --- a/ratelimiter/ratelimiter.go +++ b/ratelimiter/ratelimiter.go @@ -1,9 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package ratelimiter -/* Copyright (C) 2015-2017 Jason A. Donenfeld . All Rights Reserved. */ - -/* This file contains a port of the rate-limiter from the linux kernel version */ - import ( "net" "sync" diff --git a/ratelimiter/ratelimiter_test.go b/ratelimiter/ratelimiter_test.go index 37339ee..9bdaa4d 100644 --- a/ratelimiter/ratelimiter_test.go +++ b/ratelimiter/ratelimiter_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package ratelimiter import ( diff --git a/receive.go b/receive.go index 7d35497..156ade5 100644 --- a/receive.go +++ b/receive.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/replay.go b/replay.go index 5d42860..8fab1d2 100644 --- a/replay.go +++ b/replay.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main /* Copyright (C) 2015-2017 Jason A. Donenfeld . All Rights Reserved. */ diff --git a/replay_test.go b/replay_test.go index f697701..77180e5 100644 --- a/replay_test.go +++ b/replay_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/routing.go b/routing.go index 2a2e237..77c9b1e 100644 --- a/routing.go +++ b/routing.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/send.go b/send.go index 5c6b350..24c7f32 100644 --- a/send.go +++ b/send.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/signal.go b/signal.go index 1505593..4d51bfa 100644 --- a/signal.go +++ b/signal.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main type Signal struct { diff --git a/tai64n/tai64n.go b/tai64n/tai64n.go index da5257c..1c7f42b 100644 --- a/tai64n/tai64n.go +++ b/tai64n/tai64n.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package tai64n import ( diff --git a/tai64n/tai64n_test.go b/tai64n/tai64n_test.go index 389b65c..62e7b1b 100644 --- a/tai64n/tai64n_test.go +++ b/tai64n/tai64n_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package tai64n import ( diff --git a/timer.go b/timer.go index 74e3a4e..aeab5d9 100644 --- a/timer.go +++ b/timer.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/timers.go b/timers.go index ba0d0e5..835191f 100644 --- a/timers.go +++ b/timers.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/trie.go b/trie.go index 405ffc3..03f0722 100644 --- a/trie.go +++ b/trie.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/trie_rand_test.go b/trie_rand_test.go index 840d269..157c270 100644 --- a/trie_rand_test.go +++ b/trie_rand_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/trie_test.go b/trie_test.go index 9d53df3..3c3b5ba 100644 --- a/trie_test.go +++ b/trie_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/tun.go b/tun.go index 318772a..ec3ab47 100644 --- a/tun.go +++ b/tun.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/tun_darwin.go b/tun_darwin.go index d03ff48..a03347f 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/tun_linux.go b/tun_linux.go index b0ffa00..a74a9cc 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + /* Copyright 2018 Jason A. Donenfeld . All Rights Reserved. */ package main diff --git a/tun_windows.go b/tun_windows.go index 0711032..c0c9ff8 100644 --- a/tun_windows.go +++ b/tun_windows.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/uapi.go b/uapi.go index c795b73..a7ef662 100644 --- a/uapi.go +++ b/uapi.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/uapi_darwin.go b/uapi_darwin.go index 4cb4e62..954d720 100644 --- a/uapi_darwin.go +++ b/uapi_darwin.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/uapi_linux.go b/uapi_linux.go index f97a18a..c40472e 100644 --- a/uapi_linux.go +++ b/uapi_linux.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/uapi_windows.go b/uapi_windows.go index 7807235..01f5505 100644 --- a/uapi_windows.go +++ b/uapi_windows.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main /* UAPI on windows uses a bidirectional named pipe diff --git a/warning_default.go b/warning_default.go index 92d1b1d..8a0a448 100644 --- a/warning_default.go +++ b/warning_default.go @@ -1,5 +1,10 @@ // +build !linux +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/warning_linux.go b/warning_linux.go index d82805f..2ac7957 100644 --- a/warning_linux.go +++ b/warning_linux.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package main import ( diff --git a/xchacha20poly1305/xchacha20.go b/xchacha20poly1305/xchacha20.go index a6e59f0..bd27f02 100644 --- a/xchacha20poly1305/xchacha20.go +++ b/xchacha20poly1305/xchacha20.go @@ -1,6 +1,8 @@ -// Copyright (c) 2016 Andreas Auernhammer. All rights reserved. -// Use of this source code is governed by a license that can be -// found in the LICENSE file. +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2016 Andreas Auernhammer. All Rights Reserved. + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ package xchacha20poly1305 diff --git a/xchacha20poly1305/xchacha20_test.go b/xchacha20poly1305/xchacha20_test.go index 5d5b78f..c0d11d7 100644 --- a/xchacha20poly1305/xchacha20_test.go +++ b/xchacha20poly1305/xchacha20_test.go @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. + */ + package xchacha20poly1305 import ( From 0f322f83f5a920f89a9293e4dc48efc27e4acbac Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 4 May 2018 19:50:08 +0200 Subject: [PATCH 4/7] warning: put into main --- main.go | 45 +++++++++++++++++++++++++++++++++++++++++---- warning_default.go | 24 ------------------------ warning_linux.go | 44 -------------------------------------------- 3 files changed, 41 insertions(+), 72 deletions(-) delete mode 100644 warning_default.go delete mode 100644 warning_linux.go diff --git a/main.go b/main.go index 4b8299a..41231bf 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "fmt" "os" "os/signal" + "runtime" "strconv" ) @@ -18,8 +19,8 @@ const ( ) const ( - ENV_WG_TUN_FD = "WG_TUN_FD" - ENV_WG_UAPI_FD = "WG_UAPI_FD" + ENV_WG_TUN_FD = "WG_TUN_FD" + ENV_WG_UAPI_FD = "WG_UAPI_FD" ENV_WG_PROCESS_FOREGROUND = "WG_PROCESS_FOREGROUND" ) @@ -28,9 +29,45 @@ func printUsage() { fmt.Printf("%s [-f/--foreground] INTERFACE-NAME\n", os.Args[0]) } -func main() { +func warning() { + shouldQuit := false - Warning() + fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "W This is alpha software. It will very likely not G") + fmt.Fprintln(os.Stderr, "W do what it is supposed to do, and things may go G") + fmt.Fprintln(os.Stderr, "W horribly wrong. You have been warned. Proceed G") + fmt.Fprintln(os.Stderr, "W at your own risk. G") + if runtime.GOOS == "linux" { + shouldQuit = os.Getenv("WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD") != "1" + + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "W Furthermore, you are running this software on a G") + fmt.Fprintln(os.Stderr, "W Linux kernel, which is probably unnecessary and G") + fmt.Fprintln(os.Stderr, "W foolish. This is because the Linux kernel has G") + fmt.Fprintln(os.Stderr, "W built-in first class support for WireGuard, and G") + fmt.Fprintln(os.Stderr, "W this support is much more refined than this G") + fmt.Fprintln(os.Stderr, "W program. For more information on installing the G") + fmt.Fprintln(os.Stderr, "W kernel module, please visit: G") + fmt.Fprintln(os.Stderr, "W https://www.wireguard.com/install G") + if shouldQuit { + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "W If you still want to use this program, against G") + fmt.Fprintln(os.Stderr, "W the sage advice here, please first export this G") + fmt.Fprintln(os.Stderr, "W environment variable: G") + fmt.Fprintln(os.Stderr, "W WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1 G") + } + } + fmt.Fprintln(os.Stderr, "W G") + fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") + + if shouldQuit { + os.Exit(1) + } +} + +func main() { + warning() // parse arguments diff --git a/warning_default.go b/warning_default.go deleted file mode 100644 index 8a0a448..0000000 --- a/warning_default.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build !linux - -/* SPDX-License-Identifier: GPL-2.0 - * - * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. - */ - -package main - -import ( - "fmt" - "os" -) - -func Warning() { - fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") - fmt.Fprintln(os.Stderr, "W G") - fmt.Fprintln(os.Stderr, "W This is alpha software. It will very likely not G") - fmt.Fprintln(os.Stderr, "W do what it is supposed to do, and things may go G") - fmt.Fprintln(os.Stderr, "W horribly wrong. You have been warned. Proceed G") - fmt.Fprintln(os.Stderr, "W at your own risk. G") - fmt.Fprintln(os.Stderr, "W G") - fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") -} diff --git a/warning_linux.go b/warning_linux.go deleted file mode 100644 index 2ac7957..0000000 --- a/warning_linux.go +++ /dev/null @@ -1,44 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 - * - * Copyright (C) 2017-2018 Jason A. Donenfeld . All Rights Reserved. - */ - -package main - -import ( - "fmt" - "os" -) - -func Warning() { - shouldQuit := os.Getenv("WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD") != "1" - - fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") - fmt.Fprintln(os.Stderr, "W G") - fmt.Fprintln(os.Stderr, "W This is alpha software. It will very likely not G") - fmt.Fprintln(os.Stderr, "W do what it is supposed to do, and things may go G") - fmt.Fprintln(os.Stderr, "W horribly wrong. You have been warned. Proceed G") - fmt.Fprintln(os.Stderr, "W at your own risk. G") - fmt.Fprintln(os.Stderr, "W G") - fmt.Fprintln(os.Stderr, "W Furthermore, you are running this software on a G") - fmt.Fprintln(os.Stderr, "W Linux kernel, which is probably unnecessary and G") - fmt.Fprintln(os.Stderr, "W foolish. This is because the Linux kernel has G") - fmt.Fprintln(os.Stderr, "W built-in first class support for WireGuard, and G") - fmt.Fprintln(os.Stderr, "W this support is much more refined than this G") - fmt.Fprintln(os.Stderr, "W program. For more information on installing the G") - fmt.Fprintln(os.Stderr, "W kernel module, please visit: G") - fmt.Fprintln(os.Stderr, "W https://www.wireguard.com/install G") - if shouldQuit { - fmt.Fprintln(os.Stderr, "W G") - fmt.Fprintln(os.Stderr, "W If you still want to use this program, against G") - fmt.Fprintln(os.Stderr, "W the sage advice here, please first export this G") - fmt.Fprintln(os.Stderr, "W environment variable: G") - fmt.Fprintln(os.Stderr, "W WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1 G") - } - fmt.Fprintln(os.Stderr, "W G") - fmt.Fprintln(os.Stderr, "WARNING WARNING WARNING WARNING WARNING WARNING WARNING") - - if shouldQuit { - os.Exit(1) - } -} From de7ecc571b9ea81d5cad97e339e84f8084352741 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 4 May 2018 21:11:38 +0200 Subject: [PATCH 5/7] tun: allow darwin to auto assign names --- main.go | 22 +++++++++++++++------- tun_darwin.go | 8 +++++--- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index 41231bf..8562bf6 100644 --- a/main.go +++ b/main.go @@ -115,13 +115,6 @@ func main() { return LogLevelInfo }() - logger := NewLogger( - logLevel, - fmt.Sprintf("(%s) ", interfaceName), - ) - - logger.Debug.Println("Debug log enabled") - // open TUN device (or use supplied fd) tun, err := func() (TUNDevice, error) { @@ -141,6 +134,21 @@ func main() { return CreateTUNFromFile(file) }() + if err == nil { + realInterfaceName, err2 := tun.Name() + if err2 == nil { + interfaceName = realInterfaceName + } + } + + logger := NewLogger( + logLevel, + fmt.Sprintf("(%s) ", interfaceName), + ) + + logger.Debug.Println("Debug log enabled") + + if err != nil { logger.Error.Println("Failed to create TUN device:", err) os.Exit(ExitSetupFailed) diff --git a/tun_darwin.go b/tun_darwin.go index a03347f..4d9b06d 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -46,9 +46,11 @@ var sockaddrCtlSize uintptr = 32 func CreateTUN(name string) (TUNDevice, error) { ifIndex := -1 - fmt.Sscanf(name, "utun%d", &ifIndex) - if ifIndex < 0 { - return nil, fmt.Errorf("error parsing interface name %s, must be utun[0-9]+", name) + if (name != "utun") { + fmt.Sscanf(name, "utun%d", &ifIndex) + if ifIndex < 0 { + return nil, fmt.Errorf("Interface name must be utun[0-9]*") + } } fd, err := unix.Socket(unix.AF_SYSTEM, unix.SOCK_DGRAM, 2) From ac898bb35afde34a383f72726c2818d082933e8d Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 4 May 2018 21:20:19 +0200 Subject: [PATCH 6/7] tun: print automatically assigned interface name to stdout This way scripts know what process they just started. --- tun_darwin.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tun_darwin.go b/tun_darwin.go index 4d9b06d..5514563 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -98,7 +98,13 @@ func CreateTUN(name string) (TUNDevice, error) { return nil, fmt.Errorf("SYS_CONNECT: %v", errno) } - return CreateTUNFromFile(os.NewFile(uintptr(fd), "")) + tun, err := CreateTUNFromFile(os.NewFile(uintptr(fd), "")) + + if err == nil && name == "utun" { + fmt.Printf("OS assigned interface: %s\n", tun.(*NativeTun).name) + } + + return tun, err } func CreateTUNFromFile(file *os.File) (TUNDevice, error) { From e1de0f229a8f2cbfc4bb56230de885386a775fd6 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 4 May 2018 21:51:55 +0200 Subject: [PATCH 7/7] uapi: use kqueue for sock deletion on darwin --- main.go | 4 ++++ uapi_darwin.go | 44 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index 8562bf6..e7e0488 100644 --- a/main.go +++ b/main.go @@ -227,6 +227,10 @@ func main() { term := make(chan os.Signal) uapi, err := UAPIListen(interfaceName, fileUAPI) + if err != nil { + logger.Error.Println("Failed to listen on uapi socket:", err) + os.Exit(ExitSetupFailed) + } go func() { for { diff --git a/uapi_darwin.go b/uapi_darwin.go index 954d720..69b0e3d 100644 --- a/uapi_darwin.go +++ b/uapi_darwin.go @@ -12,7 +12,6 @@ import ( "net" "os" "path" - "time" ) const ( @@ -28,6 +27,8 @@ type UAPIListener struct { listener net.Listener // unix socket listener connNew chan net.Conn connErr chan error + kqueueFd int + keventFd int } func (l *UAPIListener) Accept() (net.Conn, error) { @@ -43,7 +44,16 @@ func (l *UAPIListener) Accept() (net.Conn, error) { } func (l *UAPIListener) Close() error { - return l.listener.Close() + err1 := unix.Close(l.kqueueFd) + err2 := unix.Close(l.keventFd) + err3 := l.listener.Close() + if err1 != nil { + return err1 + } + if err2 != nil { + return err2 + } + return err3 } func (l *UAPIListener) Addr() net.Addr { @@ -65,8 +75,6 @@ func UAPIListen(name string, file *os.File) (net.Listener, error) { connErr: make(chan error, 1), } - // watch for deletion of socket - socketPath := path.Join( socketDirectory, fmt.Sprintf(socketName, name), @@ -74,12 +82,36 @@ func UAPIListen(name string, file *os.File) (net.Listener, error) { // watch for deletion of socket + uapi.kqueueFd, err = unix.Kqueue() + if err != nil { + return nil, err + } + uapi.keventFd, err = unix.Open(socketDirectory, unix.O_EVTONLY, 0) + if err != nil { + unix.Close(uapi.kqueueFd) + return nil, err + } + go func(l *UAPIListener) { - for ; ; time.Sleep(time.Second) { - if _, err := os.Stat(socketPath); os.IsNotExist(err) { + event := unix.Kevent_t{ + Ident: uint64(uapi.keventFd), + Filter: unix.EVFILT_VNODE, + Flags: unix.EV_ADD | unix.EV_ENABLE | unix.EV_ONESHOT, + Fflags: unix.NOTE_WRITE, + } + events := make([]unix.Kevent_t, 1) + n := 1 + var kerr error + for { + // start with lstat to avoid race condition + if _, err := os.Lstat(socketPath); os.IsNotExist(err) { l.connErr <- err return } + if kerr != nil || n != 1 { + return + } + n, kerr = unix.Kevent(uapi.kqueueFd, []unix.Kevent_t{event}, events, nil) } }(uapi)