Merge branch 'master' of ssh://git.zx2c4.com/wireguard-go
This commit is contained in:
commit
edbce6b400
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
5
conn.go
5
conn.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
/* Copyright 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
*
|
*
|
||||||
* This implements userspace semantics of "sticky sockets", modeled after
|
* This implements userspace semantics of "sticky sockets", modeled after
|
||||||
* WireGuard's kernelspace implementation. This is more or less a straight port
|
* WireGuard's kernelspace implementation. This is more or less a straight port
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Daemonize() error {
|
|
||||||
return errors.New("Not implemented on OSX")
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
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])
|
|
||||||
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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
/* Create two device instances and simulate full WireGuard interaction
|
/* Create two device instances and simulate full WireGuard interaction
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
5
index.go
5
index.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
5
ip.go
5
ip.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
97
main.go
97
main.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -14,8 +19,9 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ENV_WG_TUN_FD = "WG_TUN_FD"
|
ENV_WG_TUN_FD = "WG_TUN_FD"
|
||||||
ENV_WG_UAPI_FD = "WG_UAPI_FD"
|
ENV_WG_UAPI_FD = "WG_UAPI_FD"
|
||||||
|
ENV_WG_PROCESS_FOREGROUND = "WG_PROCESS_FOREGROUND"
|
||||||
)
|
)
|
||||||
|
|
||||||
func printUsage() {
|
func printUsage() {
|
||||||
|
@ -23,7 +29,45 @@ func printUsage() {
|
||||||
fmt.Printf("%s [-f/--foreground] INTERFACE-NAME\n", os.Args[0])
|
fmt.Printf("%s [-f/--foreground] INTERFACE-NAME\n", os.Args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func warning() {
|
||||||
|
shouldQuit := false
|
||||||
|
|
||||||
|
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() {
|
func main() {
|
||||||
|
warning()
|
||||||
|
|
||||||
// parse arguments
|
// parse arguments
|
||||||
|
|
||||||
|
@ -53,6 +97,10 @@ func main() {
|
||||||
interfaceName = os.Args[1]
|
interfaceName = os.Args[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !foreground {
|
||||||
|
foreground = os.Getenv(ENV_WG_PROCESS_FOREGROUND) == "1"
|
||||||
|
}
|
||||||
|
|
||||||
// get log level (default: info)
|
// get log level (default: info)
|
||||||
|
|
||||||
logLevel := func() int {
|
logLevel := func() int {
|
||||||
|
@ -67,13 +115,6 @@ func main() {
|
||||||
return LogLevelInfo
|
return LogLevelInfo
|
||||||
}()
|
}()
|
||||||
|
|
||||||
logger := NewLogger(
|
|
||||||
logLevel,
|
|
||||||
fmt.Sprintf("(%s) ", interfaceName),
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.Debug.Println("Debug log enabled")
|
|
||||||
|
|
||||||
// open TUN device (or use supplied fd)
|
// open TUN device (or use supplied fd)
|
||||||
|
|
||||||
tun, err := func() (TUNDevice, error) {
|
tun, err := func() (TUNDevice, error) {
|
||||||
|
@ -93,6 +134,21 @@ func main() {
|
||||||
return CreateTUNFromFile(file)
|
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 {
|
if err != nil {
|
||||||
logger.Error.Println("Failed to create TUN device:", err)
|
logger.Error.Println("Failed to create TUN device:", err)
|
||||||
os.Exit(ExitSetupFailed)
|
os.Exit(ExitSetupFailed)
|
||||||
|
@ -127,6 +183,7 @@ func main() {
|
||||||
env := os.Environ()
|
env := os.Environ()
|
||||||
env = append(env, fmt.Sprintf("%s=3", ENV_WG_TUN_FD))
|
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=4", ENV_WG_UAPI_FD))
|
||||||
|
env = append(env, fmt.Sprintf("%s=1", ENV_WG_PROCESS_FOREGROUND))
|
||||||
attr := &os.ProcAttr{
|
attr := &os.ProcAttr{
|
||||||
Files: []*os.File{
|
Files: []*os.File{
|
||||||
nil, // stdin
|
nil, // stdin
|
||||||
|
@ -138,18 +195,26 @@ func main() {
|
||||||
Dir: ".",
|
Dir: ".",
|
||||||
Env: env,
|
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 {
|
if err != nil {
|
||||||
logger.Error.Println("Failed to daemonize:", err)
|
logger.Error.Println("Failed to daemonize:", err)
|
||||||
os.Exit(ExitSetupFailed)
|
os.Exit(ExitSetupFailed)
|
||||||
}
|
}
|
||||||
|
process.Release()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase number of go workers (for Go <1.5)
|
|
||||||
|
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
|
||||||
|
|
||||||
// create wireguard device
|
// create wireguard device
|
||||||
|
|
||||||
device := NewDevice(tun, logger)
|
device := NewDevice(tun, logger)
|
||||||
|
@ -162,6 +227,10 @@ func main() {
|
||||||
term := make(chan os.Signal)
|
term := make(chan os.Signal)
|
||||||
|
|
||||||
uapi, err := UAPIListen(interfaceName, fileUAPI)
|
uapi, err := UAPIListen(interfaceName, fileUAPI)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error.Println("Failed to listen on uapi socket:", err)
|
||||||
|
os.Exit(ExitSetupFailed)
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
|
5
misc.go
5
misc.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
5
peer.go
5
peer.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package ratelimiter
|
package ratelimiter
|
||||||
|
|
||||||
/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
|
||||||
|
|
||||||
/* This file contains a port of the rate-limiter from the linux kernel version */
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package ratelimiter
|
package ratelimiter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
5
send.go
5
send.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
func signalSend(s chan<- struct{}) {
|
func signalSend(s chan<- struct{}) {
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package tai64n
|
package tai64n
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package tai64n
|
package tai64n
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
5
trie.go
5
trie.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
5
tun.go
5
tun.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
205
tun_darwin.go
205
tun_darwin.go
|
@ -1,22 +1,17 @@
|
||||||
/* Copyright (c) 2016, Song Gao <song@gao.io>
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
* All rights reserved.
|
|
||||||
*
|
*
|
||||||
* Code from https://github.com/songgao/water
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/net/ipv4"
|
|
||||||
"golang.org/x/net/ipv6"
|
"golang.org/x/net/ipv6"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
@ -36,36 +31,32 @@ type sockaddrCtl struct {
|
||||||
scReserved [5]uint32
|
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.
|
// information" because there doesn't seem to be an IFF_NO_PI for darwin.
|
||||||
type NativeTUN struct {
|
type NativeTun struct {
|
||||||
name string
|
name string
|
||||||
f io.ReadWriteCloser
|
fd *os.File
|
||||||
mtu int
|
mtu int
|
||||||
|
|
||||||
rMu sync.Mutex
|
|
||||||
rBuf []byte
|
|
||||||
|
|
||||||
wMu sync.Mutex
|
|
||||||
wBuf []byte
|
|
||||||
|
|
||||||
events chan TUNEvent
|
events chan TUNEvent
|
||||||
errors chan error
|
errors chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
var sockaddrCtlSize uintptr = 32
|
var sockaddrCtlSize uintptr = 32
|
||||||
|
|
||||||
func CreateTUN(name string) (ifce TUNDevice, err error) {
|
func CreateTUN(name string) (TUNDevice, error) {
|
||||||
ifIndex := -1
|
ifIndex := -1
|
||||||
fmt.Sscanf(name, "utun%d", &ifIndex)
|
if (name != "utun") {
|
||||||
if ifIndex < 0 {
|
fmt.Sscanf(name, "utun%d", &ifIndex)
|
||||||
return nil, fmt.Errorf("error parsing interface name %s, must be utun[0-9]+", name)
|
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)
|
fd, err := unix.Socket(unix.AF_SYSTEM, unix.SOCK_DGRAM, 2)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error in unix.Socket: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var ctlInfo = &struct {
|
var ctlInfo = &struct {
|
||||||
|
@ -83,8 +74,7 @@ func CreateTUN(name string) (ifce TUNDevice, err error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
err = errno
|
return nil, fmt.Errorf("_CTLIOCGINFO: %v", errno)
|
||||||
return nil, fmt.Errorf("error in unix.Syscall(unix.SYS_IOTL, ...): %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sc := sockaddrCtl{
|
sc := sockaddrCtl{
|
||||||
|
@ -105,148 +95,139 @@ func CreateTUN(name string) (ifce TUNDevice, err error) {
|
||||||
)
|
)
|
||||||
|
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
err = errno
|
return nil, fmt.Errorf("SYS_CONNECT: %v", errno)
|
||||||
return nil, fmt.Errorf("error in unix.RawSyscall(unix.SYS_CONNECT, ...): %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// read (new) name of interface
|
tun, err := CreateTUNFromFile(os.NewFile(uintptr(fd), ""))
|
||||||
|
|
||||||
var ifName struct {
|
if err == nil && name == "utun" {
|
||||||
name [16]byte
|
fmt.Printf("OS assigned interface: %s\n", tun.(*NativeTun).name)
|
||||||
}
|
|
||||||
ifNameSize := uintptr(16)
|
|
||||||
|
|
||||||
_, _, 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{
|
return tun, err
|
||||||
name: string(ifName.name[:ifNameSize-1 /* -1 is for \0 */]),
|
}
|
||||||
f: os.NewFile(uintptr(fd), string(ifName.name[:])),
|
|
||||||
|
func CreateTUNFromFile(file *os.File) (TUNDevice, error) {
|
||||||
|
|
||||||
|
tun := &NativeTun{
|
||||||
|
fd: file,
|
||||||
mtu: 1500,
|
mtu: 1500,
|
||||||
events: make(chan TUNEvent, 10),
|
events: make(chan TUNEvent, 10),
|
||||||
errors: make(chan error, 1),
|
errors: make(chan error, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
// start listener
|
_, err := tun.Name()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
go func(native *NativeTUN) {
|
// TODO: Fix this very naive implementation
|
||||||
// TODO: Fix this very niave implementation
|
go func(tun *NativeTun) {
|
||||||
var (
|
var (
|
||||||
statusUp bool
|
statusUp bool
|
||||||
statusMTU int
|
statusMTU int
|
||||||
)
|
)
|
||||||
|
|
||||||
for ; ; time.Sleep(time.Second) {
|
for ; ; time.Sleep(time.Second) {
|
||||||
intr, err := net.InterfaceByName(device.name)
|
intr, err := net.InterfaceByName(tun.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
native.errors <- err
|
tun.errors <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Up / Down event
|
// Up / Down event
|
||||||
up := (intr.Flags & net.FlagUp) != 0
|
up := (intr.Flags & net.FlagUp) != 0
|
||||||
if up != statusUp && up {
|
if up != statusUp && up {
|
||||||
native.events <- TUNEventUp
|
tun.events <- TUNEventUp
|
||||||
}
|
}
|
||||||
if up != statusUp && !up {
|
if up != statusUp && !up {
|
||||||
native.events <- TUNEventDown
|
tun.events <- TUNEventDown
|
||||||
}
|
}
|
||||||
statusUp = up
|
statusUp = up
|
||||||
|
|
||||||
// MTU changes
|
// MTU changes
|
||||||
if intr.MTU != statusMTU {
|
if intr.MTU != statusMTU {
|
||||||
native.events <- TUNEventMTUUpdate
|
tun.events <- TUNEventMTUUpdate
|
||||||
}
|
}
|
||||||
statusMTU = intr.MTU
|
statusMTU = intr.MTU
|
||||||
}
|
}
|
||||||
}(device)
|
}(tun)
|
||||||
|
|
||||||
// set default MTU
|
// set default MTU
|
||||||
|
err = tun.setMTU(DefaultMTU)
|
||||||
|
|
||||||
err = device.setMTU(DefaultMTU)
|
return tun, err
|
||||||
|
|
||||||
return device, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ io.ReadWriteCloser = (*NativeTUN)(nil)
|
func (tun *NativeTun) Name() (string, error) {
|
||||||
|
|
||||||
func (t *NativeTUN) Events() chan TUNEvent {
|
var ifName struct {
|
||||||
return t.events
|
name [16]byte
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
t.rBuf = t.rBuf[:len(to)+4]
|
ifNameSize := uintptr(16)
|
||||||
|
|
||||||
n, err := t.f.Read(t.rBuf)
|
_, _, errno := unix.Syscall6(
|
||||||
copy(to, t.rBuf[4:])
|
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
|
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 {
|
// reserve space for header
|
||||||
return 0, unix.EIO
|
|
||||||
}
|
|
||||||
|
|
||||||
t.wMu.Lock()
|
buff = buff[offset-4:]
|
||||||
defer t.wMu.Unlock()
|
|
||||||
|
|
||||||
if cap(t.wBuf) < len(from)+4 {
|
// add packet information header
|
||||||
t.wBuf = make([]byte, len(from)+4)
|
|
||||||
}
|
|
||||||
t.wBuf = t.wBuf[:len(from)+4]
|
|
||||||
|
|
||||||
// determine the IP Family for the NULL L2 Header
|
buff[0] = 0x00
|
||||||
|
buff[1] = 0x00
|
||||||
|
buff[2] = 0x00
|
||||||
|
|
||||||
ipVer := from[0] >> 4
|
if buff[4]>>4 == ipv6.Version {
|
||||||
if ipVer == ipv4.Version {
|
buff[3] = unix.AF_INET6
|
||||||
t.wBuf[3] = unix.AF_INET
|
|
||||||
} else if ipVer == ipv6.Version {
|
|
||||||
t.wBuf[3] = unix.AF_INET6
|
|
||||||
} else {
|
} 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 tun.fd.Write(buff)
|
||||||
return n - 4, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *NativeTUN) Close() error {
|
func (tun *NativeTun) Close() error {
|
||||||
|
return tun.fd.Close()
|
||||||
// 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 (t *NativeTUN) Name() string {
|
func (tun *NativeTun) setMTU(n int) error {
|
||||||
return t.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *NativeTUN) setMTU(n int) error {
|
|
||||||
|
|
||||||
// open datagram socket
|
// open datagram socket
|
||||||
|
|
||||||
|
@ -267,7 +248,7 @@ func (t *NativeTUN) setMTU(n int) error {
|
||||||
// do ioctl call
|
// do ioctl call
|
||||||
|
|
||||||
var ifr [32]byte
|
var ifr [32]byte
|
||||||
copy(ifr[:], t.name)
|
copy(ifr[:], tun.name)
|
||||||
binary.LittleEndian.PutUint32(ifr[16:20], uint32(n))
|
binary.LittleEndian.PutUint32(ifr[16:20], uint32(n))
|
||||||
_, _, errno := unix.Syscall(
|
_, _, errno := unix.Syscall(
|
||||||
unix.SYS_IOCTL,
|
unix.SYS_IOCTL,
|
||||||
|
@ -277,13 +258,13 @@ func (t *NativeTUN) setMTU(n int) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
if errno != 0 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *NativeTUN) MTU() (int, error) {
|
func (tun *NativeTun) MTU() (int, error) {
|
||||||
|
|
||||||
// open datagram socket
|
// open datagram socket
|
||||||
|
|
||||||
|
@ -302,7 +283,7 @@ func (t *NativeTUN) MTU() (int, error) {
|
||||||
// do ioctl call
|
// do ioctl call
|
||||||
|
|
||||||
var ifr [64]byte
|
var ifr [64]byte
|
||||||
copy(ifr[:], t.name)
|
copy(ifr[:], tun.name)
|
||||||
_, _, errno := unix.Syscall(
|
_, _, errno := unix.Syscall(
|
||||||
unix.SYS_IOCTL,
|
unix.SYS_IOCTL,
|
||||||
uintptr(fd),
|
uintptr(fd),
|
||||||
|
@ -310,7 +291,7 @@ func (t *NativeTUN) MTU() (int, error) {
|
||||||
uintptr(unsafe.Pointer(&ifr[0])),
|
uintptr(unsafe.Pointer(&ifr[0])),
|
||||||
)
|
)
|
||||||
if errno != 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
|
// convert result to signed 32-bit int
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Copyright 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
/* Copyright 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
5
uapi.go
5
uapi.go
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
124
uapi_darwin.go
124
uapi_darwin.go
|
@ -1,12 +1,17 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -22,6 +27,8 @@ type UAPIListener struct {
|
||||||
listener net.Listener // unix socket listener
|
listener net.Listener // unix socket listener
|
||||||
connNew chan net.Conn
|
connNew chan net.Conn
|
||||||
connErr chan error
|
connErr chan error
|
||||||
|
kqueueFd int
|
||||||
|
keventFd int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *UAPIListener) Accept() (net.Conn, error) {
|
func (l *UAPIListener) Accept() (net.Conn, error) {
|
||||||
|
@ -37,30 +44,27 @@ func (l *UAPIListener) Accept() (net.Conn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *UAPIListener) Close() 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 {
|
func (l *UAPIListener) Addr() net.Addr {
|
||||||
return nil
|
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)
|
listener, err := net.FileListener(file)
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -71,14 +75,43 @@ func NewUAPIListener(name string) (net.Listener, error) {
|
||||||
connErr: make(chan error, 1),
|
connErr: make(chan error, 1),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socketPath := path.Join(
|
||||||
|
socketDirectory,
|
||||||
|
fmt.Sprintf(socketName, name),
|
||||||
|
)
|
||||||
|
|
||||||
// watch for deletion of socket
|
// 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) {
|
go func(l *UAPIListener) {
|
||||||
for ; ; time.Sleep(time.Second) {
|
event := unix.Kevent_t{
|
||||||
if _, err := os.Stat(socketPath); os.IsNotExist(err) {
|
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
|
l.connErr <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if kerr != nil || n != 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n, kerr = unix.Kevent(uapi.kqueueFd, []unix.Kevent_t{event}, events, nil)
|
||||||
}
|
}
|
||||||
}(uapi)
|
}(uapi)
|
||||||
|
|
||||||
|
@ -97,3 +130,56 @@ func NewUAPIListener(name string) (net.Listener, error) {
|
||||||
|
|
||||||
return uapi, nil
|
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()
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
/* UAPI on windows uses a bidirectional named pipe
|
/* UAPI on windows uses a bidirectional named pipe
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
|
/* SPDX-License-Identifier: MIT
|
||||||
// Use of this source code is governed by a license that can be
|
*
|
||||||
// found in the LICENSE file.
|
* Copyright (C) 2016 Andreas Auernhammer. All Rights Reserved.
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package xchacha20poly1305
|
package xchacha20poly1305
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
package xchacha20poly1305
|
package xchacha20poly1305
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
Loading…
Reference in a new issue