2021-09-05 16:00:43 +02:00
//go:build !windows
2019-02-04 17:29:52 +01:00
2019-01-02 01:55:51 +01:00
/ * SPDX - License - Identifier : MIT
2018-05-03 15:04:00 +02:00
*
2022-09-20 17:21:32 +02:00
* Copyright ( C ) 2017 - 2023 WireGuard LLC . All Rights Reserved .
2018-05-03 15:04:00 +02:00
* /
2017-05-30 22:36:49 +02:00
package main
2017-06-26 13:14:02 +02:00
import (
2017-07-20 15:06:24 +02:00
"fmt"
2017-06-29 14:39:21 +02:00
"os"
2017-08-01 12:14:38 +02:00
"os/signal"
2018-05-04 19:50:08 +02:00
"runtime"
2017-11-14 18:26:28 +01:00
"strconv"
2018-05-21 05:39:25 +02:00
"syscall"
2019-05-14 09:09:52 +02:00
2021-02-22 02:01:50 +01:00
"golang.zx2c4.com/wireguard/conn"
2019-05-14 09:09:52 +02:00
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/ipc"
"golang.zx2c4.com/wireguard/tun"
2017-11-14 18:26:28 +01:00
)
2017-11-30 23:30:29 +01:00
const (
ExitSetupSuccess = 0
ExitSetupFailed = 1
)
2017-11-14 18:26:28 +01:00
const (
2018-05-04 19:50:08 +02:00
ENV_WG_TUN_FD = "WG_TUN_FD"
ENV_WG_UAPI_FD = "WG_UAPI_FD"
2018-05-03 14:50:57 +02:00
ENV_WG_PROCESS_FOREGROUND = "WG_PROCESS_FOREGROUND"
2017-06-26 13:14:02 +02:00
)
2017-06-04 21:48:15 +02:00
2017-07-20 15:06:24 +02:00
func printUsage ( ) {
2021-04-16 07:32:44 +02:00
fmt . Printf ( "Usage: %s [-f/--foreground] INTERFACE-NAME\n" , os . Args [ 0 ] )
2017-07-20 15:06:24 +02:00
}
2018-05-04 19:50:08 +02:00
func warning ( ) {
2021-04-16 07:32:44 +02:00
switch runtime . GOOS {
case "linux" , "freebsd" , "openbsd" :
if os . Getenv ( ENV_WG_PROCESS_FOREGROUND ) == "1" {
return
}
default :
2018-05-14 15:58:40 +02:00
return
}
2018-05-07 22:27:03 +02:00
2021-04-16 07:32:44 +02:00
fmt . Fprintln ( os . Stderr , "┌──────────────────────────────────────────────────────┐" )
fmt . Fprintln ( os . Stderr , "│ │" )
fmt . Fprintln ( os . Stderr , "│ Running wireguard-go is not required because this │" )
fmt . Fprintln ( os . Stderr , "│ kernel has first class support for WireGuard. For │" )
fmt . Fprintln ( os . Stderr , "│ information on installing the kernel module, │" )
fmt . Fprintln ( os . Stderr , "│ please visit: │" )
fmt . Fprintln ( os . Stderr , "│ https://www.wireguard.com/install/ │" )
fmt . Fprintln ( os . Stderr , "│ │" )
fmt . Fprintln ( os . Stderr , "└──────────────────────────────────────────────────────┘" )
2018-05-04 19:50:08 +02:00
}
func main ( ) {
2018-05-24 01:52:22 +02:00
if len ( os . Args ) == 2 && os . Args [ 1 ] == "--version" {
2021-01-28 17:23:39 +01:00
fmt . Printf ( "wireguard-go v%s\n\nUserspace WireGuard daemon for %s-%s.\nInformation available at https://www.wireguard.com.\nCopyright (C) Jason A. Donenfeld <Jason@zx2c4.com>.\n" , Version , runtime . GOOS , runtime . GOARCH )
2018-05-24 01:52:22 +02:00
return
}
2018-05-04 19:50:08 +02:00
warning ( )
2018-05-03 04:49:35 +02:00
2017-07-15 13:41:02 +02:00
var foreground bool
var interfaceName string
if len ( os . Args ) < 2 || len ( os . Args ) > 3 {
2017-07-20 15:06:24 +02:00
printUsage ( )
2017-07-15 13:41:02 +02:00
return
}
switch os . Args [ 1 ] {
2017-07-17 16:16:18 +02:00
2017-07-15 13:41:02 +02:00
case "-f" , "--foreground" :
foreground = true
if len ( os . Args ) != 3 {
2017-07-20 15:06:24 +02:00
printUsage ( )
2017-07-15 13:41:02 +02:00
return
}
interfaceName = os . Args [ 2 ]
2017-07-17 16:16:18 +02:00
2017-07-15 13:41:02 +02:00
default :
foreground = false
if len ( os . Args ) != 2 {
2017-07-20 15:06:24 +02:00
printUsage ( )
2017-07-15 13:41:02 +02:00
return
}
interfaceName = os . Args [ 1 ]
}
2018-05-03 14:50:57 +02:00
if ! foreground {
foreground = os . Getenv ( ENV_WG_PROCESS_FOREGROUND ) == "1"
}
2017-08-11 16:18:20 +02:00
// get log level (default: info)
logLevel := func ( ) int {
switch os . Getenv ( "LOG_LEVEL" ) {
2021-01-26 23:05:48 +01:00
case "verbose" , "debug" :
return device . LogLevelVerbose
2017-08-11 16:18:20 +02:00
case "error" :
2019-03-03 04:04:41 +01:00
return device . LogLevelError
2018-05-14 03:38:06 +02:00
case "silent" :
2019-03-03 04:04:41 +01:00
return device . LogLevelSilent
2017-08-11 16:18:20 +02:00
}
2021-01-26 23:05:48 +01:00
return device . LogLevelError
2017-08-11 16:18:20 +02:00
} ( )
2017-11-17 14:36:08 +01:00
// open TUN device (or use supplied fd)
2017-07-15 13:41:02 +02:00
2019-06-10 23:33:40 +02:00
tun , err := func ( ) ( tun . Device , error ) {
2017-11-17 14:36:08 +01:00
tunFdStr := os . Getenv ( ENV_WG_TUN_FD )
2017-11-14 18:26:28 +01:00
if tunFdStr == "" {
2019-03-03 04:04:41 +01:00
return tun . CreateTUN ( interfaceName , device . DefaultMTU )
2017-11-14 18:26:28 +01:00
}
2017-10-27 10:43:37 +02:00
2017-11-17 14:36:08 +01:00
// construct tun device from supplied fd
2017-11-14 18:26:28 +01:00
fd , err := strconv . ParseUint ( tunFdStr , 10 , 32 )
if err != nil {
return nil , err
}
tun: use netpoll instead of rwcancel
The new sysconn function of Go 1.12 makes this possible:
package main
import "log"
import "os"
import "unsafe"
import "time"
import "syscall"
import "sync"
import "golang.org/x/sys/unix"
func main() {
fd, err := os.OpenFile("/dev/net/tun", os.O_RDWR, 0)
if err != nil {
log.Fatal(err)
}
var ifr [unix.IFNAMSIZ + 64]byte
copy(ifr[:], []byte("cheese"))
*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = unix.IFF_TUN
var errno syscall.Errno
s, _ := fd.SyscallConn()
s.Control(func(fd uintptr) {
_, _, errno = unix.Syscall(
unix.SYS_IOCTL,
fd,
uintptr(unix.TUNSETIFF),
uintptr(unsafe.Pointer(&ifr[0])),
)
})
if errno != 0 {
log.Fatal(errno)
}
b := [4]byte{}
wait := sync.WaitGroup{}
wait.Add(1)
go func() {
_, err := fd.Read(b[:])
log.Print("Read errored: ", err)
wait.Done()
}()
time.Sleep(time.Second)
log.Print("Closing")
err = fd.Close()
if err != nil {
log.Print("Close errored: " , err)
}
wait.Wait()
log.Print("Exiting")
}
2019-02-27 01:48:58 +01:00
err = syscall . SetNonblock ( int ( fd ) , true )
if err != nil {
return nil , err
}
2017-11-17 14:36:08 +01:00
file := os . NewFile ( uintptr ( fd ) , "" )
2019-03-03 04:04:41 +01:00
return tun . CreateTUNFromFile ( file , device . DefaultMTU )
2017-11-14 18:26:28 +01:00
} ( )
2018-05-04 21:11:38 +02:00
if err == nil {
realInterfaceName , err2 := tun . Name ( )
if err2 == nil {
interfaceName = realInterfaceName
}
}
2019-03-03 04:04:41 +01:00
logger := device . NewLogger (
2018-05-04 21:11:38 +02:00
logLevel ,
fmt . Sprintf ( "(%s) " , interfaceName ) ,
)
2021-01-28 17:23:39 +01:00
logger . Verbosef ( "Starting wireguard-go version %s" , Version )
2018-05-04 21:11:38 +02:00
2017-11-14 18:26:28 +01:00
if err != nil {
2021-01-22 23:11:17 +01:00
logger . Errorf ( "Failed to create TUN device: %v" , err )
2017-11-17 14:36:08 +01:00
os . Exit ( ExitSetupFailed )
2017-11-14 18:26:28 +01:00
}
2017-11-17 14:36:08 +01:00
// open UAPI file (or use supplied fd)
fileUAPI , err := func ( ) ( * os . File , error ) {
uapiFdStr := os . Getenv ( ENV_WG_UAPI_FD )
if uapiFdStr == "" {
2019-03-03 04:04:41 +01:00
return ipc . UAPIOpen ( interfaceName )
2017-11-17 14:36:08 +01:00
}
// use supplied fd
fd , err := strconv . ParseUint ( uapiFdStr , 10 , 32 )
if err != nil {
return nil , err
}
return os . NewFile ( uintptr ( fd ) , "" ) , nil
} ( )
if err != nil {
2021-01-22 23:11:17 +01:00
logger . Errorf ( "UAPI listen error: %v" , err )
2017-11-17 14:36:08 +01:00
os . Exit ( ExitSetupFailed )
return
}
2017-11-14 18:26:28 +01:00
// daemonize the process
if ! foreground {
env := os . Environ ( )
2017-11-17 14:36:08 +01:00
env = append ( env , fmt . Sprintf ( "%s=3" , ENV_WG_TUN_FD ) )
env = append ( env , fmt . Sprintf ( "%s=4" , ENV_WG_UAPI_FD ) )
2018-05-03 14:50:57 +02:00
env = append ( env , fmt . Sprintf ( "%s=1" , ENV_WG_PROCESS_FOREGROUND ) )
2018-05-14 03:38:06 +02:00
files := [ 3 ] * os . File { }
2019-03-03 04:04:41 +01:00
if os . Getenv ( "LOG_LEVEL" ) != "" && logLevel != device . LogLevelSilent {
2018-05-14 20:06:33 +02:00
files [ 0 ] , _ = os . Open ( os . DevNull )
2018-05-14 03:38:06 +02:00
files [ 1 ] = os . Stdout
files [ 2 ] = os . Stderr
2018-05-14 20:06:33 +02:00
} else {
files [ 0 ] , _ = os . Open ( os . DevNull )
files [ 1 ] , _ = os . Open ( os . DevNull )
files [ 2 ] , _ = os . Open ( os . DevNull )
2018-05-14 03:38:06 +02:00
}
2017-11-14 18:26:28 +01:00
attr := & os . ProcAttr {
Files : [ ] * os . File {
2018-05-14 03:38:06 +02:00
files [ 0 ] , // stdin
files [ 1 ] , // stdout
files [ 2 ] , // stderr
2017-11-14 18:26:28 +01:00
tun . File ( ) ,
2017-11-17 14:36:08 +01:00
fileUAPI ,
2017-11-14 18:26:28 +01:00
} ,
Dir : "." ,
Env : env ,
}
2018-05-03 14:50:57 +02:00
path , err := os . Executable ( )
if err != nil {
2021-01-22 23:11:17 +01:00
logger . Errorf ( "Failed to determine executable: %v" , err )
2018-05-03 14:50:57 +02:00
os . Exit ( ExitSetupFailed )
}
process , err := os . StartProcess (
path ,
os . Args ,
attr ,
)
2017-11-14 18:26:28 +01:00
if err != nil {
2021-01-22 23:11:17 +01:00
logger . Errorf ( "Failed to daemonize: %v" , err )
2017-11-17 14:36:08 +01:00
os . Exit ( ExitSetupFailed )
2017-11-14 18:26:28 +01:00
}
2018-05-03 14:50:57 +02:00
process . Release ( )
2017-11-14 18:26:28 +01:00
return
}
2021-02-22 02:01:50 +01:00
device := device . NewDevice ( tun , conn . NewDefaultBind ( ) , logger )
2017-11-17 14:36:08 +01:00
2021-01-26 23:05:48 +01:00
logger . Verbosef ( "Device started" )
2017-06-04 21:48:15 +02:00
2017-08-01 12:14:38 +02:00
errs := make ( chan error )
2018-05-21 05:39:25 +02:00
term := make ( chan os . Signal , 1 )
2017-07-13 14:32:40 +02:00
2019-03-03 04:04:41 +01:00
uapi , err := ipc . UAPIListen ( interfaceName , fileUAPI )
2018-05-04 21:51:55 +02:00
if err != nil {
2021-01-22 23:11:17 +01:00
logger . Errorf ( "Failed to listen on uapi socket: %v" , err )
2018-05-04 21:51:55 +02:00
os . Exit ( ExitSetupFailed )
}
2017-11-17 14:36:08 +01:00
2017-07-17 16:16:18 +02:00
go func ( ) {
for {
conn , err := uapi . Accept ( )
if err != nil {
2017-08-01 12:14:38 +02:00
errs <- err
return
2017-07-17 16:16:18 +02:00
}
2019-03-03 04:04:41 +01:00
go device . IpcHandle ( conn )
2017-07-13 14:32:40 +02:00
}
2017-07-17 16:16:18 +02:00
} ( )
2021-01-26 23:05:48 +01:00
logger . Verbosef ( "UAPI listener started" )
2017-08-01 12:14:38 +02:00
// wait for program to terminate
2018-05-21 05:39:25 +02:00
signal . Notify ( term , syscall . SIGTERM )
2017-08-01 12:14:38 +02:00
signal . Notify ( term , os . Interrupt )
select {
case <- term :
case <- errs :
2017-12-01 23:37:26 +01:00
case <- device . Wait ( ) :
2017-08-01 12:14:38 +02:00
}
2017-11-17 14:36:08 +01:00
// clean up
2017-08-01 12:14:38 +02:00
uapi . Close ( )
2017-11-17 14:36:08 +01:00
device . Close ( )
2017-08-01 12:14:38 +02:00
2021-01-26 23:05:48 +01:00
logger . Verbosef ( "Shutting down" )
2017-05-30 22:36:49 +02:00
}