Compare commits
52 Commits
0.0.201805
...
0.0.201812
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fde8334dc | ||
|
|
a8326ae753 | ||
|
|
05cc0c8298 | ||
|
|
c967f15e44 | ||
|
|
5ace0fdfe2 | ||
|
|
849fa400e9 | ||
|
|
651744561e | ||
|
|
4fd55daafe | ||
|
|
276bf973e8 | ||
|
|
c37c4ece9e | ||
|
|
b803276061 | ||
|
|
8be1fc9c00 | ||
|
|
738d027f0b | ||
|
|
60848b9c72 | ||
|
|
2e772194cf | ||
|
|
85b2378a07 | ||
|
|
fddb949002 | ||
|
|
5d6083df7e | ||
|
|
b41922e5c8 | ||
|
|
dbb72402f2 | ||
|
|
7c971d7ef4 | ||
|
|
70bcf9ecb8 | ||
|
|
ebc7541953 | ||
|
|
833597b585 | ||
|
|
cf81a28dd3 | ||
|
|
942abf948a | ||
|
|
47d1140361 | ||
|
|
39d6e4f2f1 | ||
|
|
1c02557013 | ||
|
|
32d2148835 | ||
|
|
5be541d147 | ||
|
|
063becdc73 | ||
|
|
15da869b31 | ||
|
|
3ad3e83c7a | ||
|
|
2e13b7b0fb | ||
|
|
6b3b1c3b91 | ||
|
|
6a5d0e2bcd | ||
|
|
0ba551807f | ||
|
|
99d5aeeb27 | ||
|
|
a050431f26 | ||
|
|
0c976003c8 | ||
|
|
955e89839f | ||
|
|
a4cd0216c0 | ||
|
|
1d7845a600 | ||
|
|
5079298ce2 | ||
|
|
fc3a7635e5 | ||
|
|
2496cdd8e6 | ||
|
|
4365b4583f | ||
|
|
bbf320c477 | ||
|
|
625d59da14 | ||
|
|
2f2eca8947 | ||
|
|
66f6ca3e4a |
42
Gopkg.lock
generated
42
Gopkg.lock
generated
@@ -1,42 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = [
|
||||
"blake2s",
|
||||
"chacha20poly1305",
|
||||
"curve25519",
|
||||
"internal/chacha20",
|
||||
"poly1305"
|
||||
]
|
||||
revision = "1a580b3eff7814fc9b40602fd35256c63b50f491"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = [
|
||||
"bpf",
|
||||
"internal/iana",
|
||||
"internal/socket",
|
||||
"ipv4",
|
||||
"ipv6"
|
||||
]
|
||||
revision = "9ef9f5bb98a1fdc41f8cf6c250a4404b4085e389"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = [
|
||||
"cpu",
|
||||
"unix"
|
||||
]
|
||||
revision = "88eb85aaee56831ad49eaf7aa80d73de9814cde2"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "d85ae9d2b4afafc3d7535505c46368cbbbec350cf876616302c1bcf44f6ec103"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
15
Gopkg.toml
15
Gopkg.toml
@@ -1,15 +0,0 @@
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
55
Makefile
55
Makefile
@@ -1,51 +1,42 @@
|
||||
PREFIX ?= /usr
|
||||
DESTDIR ?=
|
||||
BINDIR ?= $(PREFIX)/bin
|
||||
export GOPATH ?= $(CURDIR)/.gopath
|
||||
export GO111MODULE := on
|
||||
|
||||
ifeq ($(shell go env GOOS),linux)
|
||||
ifeq ($(wildcard .git),)
|
||||
all: generate-version-and-build
|
||||
|
||||
ifeq ($(shell go env GOOS)|$(wildcard .git),linux|)
|
||||
$(error Do not build this for Linux. Instead use the Linux kernel module. See wireguard.com/install/ for more info.)
|
||||
else
|
||||
$(shell printf 'package main\nconst UseTheKernelModuleInstead = 0xdeadbabe\n' > ireallywantobuildon_linux.go)
|
||||
endif
|
||||
ireallywantobuildon_linux.go:
|
||||
@printf "WARNING: This software is meant for use on non-Linux\nsystems. For Linux, please use the kernel module\ninstead. See wireguard.com/install/ for more info.\n\n" >&2
|
||||
@printf 'package main\nconst UseTheKernelModuleInstead = 0xdeadbabe\n' > "$@"
|
||||
clean-ireallywantobuildon_linux.go:
|
||||
@rm -f ireallywantobuildon_linux.go
|
||||
.PHONY: clean-ireallywantobuildon_linux.go
|
||||
clean: clean-ireallywantobuildon_linux.go
|
||||
wireguard-go: ireallywantobuildon_linux.go
|
||||
endif
|
||||
|
||||
all: wireguard-go
|
||||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
export GOPATH := $(CURDIR)/.gopath
|
||||
export PATH := $(PATH):$(CURDIR)/.gopath/bin
|
||||
GO_IMPORT_PATH := git.zx2c4.com/wireguard-go
|
||||
|
||||
version.go:
|
||||
generate-version-and-build:
|
||||
@export GIT_CEILING_DIRECTORIES="$(realpath $(CURDIR)/..)" && \
|
||||
tag="$$(git describe --dirty 2>/dev/null)" && \
|
||||
ver="$$(printf 'package main\nconst WireGuardGoVersion = "%s"\n' "$$tag")" && \
|
||||
[ "$$(cat $@ 2>/dev/null)" != "$$ver" ] && \
|
||||
echo "$$ver" > $@ && \
|
||||
git update-index --assume-unchanged $@ || true
|
||||
[ "$$(cat version.go 2>/dev/null)" != "$$ver" ] && \
|
||||
echo "$$ver" > version.go && \
|
||||
git update-index --assume-unchanged version.go || true
|
||||
@$(MAKE) wireguard-go
|
||||
|
||||
.gopath/.created:
|
||||
rm -rf .gopath
|
||||
mkdir -p $(dir .gopath/src/$(GO_IMPORT_PATH))
|
||||
ln -s ../../.. .gopath/src/$(GO_IMPORT_PATH)
|
||||
touch $@
|
||||
|
||||
vendor/.created: Gopkg.toml Gopkg.lock | .gopath/.created
|
||||
command -v dep >/dev/null || go get -v github.com/golang/dep/cmd/dep
|
||||
cd .gopath/src/$(GO_IMPORT_PATH) && dep ensure -vendor-only -v
|
||||
touch $@
|
||||
|
||||
wireguard-go: $(wildcard *.go) $(wildcard */*.go) .gopath/.created vendor/.created version.go
|
||||
go build $(GO_BUILD_EXTRA_ARGS) -v $(GO_IMPORT_PATH)
|
||||
wireguard-go: $(wildcard *.go) $(wildcard */*.go)
|
||||
go build -v -o "$@"
|
||||
|
||||
install: wireguard-go
|
||||
@install -v -d "$(DESTDIR)$(BINDIR)" && install -v -m 0755 wireguard-go "$(DESTDIR)$(BINDIR)/wireguard-go"
|
||||
@install -v -d "$(DESTDIR)$(BINDIR)" && install -v -m 0755 "$<" "$(DESTDIR)$(BINDIR)/wireguard-go"
|
||||
|
||||
clean:
|
||||
rm -f wireguard-go
|
||||
|
||||
update-dep: | .gopath/.created
|
||||
command -v dep >/dev/null || go get -v github.com/golang/dep/cmd/dep
|
||||
cd .gopath/src/$(GO_IMPORT_PATH) && dep ensure -update -v
|
||||
|
||||
.PHONY: clean install update-dep version.go
|
||||
.PHONY: all clean install generate-version-and-build
|
||||
|
||||
10
README.md
10
README.md
@@ -48,7 +48,7 @@ This will run on OpenBSD. It does not yet support sticky sockets. Fwmark is mapp
|
||||
|
||||
## Building
|
||||
|
||||
This requires an installation of [go](https://golang.org) and of [dep](https://github.com/golang/dep). If dep is not installed, it will be downloaded and built as part of the build process.
|
||||
This requires an installation of [go](https://golang.org) ≥ 1.11.
|
||||
|
||||
```
|
||||
$ git clone https://git.zx2c4.com/wireguard-go
|
||||
@@ -76,9 +76,9 @@ $ make
|
||||
are otherwise in compliance with the GPLv2 for each covered work you convey
|
||||
(including without limitation making the Corresponding Source available in
|
||||
compliance with Section 3 of the GPLv2), you are granted the additional
|
||||
the additional permission to convey through the Apple App Store
|
||||
non-source executable versions of the Program as incorporated into each
|
||||
applicable covered work as Executable Versions only under the Mozilla
|
||||
Public License version 2.0 (https://www.mozilla.org/en-US/MPL/2.0/).
|
||||
permission to convey through the Apple App Store non-source executable
|
||||
versions of the Program as incorporated into each applicable covered work
|
||||
as Executable Versions only under the Mozilla Public License version 2.0
|
||||
(https://www.mozilla.org/en-US/MPL/2.0/).
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
3
conn.go
3
conn.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
"net"
|
||||
"runtime"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
/* This code is meant to be a temporary solution
|
||||
@@ -87,6 +86,18 @@ func listenNet(network string, port int) (*net.UDPConn, int, error) {
|
||||
return conn, uaddr.Port, nil
|
||||
}
|
||||
|
||||
func extractErrno(err error) error {
|
||||
opErr, ok := err.(*net.OpError)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
syscallErr, ok := opErr.Err.(*os.SyscallError)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return syscallErr.Err
|
||||
}
|
||||
|
||||
func CreateBind(uport uint16, device *Device) (Bind, uint16, error) {
|
||||
var err error
|
||||
var bind NativeBind
|
||||
@@ -94,13 +105,15 @@ func CreateBind(uport uint16, device *Device) (Bind, uint16, error) {
|
||||
port := int(uport)
|
||||
|
||||
bind.ipv4, port, err = listenNet("udp4", port)
|
||||
if err != nil {
|
||||
if err != nil && extractErrno(err) != syscall.EAFNOSUPPORT {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
bind.ipv6, port, err = listenNet("udp6", port)
|
||||
if err != nil {
|
||||
if err != nil && extractErrno(err) != syscall.EAFNOSUPPORT {
|
||||
return nil, 0, err
|
||||
bind.ipv4.Close()
|
||||
bind.ipv4 = nil
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
@@ -108,8 +121,13 @@ func CreateBind(uport uint16, device *Device) (Bind, uint16, error) {
|
||||
}
|
||||
|
||||
func (bind *NativeBind) Close() error {
|
||||
err1 := bind.ipv4.Close()
|
||||
err2 := bind.ipv6.Close()
|
||||
var err1, err2 error
|
||||
if bind.ipv4 != nil {
|
||||
err1 = bind.ipv4.Close()
|
||||
}
|
||||
if bind.ipv6 != nil {
|
||||
err2 = bind.ipv6.Close()
|
||||
}
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
@@ -117,6 +135,9 @@ func (bind *NativeBind) Close() error {
|
||||
}
|
||||
|
||||
func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
|
||||
if bind.ipv4 == nil {
|
||||
return 0, nil, syscall.EAFNOSUPPORT
|
||||
}
|
||||
n, endpoint, err := bind.ipv4.ReadFromUDP(buff)
|
||||
if endpoint != nil {
|
||||
endpoint.IP = endpoint.IP.To4()
|
||||
@@ -125,6 +146,9 @@ func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
|
||||
}
|
||||
|
||||
func (bind *NativeBind) ReceiveIPv6(buff []byte) (int, Endpoint, error) {
|
||||
if bind.ipv6 == nil {
|
||||
return 0, nil, syscall.EAFNOSUPPORT
|
||||
}
|
||||
n, endpoint, err := bind.ipv6.ReadFromUDP(buff)
|
||||
return n, (*NativeEndpoint)(endpoint), err
|
||||
}
|
||||
@@ -133,55 +157,15 @@ func (bind *NativeBind) Send(buff []byte, endpoint Endpoint) error {
|
||||
var err error
|
||||
nend := endpoint.(*NativeEndpoint)
|
||||
if nend.IP.To4() != nil {
|
||||
if bind.ipv4 == nil {
|
||||
return syscall.EAFNOSUPPORT
|
||||
}
|
||||
_, err = bind.ipv4.WriteToUDP(buff, (*net.UDPAddr)(nend))
|
||||
} else {
|
||||
if bind.ipv6 == nil {
|
||||
return syscall.EAFNOSUPPORT
|
||||
}
|
||||
_, err = bind.ipv6.WriteToUDP(buff, (*net.UDPAddr)(nend))
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
var fwmarkIoctl int
|
||||
|
||||
func init() {
|
||||
switch runtime.GOOS {
|
||||
case "linux", "android":
|
||||
fwmarkIoctl = 36 /* unix.SO_MARK */
|
||||
case "freebsd":
|
||||
fwmarkIoctl = 0x1015 /* unix.SO_USER_COOKIE */
|
||||
case "openbsd":
|
||||
fwmarkIoctl = 0x1021 /* unix.SO_RTABLE */
|
||||
}
|
||||
}
|
||||
|
||||
func (bind *NativeBind) SetMark(mark uint32) error {
|
||||
if fwmarkIoctl == 0 {
|
||||
return nil
|
||||
}
|
||||
fd4, err1 := bind.ipv4.SyscallConn()
|
||||
fd6, err2 := bind.ipv6.SyscallConn()
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
err3 := fd4.Control(func(fd uintptr) {
|
||||
err1 = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
|
||||
})
|
||||
err4 := fd6.Control(func(fd uintptr) {
|
||||
err2 = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
|
||||
})
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
if err3 != nil {
|
||||
return err3
|
||||
}
|
||||
if err4 != nil {
|
||||
return err4
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
112
conn_linux.go
112
conn_linux.go
@@ -2,8 +2,7 @@
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*
|
||||
* This implements userspace semantics of "sticky sockets", modeled after
|
||||
* WireGuard's kernelspace implementation. This is more or less a straight port
|
||||
@@ -18,15 +17,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"errors"
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"golang.org/x/sys/unix"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
FD_ERR = -1
|
||||
)
|
||||
|
||||
type IPv4Source struct {
|
||||
src [4]byte
|
||||
ifindex int32
|
||||
@@ -126,6 +130,7 @@ func createNetlinkRouteSocket() (int, error) {
|
||||
func CreateBind(port uint16, device *Device) (*NativeBind, uint16, error) {
|
||||
var err error
|
||||
var bind NativeBind
|
||||
var newPort uint16
|
||||
|
||||
bind.netlinkSock, err = createNetlinkRouteSocket()
|
||||
if err != nil {
|
||||
@@ -139,41 +144,63 @@ func CreateBind(port uint16, device *Device) (*NativeBind, uint16, error) {
|
||||
|
||||
go bind.routineRouteListener(device)
|
||||
|
||||
bind.sock6, port, err = create6(port)
|
||||
// attempt ipv6 bind, update port if succesful
|
||||
|
||||
bind.sock6, newPort, err = create6(port)
|
||||
if err != nil {
|
||||
bind.netlinkCancel.Cancel()
|
||||
return nil, port, err
|
||||
if err != syscall.EAFNOSUPPORT {
|
||||
bind.netlinkCancel.Cancel()
|
||||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
port = newPort
|
||||
}
|
||||
|
||||
bind.sock4, port, err = create4(port)
|
||||
// attempt ipv4 bind, update port if succesful
|
||||
|
||||
bind.sock4, newPort, err = create4(port)
|
||||
if err != nil {
|
||||
bind.netlinkCancel.Cancel()
|
||||
unix.Close(bind.sock6)
|
||||
if err != syscall.EAFNOSUPPORT {
|
||||
bind.netlinkCancel.Cancel()
|
||||
unix.Close(bind.sock6)
|
||||
return nil, 0, err
|
||||
}
|
||||
} else {
|
||||
port = newPort
|
||||
}
|
||||
return &bind, port, err
|
||||
|
||||
if bind.sock4 == FD_ERR && bind.sock6 == FD_ERR {
|
||||
return nil, 0, errors.New("ipv4 and ipv6 not supported")
|
||||
}
|
||||
|
||||
return &bind, port, nil
|
||||
}
|
||||
|
||||
func (bind *NativeBind) SetMark(value uint32) error {
|
||||
err := unix.SetsockoptInt(
|
||||
bind.sock6,
|
||||
unix.SOL_SOCKET,
|
||||
unix.SO_MARK,
|
||||
int(value),
|
||||
)
|
||||
if bind.sock6 != -1 {
|
||||
err := unix.SetsockoptInt(
|
||||
bind.sock6,
|
||||
unix.SOL_SOCKET,
|
||||
unix.SO_MARK,
|
||||
int(value),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = unix.SetsockoptInt(
|
||||
bind.sock4,
|
||||
unix.SOL_SOCKET,
|
||||
unix.SO_MARK,
|
||||
int(value),
|
||||
)
|
||||
if bind.sock4 != -1 {
|
||||
err := unix.SetsockoptInt(
|
||||
bind.sock4,
|
||||
unix.SOL_SOCKET,
|
||||
unix.SO_MARK,
|
||||
int(value),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
bind.lastMark = value
|
||||
@@ -187,9 +214,14 @@ func closeUnblock(fd int) error {
|
||||
}
|
||||
|
||||
func (bind *NativeBind) Close() error {
|
||||
err1 := closeUnblock(bind.sock6)
|
||||
err2 := closeUnblock(bind.sock4)
|
||||
err3 := bind.netlinkCancel.Cancel()
|
||||
var err1, err2, err3 error
|
||||
if bind.sock6 != -1 {
|
||||
err1 = closeUnblock(bind.sock6)
|
||||
}
|
||||
if bind.sock4 != -1 {
|
||||
err2 = closeUnblock(bind.sock4)
|
||||
}
|
||||
err3 = bind.netlinkCancel.Cancel()
|
||||
|
||||
if err1 != nil {
|
||||
return err1
|
||||
@@ -202,6 +234,9 @@ func (bind *NativeBind) Close() error {
|
||||
|
||||
func (bind *NativeBind) ReceiveIPv6(buff []byte) (int, Endpoint, error) {
|
||||
var end NativeEndpoint
|
||||
if bind.sock6 == -1 {
|
||||
return 0, nil, syscall.EAFNOSUPPORT
|
||||
}
|
||||
n, err := receive6(
|
||||
bind.sock6,
|
||||
buff,
|
||||
@@ -212,6 +247,9 @@ func (bind *NativeBind) ReceiveIPv6(buff []byte) (int, Endpoint, error) {
|
||||
|
||||
func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
|
||||
var end NativeEndpoint
|
||||
if bind.sock4 == -1 {
|
||||
return 0, nil, syscall.EAFNOSUPPORT
|
||||
}
|
||||
n, err := receive4(
|
||||
bind.sock4,
|
||||
buff,
|
||||
@@ -223,8 +261,14 @@ func (bind *NativeBind) ReceiveIPv4(buff []byte) (int, Endpoint, error) {
|
||||
func (bind *NativeBind) Send(buff []byte, end Endpoint) error {
|
||||
nend := end.(*NativeEndpoint)
|
||||
if !nend.isV6 {
|
||||
if bind.sock4 == -1 {
|
||||
return syscall.EAFNOSUPPORT
|
||||
}
|
||||
return send4(bind.sock4, nend, buff)
|
||||
} else {
|
||||
if bind.sock6 == -1 {
|
||||
return syscall.EAFNOSUPPORT
|
||||
}
|
||||
return send6(bind.sock6, nend, buff)
|
||||
}
|
||||
}
|
||||
@@ -312,7 +356,7 @@ func create4(port uint16) (int, uint16, error) {
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return -1, 0, err
|
||||
return FD_ERR, 0, err
|
||||
}
|
||||
|
||||
addr := unix.SockaddrInet4{
|
||||
@@ -343,7 +387,7 @@ func create4(port uint16) (int, uint16, error) {
|
||||
return unix.Bind(fd, &addr)
|
||||
}(); err != nil {
|
||||
unix.Close(fd)
|
||||
return -1, 0, err
|
||||
return FD_ERR, 0, err
|
||||
}
|
||||
|
||||
return fd, uint16(addr.Port), err
|
||||
@@ -360,7 +404,7 @@ func create6(port uint16) (int, uint16, error) {
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return -1, 0, err
|
||||
return FD_ERR, 0, err
|
||||
}
|
||||
|
||||
// set sockopts and bind
|
||||
@@ -402,7 +446,7 @@ func create6(port uint16) (int, uint16, error) {
|
||||
|
||||
}(); err != nil {
|
||||
unix.Close(fd)
|
||||
return -1, 0, err
|
||||
return FD_ERR, 0, err
|
||||
}
|
||||
|
||||
return fd, uint16(addr.Port), err
|
||||
@@ -563,7 +607,7 @@ func (bind *NativeBind) routineRouteListener(device *Device) {
|
||||
var msgn int
|
||||
for {
|
||||
msgn, _, _, _, err = unix.Recvmsg(bind.netlinkSock, msg[:], nil, 0)
|
||||
if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
|
||||
if err == nil || !rwcancel.RetryAfterError(err) {
|
||||
break
|
||||
}
|
||||
if !bind.netlinkCancel.ReadyRead() {
|
||||
|
||||
17
constants.go
17
constants.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -27,18 +26,14 @@ const (
|
||||
PaddingMultiple = 16
|
||||
)
|
||||
|
||||
/* Implementation specific constants */
|
||||
|
||||
const (
|
||||
QueueOutboundSize = 1024
|
||||
QueueInboundSize = 1024
|
||||
QueueHandshakeSize = 1024
|
||||
MaxSegmentSize = (1 << 16) - 1 // largest possible UDP datagram
|
||||
MinMessageSize = MessageKeepaliveSize // minimum size of transport message (keepalive)
|
||||
MaxMessageSize = MaxSegmentSize // maximum size of transport message
|
||||
MaxContentSize = MaxSegmentSize - MessageTransportSize // maximum size of transport message content
|
||||
MinMessageSize = MessageKeepaliveSize // minimum size of transport message (keepalive)
|
||||
MaxMessageSize = MaxSegmentSize // maximum size of transport message
|
||||
MaxContentSize = MaxSegmentSize - MessageTransportSize // maximum size of transport message content
|
||||
)
|
||||
|
||||
/* Implementation constants */
|
||||
|
||||
const (
|
||||
UnderLoadQueueSize = QueueHandshakeSize / 8
|
||||
UnderLoadAfterTime = time.Second // how long does the device remain under load after detected
|
||||
|
||||
22
cookie.go
22
cookie.go
@@ -1,13 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/xchacha20poly1305"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"golang.org/x/crypto/blake2s"
|
||||
@@ -164,13 +162,8 @@ func (st *CookieChecker) CreateReply(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
xchacha20poly1305.Encrypt(
|
||||
reply.Cookie[:0],
|
||||
&reply.Nonce,
|
||||
cookie[:],
|
||||
msg[smac1:smac2],
|
||||
&st.mac2.encryptionKey,
|
||||
)
|
||||
xchapoly, _ := chacha20poly1305.NewX(st.mac2.encryptionKey[:])
|
||||
xchapoly.Seal(reply.Cookie[:0], reply.Nonce[:], cookie[:], msg[smac1:smac2])
|
||||
|
||||
st.mutex.RUnlock()
|
||||
|
||||
@@ -208,13 +201,8 @@ func (st *CookieGenerator) ConsumeReply(msg *MessageCookieReply) bool {
|
||||
|
||||
var cookie [blake2s.Size128]byte
|
||||
|
||||
_, err := xchacha20poly1305.Decrypt(
|
||||
cookie[:0],
|
||||
&msg.Nonce,
|
||||
msg.Cookie[:],
|
||||
st.mac2.lastMAC1[:],
|
||||
&st.mac2.encryptionKey,
|
||||
)
|
||||
xchapoly, _ := chacha20poly1305.NewX(st.mac2.encryptionKey[:])
|
||||
_, err := xchapoly.Open(cookie[:0], msg.Nonce[:], msg.Cookie[:], st.mac2.lastMAC1[:])
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
27
device.go
27
device.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -67,7 +66,12 @@ type Device struct {
|
||||
}
|
||||
|
||||
pool struct {
|
||||
messageBuffers sync.Pool
|
||||
messageBufferPool *sync.Pool
|
||||
messageBufferReuseChan chan *[MaxMessageSize]byte
|
||||
inboundElementPool *sync.Pool
|
||||
inboundElementReuseChan chan *QueueInboundElement
|
||||
outboundElementPool *sync.Pool
|
||||
outboundElementReuseChan chan *QueueOutboundElement
|
||||
}
|
||||
|
||||
queue struct {
|
||||
@@ -243,14 +247,6 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (device *Device) GetMessageBuffer() *[MaxMessageSize]byte {
|
||||
return device.pool.messageBuffers.Get().(*[MaxMessageSize]byte)
|
||||
}
|
||||
|
||||
func (device *Device) PutMessageBuffer(msg *[MaxMessageSize]byte) {
|
||||
device.pool.messageBuffers.Put(msg)
|
||||
}
|
||||
|
||||
func NewDevice(tunDevice tun.TUNDevice, logger *Logger) *Device {
|
||||
device := new(Device)
|
||||
|
||||
@@ -275,11 +271,7 @@ func NewDevice(tunDevice tun.TUNDevice, logger *Logger) *Device {
|
||||
device.indexTable.Init()
|
||||
device.allowedips.Reset()
|
||||
|
||||
device.pool.messageBuffers = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new([MaxMessageSize]byte)
|
||||
},
|
||||
}
|
||||
device.PopulatePools()
|
||||
|
||||
// create queues
|
||||
|
||||
@@ -385,10 +377,11 @@ func (device *Device) Close() {
|
||||
|
||||
close(device.signals.stop)
|
||||
|
||||
device.RemoveAllPeers()
|
||||
|
||||
device.state.stopping.Wait()
|
||||
device.FlushPacketQueues()
|
||||
|
||||
device.RemoveAllPeers()
|
||||
device.rate.limiter.Close()
|
||||
|
||||
device.state.changing.Set(false)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
7
go.mod
Normal file
7
go.mod
Normal file
@@ -0,0 +1,7 @@
|
||||
module git.zx2c4.com/wireguard-go
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9
|
||||
golang.org/x/net v0.0.0-20181207154023-610586996380
|
||||
golang.org/x/sys v0.0.0-20181210030007-2a47403f2ae5
|
||||
)
|
||||
6
go.sum
Normal file
6
go.sum
Normal file
@@ -0,0 +1,6 @@
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/net v0.0.0-20181207154023-610586996380 h1:zPQexyRtNYBc7bcHmehl1dH6TB3qn8zytv8cBGLDNY0=
|
||||
golang.org/x/net v0.0.0-20181207154023-610586996380/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sys v0.0.0-20181210030007-2a47403f2ae5 h1:SlFRMb9PEnqzqnBRCynVOhxv4vHjB2lnIoxK6p5nzFM=
|
||||
golang.org/x/sys v0.0.0-20181210030007-2a47403f2ae5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -9,6 +8,7 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"git.zx2c4.com/wireguard-go/tun"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
@@ -20,7 +20,7 @@ type DummyTUN struct {
|
||||
name string
|
||||
mtu int
|
||||
packets chan []byte
|
||||
events chan TUNEvent
|
||||
events chan tun.TUNEvent
|
||||
}
|
||||
|
||||
func (tun *DummyTUN) File() *os.File {
|
||||
@@ -46,7 +46,7 @@ func (tun *DummyTUN) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tun *DummyTUN) Events() chan TUNEvent {
|
||||
func (tun *DummyTUN) Events() chan tun.TUNEvent {
|
||||
return tun.events
|
||||
}
|
||||
|
||||
@@ -59,11 +59,11 @@ func (tun *DummyTUN) Read(d []byte, offset int) (int, error) {
|
||||
return len(t), nil
|
||||
}
|
||||
|
||||
func CreateDummyTUN(name string) (TUNDevice, error) {
|
||||
func CreateDummyTUN(name string) (tun.TUNDevice, error) {
|
||||
var dummy DummyTUN
|
||||
dummy.mtu = 0
|
||||
dummy.packets = make(chan []byte, 100)
|
||||
dummy.events = make(chan TUNEvent, 10)
|
||||
dummy.events = make(chan tun.TUNEvent, 10)
|
||||
return &dummy, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
3
ip.go
3
ip.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/replay"
|
||||
"crypto/cipher"
|
||||
"git.zx2c4.com/wireguard-go/replay"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
7
main.go
7
main.go
@@ -1,14 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/tun"
|
||||
"fmt"
|
||||
"git.zx2c4.com/wireguard-go/tun"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
@@ -160,6 +159,8 @@ func main() {
|
||||
fmt.Sprintf("(%s) ", interfaceName),
|
||||
)
|
||||
|
||||
logger.Info.Println("Starting wireguard-go version", WireGuardGoVersion)
|
||||
|
||||
logger.Debug.Println("Debug log enabled")
|
||||
|
||||
if err != nil {
|
||||
|
||||
12
mark_default.go
Normal file
12
mark_default.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// +build !linux,!openbsd,!freebsd
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
func (bind *NativeBind) SetMark(mark uint32) error {
|
||||
return nil
|
||||
}
|
||||
57
mark_unix.go
Normal file
57
mark_unix.go
Normal file
@@ -0,0 +1,57 @@
|
||||
// +build android openbsd freebsd
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var fwmarkIoctl int
|
||||
|
||||
func init() {
|
||||
switch runtime.GOOS {
|
||||
case "linux", "android":
|
||||
fwmarkIoctl = 36 /* unix.SO_MARK */
|
||||
case "freebsd":
|
||||
fwmarkIoctl = 0x1015 /* unix.SO_USER_COOKIE */
|
||||
case "openbsd":
|
||||
fwmarkIoctl = 0x1021 /* unix.SO_RTABLE */
|
||||
}
|
||||
}
|
||||
|
||||
func (bind *NativeBind) SetMark(mark uint32) error {
|
||||
if fwmarkIoctl == 0 {
|
||||
return nil
|
||||
}
|
||||
if bind.ipv4 != nil {
|
||||
fd, err := bind.ipv4.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = fd.Control(func(fd uintptr) {
|
||||
err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if bind.ipv6 != nil {
|
||||
fd, err := bind.ipv6.SyscallConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = fd.Control(func(fd uintptr) {
|
||||
err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, fwmarkIoctl, int(mark))
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
3
misc.go
3
misc.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/tai64n"
|
||||
"errors"
|
||||
"git.zx2c4.com/wireguard-go/tai64n"
|
||||
"golang.org/x/crypto/blake2s"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
"golang.org/x/crypto/poly1305"
|
||||
@@ -90,7 +89,7 @@ type MessageTransport struct {
|
||||
type MessageCookieReply struct {
|
||||
Type uint32
|
||||
Receiver uint32
|
||||
Nonce [24]byte
|
||||
Nonce [chacha20poly1305.NonceSizeX]byte
|
||||
Cookie [blake2s.Size128 + poly1305.TagSize]byte
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
14
peer.go
14
peer.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -258,3 +257,14 @@ func (peer *Peer) Stop() {
|
||||
|
||||
peer.ZeroAndFlushAll()
|
||||
}
|
||||
|
||||
var roamingDisabled bool
|
||||
|
||||
func (peer *Peer) SetEndpointFromPacket(endpoint Endpoint) {
|
||||
if roamingDisabled {
|
||||
return
|
||||
}
|
||||
peer.mutex.Lock()
|
||||
peer.endpoint = endpoint
|
||||
peer.mutex.Unlock()
|
||||
}
|
||||
|
||||
89
pools.go
Normal file
89
pools.go
Normal file
@@ -0,0 +1,89 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import "sync"
|
||||
|
||||
func (device *Device) PopulatePools() {
|
||||
if PreallocatedBuffersPerPool == 0 {
|
||||
device.pool.messageBufferPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new([MaxMessageSize]byte)
|
||||
},
|
||||
}
|
||||
device.pool.inboundElementPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(QueueInboundElement)
|
||||
},
|
||||
}
|
||||
device.pool.outboundElementPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(QueueOutboundElement)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
device.pool.messageBufferReuseChan = make(chan *[MaxMessageSize]byte, PreallocatedBuffersPerPool)
|
||||
for i := 0; i < PreallocatedBuffersPerPool; i += 1 {
|
||||
device.pool.messageBufferReuseChan <- new([MaxMessageSize]byte)
|
||||
}
|
||||
device.pool.inboundElementReuseChan = make(chan *QueueInboundElement, PreallocatedBuffersPerPool)
|
||||
for i := 0; i < PreallocatedBuffersPerPool; i += 1 {
|
||||
device.pool.inboundElementReuseChan <- new(QueueInboundElement)
|
||||
}
|
||||
device.pool.outboundElementReuseChan = make(chan *QueueOutboundElement, PreallocatedBuffersPerPool)
|
||||
for i := 0; i < PreallocatedBuffersPerPool; i += 1 {
|
||||
device.pool.outboundElementReuseChan <- new(QueueOutboundElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) GetMessageBuffer() *[MaxMessageSize]byte {
|
||||
if PreallocatedBuffersPerPool == 0 {
|
||||
return device.pool.messageBufferPool.Get().(*[MaxMessageSize]byte)
|
||||
} else {
|
||||
return <-device.pool.messageBufferReuseChan
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) PutMessageBuffer(msg *[MaxMessageSize]byte) {
|
||||
if PreallocatedBuffersPerPool == 0 {
|
||||
device.pool.messageBufferPool.Put(msg)
|
||||
} else {
|
||||
device.pool.messageBufferReuseChan <- msg
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) GetInboundElement() *QueueInboundElement {
|
||||
if PreallocatedBuffersPerPool == 0 {
|
||||
return device.pool.inboundElementPool.Get().(*QueueInboundElement)
|
||||
} else {
|
||||
return <-device.pool.inboundElementReuseChan
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) PutInboundElement(msg *QueueInboundElement) {
|
||||
if PreallocatedBuffersPerPool == 0 {
|
||||
device.pool.inboundElementPool.Put(msg)
|
||||
} else {
|
||||
device.pool.inboundElementReuseChan <- msg
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) GetOutboundElement() *QueueOutboundElement {
|
||||
if PreallocatedBuffersPerPool == 0 {
|
||||
return device.pool.outboundElementPool.Get().(*QueueOutboundElement)
|
||||
} else {
|
||||
return <-device.pool.outboundElementReuseChan
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) PutOutboundElement(msg *QueueOutboundElement) {
|
||||
if PreallocatedBuffersPerPool == 0 {
|
||||
device.pool.outboundElementPool.Put(msg)
|
||||
} else {
|
||||
device.pool.outboundElementReuseChan <- msg
|
||||
}
|
||||
}
|
||||
16
queueconstants.go
Normal file
16
queueconstants.go
Normal file
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
/* Implementation specific constants */
|
||||
|
||||
const (
|
||||
QueueOutboundSize = 1024
|
||||
QueueInboundSize = 1024
|
||||
QueueHandshakeSize = 1024
|
||||
MaxSegmentSize = (1 << 16) - 1 // largest possible UDP datagram
|
||||
PreallocatedBuffersPerPool = 0 // Disable and allow for infinite memory growth
|
||||
)
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package ratelimiter
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package ratelimiter
|
||||
|
||||
159
receive.go
159
receive.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -44,59 +43,29 @@ func (elem *QueueInboundElement) IsDropped() bool {
|
||||
return atomic.LoadInt32(&elem.dropped) == AtomicTrue
|
||||
}
|
||||
|
||||
func (device *Device) addToInboundQueue(
|
||||
queue chan *QueueInboundElement,
|
||||
element *QueueInboundElement,
|
||||
) {
|
||||
for {
|
||||
func (device *Device) addToInboundAndDecryptionQueues(inboundQueue chan *QueueInboundElement, decryptionQueue chan *QueueInboundElement, element *QueueInboundElement) bool {
|
||||
select {
|
||||
case inboundQueue <- element:
|
||||
select {
|
||||
case queue <- element:
|
||||
return
|
||||
case decryptionQueue <- element:
|
||||
return true
|
||||
default:
|
||||
select {
|
||||
case old := <-queue:
|
||||
old.Drop()
|
||||
default:
|
||||
}
|
||||
element.Drop()
|
||||
element.mutex.Unlock()
|
||||
return false
|
||||
}
|
||||
default:
|
||||
device.PutInboundElement(element)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) addToDecryptionQueue(
|
||||
queue chan *QueueInboundElement,
|
||||
element *QueueInboundElement,
|
||||
) {
|
||||
for {
|
||||
select {
|
||||
case queue <- element:
|
||||
return
|
||||
default:
|
||||
select {
|
||||
case old := <-queue:
|
||||
// drop & release to potential consumer
|
||||
old.Drop()
|
||||
old.mutex.Unlock()
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (device *Device) addToHandshakeQueue(
|
||||
queue chan QueueHandshakeElement,
|
||||
element QueueHandshakeElement,
|
||||
) {
|
||||
for {
|
||||
select {
|
||||
case queue <- element:
|
||||
return
|
||||
default:
|
||||
select {
|
||||
case elem := <-queue:
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
default:
|
||||
}
|
||||
}
|
||||
func (device *Device) addToHandshakeQueue(queue chan QueueHandshakeElement, element QueueHandshakeElement) bool {
|
||||
select {
|
||||
case queue <- element:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +97,7 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind Bind) {
|
||||
device.net.stopping.Done()
|
||||
}()
|
||||
|
||||
logDebug.Println("Routine: receive incoming IPv" + strconv.Itoa(IP) + " - starting")
|
||||
logDebug.Println("Routine: receive incoming IPv" + strconv.Itoa(IP) + " - started")
|
||||
device.net.starting.Done()
|
||||
|
||||
// receive datagrams until conn is closed
|
||||
@@ -155,6 +124,7 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind Bind) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
device.PutMessageBuffer(buffer)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -177,7 +147,7 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind Bind) {
|
||||
|
||||
// check size
|
||||
|
||||
if len(packet) < MessageTransportType {
|
||||
if len(packet) < MessageTransportSize {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -199,23 +169,23 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind Bind) {
|
||||
}
|
||||
|
||||
// create work element
|
||||
|
||||
peer := value.peer
|
||||
elem := &QueueInboundElement{
|
||||
packet: packet,
|
||||
buffer: buffer,
|
||||
keypair: keypair,
|
||||
dropped: AtomicFalse,
|
||||
endpoint: endpoint,
|
||||
}
|
||||
elem := device.GetInboundElement()
|
||||
elem.packet = packet
|
||||
elem.buffer = buffer
|
||||
elem.keypair = keypair
|
||||
elem.dropped = AtomicFalse
|
||||
elem.endpoint = endpoint
|
||||
elem.counter = 0
|
||||
elem.mutex = sync.Mutex{}
|
||||
elem.mutex.Lock()
|
||||
|
||||
// add to decryption queues
|
||||
|
||||
if peer.isRunning.Get() {
|
||||
device.addToDecryptionQueue(device.queue.decryption, elem)
|
||||
device.addToInboundQueue(peer.queue.inbound, elem)
|
||||
buffer = device.GetMessageBuffer()
|
||||
if device.addToInboundAndDecryptionQueues(peer.queue.inbound, device.queue.decryption, elem) {
|
||||
buffer = device.GetMessageBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
@@ -236,7 +206,7 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind Bind) {
|
||||
}
|
||||
|
||||
if okay {
|
||||
device.addToHandshakeQueue(
|
||||
if (device.addToHandshakeQueue(
|
||||
device.queue.handshake,
|
||||
QueueHandshakeElement{
|
||||
msgType: msgType,
|
||||
@@ -244,8 +214,9 @@ func (device *Device) RoutineReceiveIncoming(IP int, bind Bind) {
|
||||
packet: packet,
|
||||
endpoint: endpoint,
|
||||
},
|
||||
)
|
||||
buffer = device.GetMessageBuffer()
|
||||
)) {
|
||||
buffer = device.GetMessageBuffer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,6 +279,7 @@ func (device *Device) RoutineDecryption() {
|
||||
)
|
||||
if err != nil {
|
||||
elem.Drop()
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
}
|
||||
elem.mutex.Unlock()
|
||||
}
|
||||
@@ -322,18 +294,26 @@ func (device *Device) RoutineHandshake() {
|
||||
logError := device.log.Error
|
||||
logDebug := device.log.Debug
|
||||
|
||||
var elem QueueHandshakeElement
|
||||
var ok bool
|
||||
|
||||
defer func() {
|
||||
logDebug.Println("Routine: handshake worker - stopped")
|
||||
device.state.stopping.Done()
|
||||
if elem.buffer != nil {
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
}
|
||||
}()
|
||||
|
||||
logDebug.Println("Routine: handshake worker - started")
|
||||
device.state.starting.Done()
|
||||
|
||||
var elem QueueHandshakeElement
|
||||
var ok bool
|
||||
|
||||
for {
|
||||
if elem.buffer != nil {
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
elem.buffer = nil
|
||||
}
|
||||
|
||||
select {
|
||||
case elem, ok = <-device.queue.handshake:
|
||||
case <-device.signals.stop:
|
||||
@@ -371,7 +351,10 @@ func (device *Device) RoutineHandshake() {
|
||||
// consume reply
|
||||
|
||||
if peer := entry.peer; peer.isRunning.Get() {
|
||||
peer.cookieGenerator.ConsumeReply(&reply)
|
||||
logDebug.Println("Receiving cookie response from ", elem.endpoint.DstToString())
|
||||
if !peer.cookieGenerator.ConsumeReply(&reply) {
|
||||
logDebug.Println("Could not decrypt invalid cookie response")
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
@@ -440,10 +423,7 @@ func (device *Device) RoutineHandshake() {
|
||||
peer.timersAnyAuthenticatedPacketReceived()
|
||||
|
||||
// update endpoint
|
||||
|
||||
peer.mutex.Lock()
|
||||
peer.endpoint = elem.endpoint
|
||||
peer.mutex.Unlock()
|
||||
peer.SetEndpointFromPacket(elem.endpoint)
|
||||
|
||||
logDebug.Println(peer, "- Received handshake initiation")
|
||||
|
||||
@@ -473,10 +453,7 @@ func (device *Device) RoutineHandshake() {
|
||||
}
|
||||
|
||||
// update endpoint
|
||||
|
||||
peer.mutex.Lock()
|
||||
peer.endpoint = elem.endpoint
|
||||
peer.mutex.Unlock()
|
||||
peer.SetEndpointFromPacket(elem.endpoint)
|
||||
|
||||
logDebug.Println(peer, "- Received handshake response")
|
||||
|
||||
@@ -512,9 +489,18 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
||||
logError := device.log.Error
|
||||
logDebug := device.log.Debug
|
||||
|
||||
var elem *QueueInboundElement
|
||||
var ok bool
|
||||
|
||||
defer func() {
|
||||
logDebug.Println(peer, "- Routine: sequential receiver - stopped")
|
||||
peer.routines.stopping.Done()
|
||||
if elem != nil {
|
||||
if !elem.IsDropped() {
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
}
|
||||
device.PutInboundElement(elem)
|
||||
}
|
||||
}()
|
||||
|
||||
logDebug.Println(peer, "- Routine: sequential receiver - started")
|
||||
@@ -522,13 +508,20 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
||||
peer.routines.starting.Done()
|
||||
|
||||
for {
|
||||
if elem != nil {
|
||||
if !elem.IsDropped() {
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
}
|
||||
device.PutInboundElement(elem)
|
||||
elem = nil
|
||||
}
|
||||
|
||||
select {
|
||||
|
||||
case <-peer.routines.stop:
|
||||
return
|
||||
|
||||
case elem, ok := <-peer.queue.inbound:
|
||||
case elem, ok = <-peer.queue.inbound:
|
||||
|
||||
if !ok {
|
||||
return
|
||||
@@ -549,10 +542,7 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
||||
}
|
||||
|
||||
// update endpoint
|
||||
|
||||
peer.mutex.Lock()
|
||||
peer.endpoint = elem.endpoint
|
||||
peer.mutex.Unlock()
|
||||
peer.SetEndpointFromPacket(elem.endpoint)
|
||||
|
||||
// check if using new keypair
|
||||
if peer.ReceivedWithKeypair(elem.keypair) {
|
||||
@@ -642,10 +632,7 @@ func (peer *Peer) RoutineSequentialReceiver() {
|
||||
|
||||
offset := MessageTransportOffsetContent
|
||||
atomic.AddUint64(&peer.stats.rxBytes, uint64(len(elem.packet)))
|
||||
_, err := device.tun.device.Write(
|
||||
elem.buffer[:offset+len(elem.packet)],
|
||||
offset)
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
_, err := device.tun.device.Write(elem.buffer[:offset+len(elem.packet)], offset)
|
||||
if err != nil {
|
||||
logError.Println("Failed to write packet to TUN device:", err)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package replay
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package replay
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// +build !freebsd
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package rwcancel
|
||||
@@ -1,22 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package rwcancel
|
||||
|
||||
import "golang.org/x/sys/unix"
|
||||
|
||||
type fdSet struct {
|
||||
fdset unix.FdSet
|
||||
}
|
||||
|
||||
func (fdset *fdSet) set(i int) {
|
||||
bits := 32 << (^uint(0) >> 63)
|
||||
fdset.fdset.X__fds_bits[i/bits] |= 1 << uint(i%bits)
|
||||
}
|
||||
|
||||
func (fdset *fdSet) check(i int) bool {
|
||||
bits := 32 << (^uint(0) >> 63)
|
||||
return (fdset.fdset.X__fds_bits[i/bits] & (1 << uint(i%bits))) != 0
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package rwcancel
|
||||
@@ -40,15 +40,16 @@ func NewRWCancel(fd int) (*RWCancel, error) {
|
||||
return &rwcancel, nil
|
||||
}
|
||||
|
||||
/* https://golang.org/src/crypto/rand/eagain.go */
|
||||
func ErrorIsEAGAIN(err error) bool {
|
||||
func RetryAfterError(err error) bool {
|
||||
if pe, ok := err.(*os.PathError); ok {
|
||||
if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EAGAIN {
|
||||
err = pe.Err
|
||||
}
|
||||
if errno, ok := err.(syscall.Errno); ok {
|
||||
switch errno {
|
||||
case syscall.EAGAIN, syscall.EINTR:
|
||||
return true
|
||||
}
|
||||
}
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EAGAIN {
|
||||
return true
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -86,7 +87,7 @@ func (rw *RWCancel) ReadyWrite() bool {
|
||||
func (rw *RWCancel) Read(p []byte) (n int, err error) {
|
||||
for {
|
||||
n, err := unix.Read(rw.fd, p)
|
||||
if err == nil || !ErrorIsEAGAIN(err) {
|
||||
if err == nil || !RetryAfterError(err) {
|
||||
return n, err
|
||||
}
|
||||
if !rw.ReadyRead() {
|
||||
@@ -98,7 +99,7 @@ func (rw *RWCancel) Read(p []byte) (n int, err error) {
|
||||
func (rw *RWCancel) Write(p []byte) (n int, err error) {
|
||||
for {
|
||||
n, err := unix.Write(rw.fd, p)
|
||||
if err == nil || !ErrorIsEAGAIN(err) {
|
||||
if err == nil || !RetryAfterError(err) {
|
||||
return n, err
|
||||
}
|
||||
if !rw.ReadyWrite() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package rwcancel
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package rwcancel
|
||||
|
||||
137
send.go
137
send.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -53,10 +52,14 @@ type QueueOutboundElement struct {
|
||||
}
|
||||
|
||||
func (device *Device) NewOutboundElement() *QueueOutboundElement {
|
||||
return &QueueOutboundElement{
|
||||
dropped: AtomicFalse,
|
||||
buffer: device.pool.messageBuffers.Get().(*[MaxMessageSize]byte),
|
||||
}
|
||||
elem := device.GetOutboundElement()
|
||||
elem.dropped = AtomicFalse
|
||||
elem.buffer = device.GetMessageBuffer()
|
||||
elem.mutex = sync.Mutex{}
|
||||
elem.nonce = 0
|
||||
elem.keypair = nil
|
||||
elem.peer = nil
|
||||
return elem
|
||||
}
|
||||
|
||||
func (elem *QueueOutboundElement) Drop() {
|
||||
@@ -67,10 +70,7 @@ func (elem *QueueOutboundElement) IsDropped() bool {
|
||||
return atomic.LoadInt32(&elem.dropped) == AtomicTrue
|
||||
}
|
||||
|
||||
func addToOutboundQueue(
|
||||
queue chan *QueueOutboundElement,
|
||||
element *QueueOutboundElement,
|
||||
) {
|
||||
func addToNonceQueue(queue chan *QueueOutboundElement, element *QueueOutboundElement, device *Device) {
|
||||
for {
|
||||
select {
|
||||
case queue <- element:
|
||||
@@ -78,30 +78,28 @@ func addToOutboundQueue(
|
||||
default:
|
||||
select {
|
||||
case old := <-queue:
|
||||
old.Drop()
|
||||
device.PutMessageBuffer(old.buffer)
|
||||
device.PutOutboundElement(old)
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addToEncryptionQueue(
|
||||
queue chan *QueueOutboundElement,
|
||||
element *QueueOutboundElement,
|
||||
) {
|
||||
for {
|
||||
func addToOutboundAndEncryptionQueues(outboundQueue chan *QueueOutboundElement, encryptionQueue chan *QueueOutboundElement, element *QueueOutboundElement) {
|
||||
select {
|
||||
case outboundQueue <- element:
|
||||
select {
|
||||
case queue <- element:
|
||||
case encryptionQueue <- element:
|
||||
return
|
||||
default:
|
||||
select {
|
||||
case old := <-queue:
|
||||
// drop & release to potential consumer
|
||||
old.Drop()
|
||||
old.mutex.Unlock()
|
||||
default:
|
||||
}
|
||||
element.Drop()
|
||||
element.peer.device.PutMessageBuffer(element.buffer)
|
||||
element.mutex.Unlock()
|
||||
}
|
||||
default:
|
||||
element.peer.device.PutMessageBuffer(element.buffer)
|
||||
element.peer.device.PutOutboundElement(element)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +116,8 @@ func (peer *Peer) SendKeepalive() bool {
|
||||
peer.device.log.Debug.Println(peer, "- Sending keepalive packet")
|
||||
return true
|
||||
default:
|
||||
peer.device.PutMessageBuffer(elem.buffer)
|
||||
peer.device.PutOutboundElement(elem)
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ func (peer *Peer) SendHandshakeResponse() error {
|
||||
|
||||
func (device *Device) SendHandshakeCookie(initiatingElem *QueueHandshakeElement) error {
|
||||
|
||||
device.log.Debug.Println("Sending cookie reply to:", initiatingElem.endpoint.DstToString())
|
||||
device.log.Debug.Println("Sending cookie response for denied handshake message for", initiatingElem.endpoint.DstToString())
|
||||
|
||||
sender := binary.LittleEndian.Uint32(initiatingElem.packet[4:8])
|
||||
reply, err := device.cookieChecker.CreateReply(initiatingElem.packet, sender, initiatingElem.endpoint.DstToBytes())
|
||||
@@ -243,8 +243,6 @@ func (peer *Peer) keepKeyFreshSending() {
|
||||
*/
|
||||
func (device *Device) RoutineReadFromTUN() {
|
||||
|
||||
elem := device.NewOutboundElement()
|
||||
|
||||
logDebug := device.log.Debug
|
||||
logError := device.log.Error
|
||||
|
||||
@@ -256,7 +254,14 @@ func (device *Device) RoutineReadFromTUN() {
|
||||
logDebug.Println("Routine: TUN reader - started")
|
||||
device.state.starting.Done()
|
||||
|
||||
var elem *QueueOutboundElement
|
||||
|
||||
for {
|
||||
if elem != nil {
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
device.PutOutboundElement(elem)
|
||||
}
|
||||
elem = device.NewOutboundElement()
|
||||
|
||||
// read packet
|
||||
|
||||
@@ -268,6 +273,8 @@ func (device *Device) RoutineReadFromTUN() {
|
||||
logError.Println("Failed to read packet from TUN device:", err)
|
||||
device.Close()
|
||||
}
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
device.PutOutboundElement(elem)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -309,8 +316,8 @@ func (device *Device) RoutineReadFromTUN() {
|
||||
if peer.queue.packetInNonceQueueIsAwaitingKey.Get() {
|
||||
peer.SendHandshakeInitiation(false)
|
||||
}
|
||||
addToOutboundQueue(peer.queue.nonce, elem)
|
||||
elem = device.NewOutboundElement()
|
||||
addToNonceQueue(peer.queue.nonce, elem, device)
|
||||
elem = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,22 +341,25 @@ func (peer *Peer) RoutineNonce() {
|
||||
device := peer.device
|
||||
logDebug := device.log.Debug
|
||||
|
||||
defer func() {
|
||||
logDebug.Println(peer, "- Routine: nonce worker - stopped")
|
||||
peer.queue.packetInNonceQueueIsAwaitingKey.Set(false)
|
||||
peer.routines.stopping.Done()
|
||||
}()
|
||||
|
||||
flush := func() {
|
||||
for {
|
||||
select {
|
||||
case <-peer.queue.nonce:
|
||||
case elem := <-peer.queue.nonce:
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
device.PutOutboundElement(elem)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defer func() {
|
||||
flush()
|
||||
logDebug.Println(peer, "- Routine: nonce worker - stopped")
|
||||
peer.queue.packetInNonceQueueIsAwaitingKey.Set(false)
|
||||
peer.routines.stopping.Done()
|
||||
}()
|
||||
|
||||
peer.routines.starting.Done()
|
||||
logDebug.Println(peer, "- Routine: nonce worker - started")
|
||||
|
||||
@@ -403,10 +413,14 @@ func (peer *Peer) RoutineNonce() {
|
||||
logDebug.Println(peer, "- Obtained awaited keypair")
|
||||
|
||||
case <-peer.signals.flushNonceQueue:
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
device.PutOutboundElement(elem)
|
||||
flush()
|
||||
goto NextPacket
|
||||
|
||||
case <-peer.routines.stop:
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
device.PutOutboundElement(elem)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -421,6 +435,8 @@ func (peer *Peer) RoutineNonce() {
|
||||
|
||||
if elem.nonce >= RejectAfterMessages {
|
||||
atomic.StoreUint64(&keypair.sendNonce, RejectAfterMessages)
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
device.PutOutboundElement(elem)
|
||||
goto NextPacket
|
||||
}
|
||||
|
||||
@@ -429,9 +445,7 @@ func (peer *Peer) RoutineNonce() {
|
||||
elem.mutex.Lock()
|
||||
|
||||
// add to parallel and sequential queue
|
||||
|
||||
addToEncryptionQueue(device.queue.encryption, elem)
|
||||
addToOutboundQueue(peer.queue.outbound, elem)
|
||||
addToOutboundAndEncryptionQueues(peer.queue.outbound, device.queue.encryption, elem)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -448,6 +462,19 @@ func (device *Device) RoutineEncryption() {
|
||||
logDebug := device.log.Debug
|
||||
|
||||
defer func() {
|
||||
for {
|
||||
select {
|
||||
case elem, ok := <-device.queue.encryption:
|
||||
if ok && !elem.IsDropped() {
|
||||
elem.Drop()
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
elem.mutex.Unlock()
|
||||
}
|
||||
default:
|
||||
goto out
|
||||
}
|
||||
}
|
||||
out:
|
||||
logDebug.Println("Routine: encryption worker - stopped")
|
||||
device.state.stopping.Done()
|
||||
}()
|
||||
@@ -490,11 +517,13 @@ func (device *Device) RoutineEncryption() {
|
||||
// pad content to multiple of 16
|
||||
|
||||
mtu := int(atomic.LoadInt32(&device.tun.mtu))
|
||||
rem := len(elem.packet) % PaddingMultiple
|
||||
if rem > 0 {
|
||||
for i := 0; i < PaddingMultiple-rem && len(elem.packet) < mtu; i++ {
|
||||
elem.packet = append(elem.packet, 0)
|
||||
}
|
||||
lastUnit := len(elem.packet) % mtu
|
||||
paddedSize := (lastUnit + PaddingMultiple - 1) & ^(PaddingMultiple - 1)
|
||||
if paddedSize > mtu {
|
||||
paddedSize = mtu
|
||||
}
|
||||
for i := len(elem.packet); i < paddedSize; i++ {
|
||||
elem.packet = append(elem.packet, 0)
|
||||
}
|
||||
|
||||
// encrypt content and release to consumer
|
||||
@@ -521,8 +550,24 @@ func (peer *Peer) RoutineSequentialSender() {
|
||||
device := peer.device
|
||||
|
||||
logDebug := device.log.Debug
|
||||
logError := device.log.Error
|
||||
|
||||
defer func() {
|
||||
for {
|
||||
select {
|
||||
case elem, ok := <-peer.queue.outbound:
|
||||
if ok {
|
||||
if !elem.IsDropped() {
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
elem.Drop()
|
||||
}
|
||||
device.PutOutboundElement(elem)
|
||||
}
|
||||
default:
|
||||
goto out
|
||||
}
|
||||
}
|
||||
out:
|
||||
logDebug.Println(peer, "- Routine: sequential sender - stopped")
|
||||
peer.routines.stopping.Done()
|
||||
}()
|
||||
@@ -545,6 +590,7 @@ func (peer *Peer) RoutineSequentialSender() {
|
||||
|
||||
elem.mutex.Lock()
|
||||
if elem.IsDropped() {
|
||||
device.PutOutboundElement(elem)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -556,8 +602,9 @@ func (peer *Peer) RoutineSequentialSender() {
|
||||
length := uint64(len(elem.packet))
|
||||
err := peer.SendBuffer(elem.packet)
|
||||
device.PutMessageBuffer(elem.buffer)
|
||||
device.PutOutboundElement(elem)
|
||||
if err != nil {
|
||||
logDebug.Println("Failed to send authenticated packet to peer", peer)
|
||||
logError.Println(peer, "- Failed to send data packet", err)
|
||||
continue
|
||||
}
|
||||
atomic.AddUint64(&peer.stats.txBytes, length)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package tai64n
|
||||
@@ -20,7 +20,7 @@ func Now() Timestamp {
|
||||
var tai64n Timestamp
|
||||
now := time.Now()
|
||||
secs := base + uint64(now.Unix())
|
||||
nano := uint32(now.UnixNano())
|
||||
nano := uint32(now.Nanosecond())
|
||||
binary.BigEndian.PutUint64(tai64n[:], secs)
|
||||
binary.BigEndian.PutUint32(tai64n[8:], nano)
|
||||
return tai64n
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package tai64n
|
||||
|
||||
10
timers.go
10
timers.go
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*
|
||||
* This is based heavily on timers.c from the kernel implementation.
|
||||
*/
|
||||
@@ -79,7 +79,7 @@ func (peer *Peer) timersActive() bool {
|
||||
|
||||
func expiredRetransmitHandshake(peer *Peer) {
|
||||
if atomic.LoadUint32(&peer.timers.handshakeAttempts) > MaxTimerHandshakes {
|
||||
peer.device.log.Debug.Printf("%s: Handshake did not complete after %d attempts, giving up\n", peer, MaxTimerHandshakes+2)
|
||||
peer.device.log.Debug.Printf("%s - Handshake did not complete after %d attempts, giving up\n", peer, MaxTimerHandshakes+2)
|
||||
|
||||
if peer.timersActive() {
|
||||
peer.timers.sendKeepalive.Del()
|
||||
@@ -98,7 +98,7 @@ func expiredRetransmitHandshake(peer *Peer) {
|
||||
}
|
||||
} else {
|
||||
atomic.AddUint32(&peer.timers.handshakeAttempts, 1)
|
||||
peer.device.log.Debug.Printf("%s: Handshake did not complete after %d seconds, retrying (try %d)\n", peer, int(RekeyTimeout.Seconds()), atomic.LoadUint32(&peer.timers.handshakeAttempts)+1)
|
||||
peer.device.log.Debug.Printf("%s - Handshake did not complete after %d seconds, retrying (try %d)\n", peer, int(RekeyTimeout.Seconds()), atomic.LoadUint32(&peer.timers.handshakeAttempts)+1)
|
||||
|
||||
/* We clear the endpoint address src address, in case this is the cause of trouble. */
|
||||
peer.mutex.Lock()
|
||||
@@ -122,7 +122,7 @@ func expiredSendKeepalive(peer *Peer) {
|
||||
}
|
||||
|
||||
func expiredNewHandshake(peer *Peer) {
|
||||
peer.device.log.Debug.Printf("%s: Retrying handshake because we stopped hearing back after %d seconds\n", peer, int((KeepaliveTimeout + RekeyTimeout).Seconds()))
|
||||
peer.device.log.Debug.Printf("%s - Retrying handshake because we stopped hearing back after %d seconds\n", peer, int((KeepaliveTimeout + RekeyTimeout).Seconds()))
|
||||
/* We clear the endpoint address src address, in case this is the cause of trouble. */
|
||||
peer.mutex.Lock()
|
||||
if peer.endpoint != nil {
|
||||
@@ -134,7 +134,7 @@ func expiredNewHandshake(peer *Peer) {
|
||||
}
|
||||
|
||||
func expiredZeroKeyMaterial(peer *Peer) {
|
||||
peer.device.log.Debug.Printf(":%s Removing all keys, since we haven't received a new one in %d seconds\n", peer, int((RejectAfterTime * 3).Seconds()))
|
||||
peer.device.log.Debug.Printf("%s - Removing all keys, since we haven't received a new one in %d seconds\n", peer, int((RejectAfterTime * 3).Seconds()))
|
||||
peer.ZeroAndFlushAll()
|
||||
}
|
||||
|
||||
|
||||
3
tun.go
3
tun.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package tun
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package tun
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"golang.org/x/net/ipv6"
|
||||
"golang.org/x/sys/unix"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -35,7 +35,8 @@ type sockaddrCtl struct {
|
||||
|
||||
type nativeTun struct {
|
||||
name string
|
||||
fd *os.File
|
||||
tunFile *os.File
|
||||
fd uintptr
|
||||
rwcancel *rwcancel.RWCancel
|
||||
events chan TUNEvent
|
||||
errors chan error
|
||||
@@ -54,8 +55,12 @@ func (tun *nativeTun) routineRouteListener(tunIfindex int) {
|
||||
|
||||
data := make([]byte, os.Getpagesize())
|
||||
for {
|
||||
retry:
|
||||
n, err := unix.Read(tun.routeSocket, data)
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
|
||||
goto retry
|
||||
}
|
||||
tun.errors <- err
|
||||
return
|
||||
}
|
||||
@@ -165,14 +170,15 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
||||
func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
|
||||
tun := &nativeTun{
|
||||
fd: file,
|
||||
events: make(chan TUNEvent, 10),
|
||||
errors: make(chan error, 1),
|
||||
tunFile: file,
|
||||
fd: file.Fd(),
|
||||
events: make(chan TUNEvent, 10),
|
||||
errors: make(chan error, 1),
|
||||
}
|
||||
|
||||
name, err := tun.Name()
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -184,19 +190,19 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
return iface.Index, nil
|
||||
}()
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tun.rwcancel, err = rwcancel.NewRWCancel(int(file.Fd()))
|
||||
tun.rwcancel, err = rwcancel.NewRWCancel(int(tun.fd))
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -220,7 +226,7 @@ func (tun *nativeTun) Name() (string, error) {
|
||||
|
||||
_, _, errno := unix.Syscall6(
|
||||
unix.SYS_GETSOCKOPT,
|
||||
uintptr(tun.fd.Fd()),
|
||||
uintptr(tun.fd),
|
||||
2, /* #define SYSPROTO_CONTROL 2 */
|
||||
2, /* #define UTUN_OPT_IFNAME 2 */
|
||||
uintptr(unsafe.Pointer(&ifName)),
|
||||
@@ -235,7 +241,7 @@ func (tun *nativeTun) Name() (string, error) {
|
||||
}
|
||||
|
||||
func (tun *nativeTun) File() *os.File {
|
||||
return tun.fd
|
||||
return tun.tunFile
|
||||
}
|
||||
|
||||
func (tun *nativeTun) Events() chan TUNEvent {
|
||||
@@ -248,7 +254,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
return 0, err
|
||||
default:
|
||||
buff := buff[offset-4:]
|
||||
n, err := tun.fd.Read(buff[:])
|
||||
n, err := tun.tunFile.Read(buff[:])
|
||||
if n < 4 {
|
||||
return 0, err
|
||||
}
|
||||
@@ -259,7 +265,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
|
||||
for {
|
||||
n, err := tun.doRead(buff, offset)
|
||||
if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
|
||||
if err == nil || !rwcancel.RetryAfterError(err) {
|
||||
return n, err
|
||||
}
|
||||
if !tun.rwcancel.ReadyRead() {
|
||||
@@ -288,13 +294,13 @@ func (tun *nativeTun) Write(buff []byte, offset int) (int, error) {
|
||||
|
||||
// write
|
||||
|
||||
return tun.fd.Write(buff)
|
||||
return tun.tunFile.Write(buff)
|
||||
}
|
||||
|
||||
func (tun *nativeTun) Close() error {
|
||||
var err3 error
|
||||
err1 := tun.rwcancel.Cancel()
|
||||
err2 := tun.fd.Close()
|
||||
err2 := tun.tunFile.Close()
|
||||
if tun.routeSocket != -1 {
|
||||
unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR)
|
||||
err3 = unix.Close(tun.routeSocket)
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package tun
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"golang.org/x/net/ipv6"
|
||||
"golang.org/x/sys/unix"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -50,7 +51,8 @@ type ifstat struct {
|
||||
|
||||
type nativeTun struct {
|
||||
name string
|
||||
fd *os.File
|
||||
tunFile *os.File
|
||||
fd uintptr
|
||||
rwcancel *rwcancel.RWCancel
|
||||
events chan TUNEvent
|
||||
errors chan error
|
||||
@@ -67,8 +69,12 @@ func (tun *nativeTun) routineRouteListener(tunIfindex int) {
|
||||
|
||||
data := make([]byte, os.Getpagesize())
|
||||
for {
|
||||
retry:
|
||||
n, err := unix.Read(tun.routeSocket, data)
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
|
||||
goto retry
|
||||
}
|
||||
tun.errors <- err
|
||||
return
|
||||
}
|
||||
@@ -232,15 +238,15 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
||||
return nil, fmt.Errorf("interface %s already exists", name)
|
||||
}
|
||||
|
||||
tunfile, err := os.OpenFile("/dev/tun", unix.O_RDWR, 0)
|
||||
tunFile, err := os.OpenFile("/dev/tun", unix.O_RDWR, 0)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tunfd := tunfile.Fd()
|
||||
tunfd := tunFile.Fd()
|
||||
assignedName, err := tunName(tunfd)
|
||||
if err != nil {
|
||||
tunfile.Close()
|
||||
tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -257,19 +263,6 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
||||
return nil, fmt.Errorf("error %s", errno.Error())
|
||||
}
|
||||
|
||||
// Set TUN iface to broadcast mode. TUN inferfaces on freebsd come up in point to point by default
|
||||
ifmodemode := unix.IFF_BROADCAST
|
||||
_, _, errno = unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(tunfd),
|
||||
uintptr(_TUNSIFMODE),
|
||||
uintptr(unsafe.Pointer(&ifmodemode)),
|
||||
)
|
||||
|
||||
if errno != 0 {
|
||||
return nil, fmt.Errorf("error %s", errno.Error())
|
||||
}
|
||||
|
||||
// Rename tun interface
|
||||
|
||||
// Open control socket
|
||||
@@ -301,25 +294,26 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
||||
uintptr(unsafe.Pointer(&ifr)),
|
||||
)
|
||||
if errno != 0 {
|
||||
tunfile.Close()
|
||||
tunFile.Close()
|
||||
tunDestroy(name)
|
||||
return nil, fmt.Errorf("failed to rename %s to %s: %s", assignedName, name, errno.Error())
|
||||
}
|
||||
|
||||
return CreateTUNFromFile(tunfile, mtu)
|
||||
return CreateTUNFromFile(tunFile, mtu)
|
||||
}
|
||||
|
||||
func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
|
||||
tun := &nativeTun{
|
||||
fd: file,
|
||||
events: make(chan TUNEvent, 10),
|
||||
errors: make(chan error, 1),
|
||||
tunFile: file,
|
||||
fd: file.Fd(),
|
||||
events: make(chan TUNEvent, 10),
|
||||
errors: make(chan error, 1),
|
||||
}
|
||||
|
||||
name, err := tun.Name()
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -331,19 +325,19 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
return iface.Index, nil
|
||||
}()
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tun.rwcancel, err = rwcancel.NewRWCancel(int(file.Fd()))
|
||||
tun.rwcancel, err = rwcancel.NewRWCancel(int(tun.fd))
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -359,7 +353,7 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
}
|
||||
|
||||
func (tun *nativeTun) Name() (string, error) {
|
||||
name, err := tunName(tun.fd.Fd())
|
||||
name, err := tunName(tun.fd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -368,7 +362,7 @@ func (tun *nativeTun) Name() (string, error) {
|
||||
}
|
||||
|
||||
func (tun *nativeTun) File() *os.File {
|
||||
return tun.fd
|
||||
return tun.tunFile
|
||||
}
|
||||
|
||||
func (tun *nativeTun) Events() chan TUNEvent {
|
||||
@@ -381,7 +375,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
return 0, err
|
||||
default:
|
||||
buff := buff[offset-4:]
|
||||
n, err := tun.fd.Read(buff[:])
|
||||
n, err := tun.tunFile.Read(buff[:])
|
||||
if n < 4 {
|
||||
return 0, err
|
||||
}
|
||||
@@ -392,7 +386,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
|
||||
for {
|
||||
n, err := tun.doRead(buff, offset)
|
||||
if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
|
||||
if err == nil || !rwcancel.RetryAfterError(err) {
|
||||
return n, err
|
||||
}
|
||||
if !tun.rwcancel.ReadyRead() {
|
||||
@@ -421,13 +415,13 @@ func (tun *nativeTun) Write(buff []byte, offset int) (int, error) {
|
||||
|
||||
// write
|
||||
|
||||
return tun.fd.Write(buff)
|
||||
return tun.tunFile.Write(buff)
|
||||
}
|
||||
|
||||
func (tun *nativeTun) Close() error {
|
||||
var err4 error
|
||||
err1 := tun.rwcancel.Cancel()
|
||||
err2 := tun.fd.Close()
|
||||
err2 := tun.tunFile.Close()
|
||||
err3 := tunDestroy(tun.name)
|
||||
if tun.routeSocket != -1 {
|
||||
unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR)
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/* Copyright 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
|
||||
|
||||
package tun
|
||||
|
||||
/* Implementation of the TUN device interface for linux
|
||||
*/
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"golang.org/x/net/ipv6"
|
||||
"golang.org/x/sys/unix"
|
||||
"net"
|
||||
@@ -32,7 +29,8 @@ const (
|
||||
)
|
||||
|
||||
type nativeTun struct {
|
||||
fd *os.File
|
||||
tunFile *os.File
|
||||
fd uintptr
|
||||
fdCancel *rwcancel.RWCancel
|
||||
index int32 // if index
|
||||
name string // name of interface
|
||||
@@ -46,7 +44,7 @@ type nativeTun struct {
|
||||
}
|
||||
|
||||
func (tun *nativeTun) File() *os.File {
|
||||
return tun.fd
|
||||
return tun.tunFile
|
||||
}
|
||||
|
||||
func (tun *nativeTun) routineHackListener() {
|
||||
@@ -54,7 +52,7 @@ func (tun *nativeTun) routineHackListener() {
|
||||
/* This is needed for the detection to work across network namespaces
|
||||
* If you are reading this and know a better method, please get in touch.
|
||||
*/
|
||||
fd := int(tun.fd.Fd())
|
||||
fd := int(tun.fd)
|
||||
for {
|
||||
_, err := unix.Write(fd, nil)
|
||||
switch err {
|
||||
@@ -102,7 +100,7 @@ func (tun *nativeTun) routineNetlinkListener() {
|
||||
var msgn int
|
||||
for {
|
||||
msgn, _, _, _, err = unix.Recvmsg(tun.netlinkSock, msg[:], nil, 0)
|
||||
if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
|
||||
if err == nil || !rwcancel.RetryAfterError(err) {
|
||||
break
|
||||
}
|
||||
if !tun.netlinkCancel.ReadyRead() {
|
||||
@@ -269,7 +267,7 @@ func (tun *nativeTun) Name() (string, error) {
|
||||
var ifr [ifReqSize]byte
|
||||
_, _, errno := unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
tun.fd.Fd(),
|
||||
tun.fd,
|
||||
uintptr(unix.TUNGETIFF),
|
||||
uintptr(unsafe.Pointer(&ifr[0])),
|
||||
)
|
||||
@@ -310,7 +308,7 @@ func (tun *nativeTun) Write(buff []byte, offset int) (int, error) {
|
||||
|
||||
// write
|
||||
|
||||
return tun.fd.Write(buff)
|
||||
return tun.tunFile.Write(buff)
|
||||
}
|
||||
|
||||
func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
@@ -319,10 +317,10 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
return 0, err
|
||||
default:
|
||||
if tun.nopi {
|
||||
return tun.fd.Read(buff[offset:])
|
||||
return tun.tunFile.Read(buff[offset:])
|
||||
} else {
|
||||
buff := buff[offset-4:]
|
||||
n, err := tun.fd.Read(buff[:])
|
||||
n, err := tun.tunFile.Read(buff[:])
|
||||
if n < 4 {
|
||||
return 0, err
|
||||
}
|
||||
@@ -334,7 +332,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
|
||||
for {
|
||||
n, err := tun.doRead(buff, offset)
|
||||
if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
|
||||
if err == nil || !rwcancel.RetryAfterError(err) {
|
||||
return n, err
|
||||
}
|
||||
if !tun.fdCancel.ReadyRead() {
|
||||
@@ -357,7 +355,7 @@ func (tun *nativeTun) Close() error {
|
||||
} else if tun.events != nil {
|
||||
close(tun.events)
|
||||
}
|
||||
err2 := tun.fd.Close()
|
||||
err2 := tun.tunFile.Close()
|
||||
err3 := tun.fdCancel.Cancel()
|
||||
|
||||
if err1 != nil {
|
||||
@@ -370,21 +368,11 @@ func (tun *nativeTun) Close() error {
|
||||
}
|
||||
|
||||
func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
||||
|
||||
// open clone device
|
||||
|
||||
// HACK: we open it as a raw Fd first, so that f.nonblock=false
|
||||
// when we make it into a file object.
|
||||
nfd, err := unix.Open(cloneDevicePath, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = unix.SetNonblock(nfd, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fd := os.NewFile(uintptr(nfd), cloneDevicePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -416,23 +404,24 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
||||
|
||||
func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
tun := &nativeTun{
|
||||
fd: file,
|
||||
tunFile: file,
|
||||
fd: file.Fd(),
|
||||
events: make(chan TUNEvent, 5),
|
||||
errors: make(chan error, 5),
|
||||
statusListenersShutdown: make(chan struct{}),
|
||||
nopi: false,
|
||||
nopi: false,
|
||||
}
|
||||
var err error
|
||||
|
||||
tun.fdCancel, err = rwcancel.NewRWCancel(int(file.Fd()))
|
||||
tun.fdCancel, err = rwcancel.NewRWCancel(int(tun.fd))
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = tun.Name()
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -445,12 +434,12 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
|
||||
tun.netlinkSock, err = createNetlinkSocket()
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
tun.netlinkCancel, err = rwcancel.NewRWCancel(tun.netlinkSock)
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package tun
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"golang.org/x/net/ipv6"
|
||||
"golang.org/x/sys/unix"
|
||||
"io/ioutil"
|
||||
@@ -29,7 +29,7 @@ const _TUNSIFMODE = 0x8004745d
|
||||
|
||||
type nativeTun struct {
|
||||
name string
|
||||
fd *os.File
|
||||
tunFile *os.File
|
||||
rwcancel *rwcancel.RWCancel
|
||||
events chan TUNEvent
|
||||
errors chan error
|
||||
@@ -46,8 +46,12 @@ func (tun *nativeTun) routineRouteListener(tunIfindex int) {
|
||||
|
||||
data := make([]byte, os.Getpagesize())
|
||||
for {
|
||||
retry:
|
||||
n, err := unix.Read(tun.routeSocket, data)
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
|
||||
goto retry
|
||||
}
|
||||
tun.errors <- err
|
||||
return
|
||||
}
|
||||
@@ -90,9 +94,7 @@ func (tun *nativeTun) routineRouteListener(tunIfindex int) {
|
||||
|
||||
func errorIsEBUSY(err error) bool {
|
||||
if pe, ok := err.(*os.PathError); ok {
|
||||
if errno, ok := pe.Err.(syscall.Errno); ok && errno == syscall.EBUSY {
|
||||
return true
|
||||
}
|
||||
err = pe.Err
|
||||
}
|
||||
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EBUSY {
|
||||
return true
|
||||
@@ -127,19 +129,6 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set TUN iface to broadcast mode
|
||||
ifmodemode := unix.IFF_BROADCAST
|
||||
_, _, errno := unix.Syscall(
|
||||
unix.SYS_IOCTL,
|
||||
uintptr(tunfile.Fd()),
|
||||
uintptr(_TUNSIFMODE),
|
||||
uintptr(unsafe.Pointer(&ifmodemode)),
|
||||
)
|
||||
|
||||
if errno != 0 {
|
||||
return nil, fmt.Errorf("error %s", errno.Error())
|
||||
}
|
||||
|
||||
tun, err := CreateTUNFromFile(tunfile, mtu)
|
||||
|
||||
if err == nil && name == "tun" {
|
||||
@@ -155,14 +144,14 @@ func CreateTUN(name string, mtu int) (TUNDevice, error) {
|
||||
func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
|
||||
tun := &nativeTun{
|
||||
fd: file,
|
||||
events: make(chan TUNEvent, 10),
|
||||
errors: make(chan error, 1),
|
||||
tunFile: file,
|
||||
events: make(chan TUNEvent, 10),
|
||||
errors: make(chan error, 1),
|
||||
}
|
||||
|
||||
name, err := tun.Name()
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -174,19 +163,19 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
return iface.Index, nil
|
||||
}()
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tun.rwcancel, err = rwcancel.NewRWCancel(int(file.Fd()))
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tun.routeSocket, err = unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
|
||||
if err != nil {
|
||||
tun.fd.Close()
|
||||
tun.tunFile.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -202,7 +191,7 @@ func CreateTUNFromFile(file *os.File, mtu int) (TUNDevice, error) {
|
||||
}
|
||||
|
||||
func (tun *nativeTun) Name() (string, error) {
|
||||
gostat, err := tun.fd.Stat()
|
||||
gostat, err := tun.tunFile.Stat()
|
||||
if err != nil {
|
||||
tun.name = ""
|
||||
return "", err
|
||||
@@ -213,7 +202,7 @@ func (tun *nativeTun) Name() (string, error) {
|
||||
}
|
||||
|
||||
func (tun *nativeTun) File() *os.File {
|
||||
return tun.fd
|
||||
return tun.tunFile
|
||||
}
|
||||
|
||||
func (tun *nativeTun) Events() chan TUNEvent {
|
||||
@@ -226,7 +215,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
return 0, err
|
||||
default:
|
||||
buff := buff[offset-4:]
|
||||
n, err := tun.fd.Read(buff[:])
|
||||
n, err := tun.tunFile.Read(buff[:])
|
||||
if n < 4 {
|
||||
return 0, err
|
||||
}
|
||||
@@ -237,7 +226,7 @@ func (tun *nativeTun) doRead(buff []byte, offset int) (int, error) {
|
||||
func (tun *nativeTun) Read(buff []byte, offset int) (int, error) {
|
||||
for {
|
||||
n, err := tun.doRead(buff, offset)
|
||||
if err == nil || !rwcancel.ErrorIsEAGAIN(err) {
|
||||
if err == nil || !rwcancel.RetryAfterError(err) {
|
||||
return n, err
|
||||
}
|
||||
if !tun.rwcancel.ReadyRead() {
|
||||
@@ -266,13 +255,13 @@ func (tun *nativeTun) Write(buff []byte, offset int) (int, error) {
|
||||
|
||||
// write
|
||||
|
||||
return tun.fd.Write(buff)
|
||||
return tun.tunFile.Write(buff)
|
||||
}
|
||||
|
||||
func (tun *nativeTun) Close() error {
|
||||
var err3 error
|
||||
err1 := tun.rwcancel.Cancel()
|
||||
err2 := tun.fd.Close()
|
||||
err2 := tun.tunFile.Close()
|
||||
if tun.routeSocket != -1 {
|
||||
unix.Shutdown(tun.routeSocket, unix.SHUT_RDWR)
|
||||
err3 = unix.Close(tun.routeSocket)
|
||||
|
||||
13
uapi.go
13
uapi.go
@@ -1,7 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -75,6 +74,7 @@ func ipcGetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
|
||||
|
||||
send("public_key=" + peer.handshake.remoteStatic.ToHex())
|
||||
send("preshared_key=" + peer.handshake.presharedKey.ToHex())
|
||||
send("protocol_version=1")
|
||||
if peer.endpoint != nil {
|
||||
send("endpoint=" + peer.endpoint.DstToString())
|
||||
}
|
||||
@@ -307,7 +307,7 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
|
||||
|
||||
// update persistent keepalive interval
|
||||
|
||||
logDebug.Println(peer, "- UAPI: Updating persistent keepalive interva")
|
||||
logDebug.Println(peer, "- UAPI: Updating persistent keepalive interval")
|
||||
|
||||
secs, err := strconv.ParseUint(value, 10, 16)
|
||||
if err != nil {
|
||||
@@ -362,6 +362,13 @@ func ipcSetOperation(device *Device, socket *bufio.ReadWriter) *IPCError {
|
||||
ones, _ := network.Mask.Size()
|
||||
device.allowedips.Insert(network.IP, uint(ones), peer)
|
||||
|
||||
case "protocol_version":
|
||||
|
||||
if value != "1" {
|
||||
logError.Println("Invalid protocol version:", value)
|
||||
return &IPCError{Code: ipcErrorInvalid}
|
||||
}
|
||||
|
||||
default:
|
||||
logError.Println("Invalid UAPI peer key:", key)
|
||||
return &IPCError{Code: ipcErrorInvalid}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
@@ -18,12 +17,13 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var socketDirectory = "/var/run/wireguard"
|
||||
|
||||
const (
|
||||
ipcErrorIO = -int64(unix.EIO)
|
||||
ipcErrorProtocol = -int64(unix.EPROTO)
|
||||
ipcErrorInvalid = -int64(unix.EINVAL)
|
||||
ipcErrorPortInUse = -int64(unix.EADDRINUSE)
|
||||
socketDirectory = "/var/run/wireguard"
|
||||
socketName = "%s.sock"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Mathias N. Hall-Andersen <mathias@hall-andersen.dk>.
|
||||
* Copyright (C) 2017-2018 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.zx2c4.com/wireguard-go/rwcancel"
|
||||
"golang.org/x/sys/unix"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
var socketDirectory = "/var/run/wireguard"
|
||||
|
||||
const (
|
||||
ipcErrorIO = -int64(unix.EIO)
|
||||
ipcErrorProtocol = -int64(unix.EPROTO)
|
||||
ipcErrorInvalid = -int64(unix.EINVAL)
|
||||
ipcErrorPortInUse = -int64(unix.EADDRINUSE)
|
||||
socketDirectory = "/var/run/wireguard"
|
||||
socketName = "%s.sock"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
package main
|
||||
const WireGuardGoVersion = "0.0.20180524"
|
||||
const WireGuardGoVersion = "0.0.20181222"
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Copyright (C) 2016 Andreas Auernhammer. All Rights Reserved.
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package xchacha20poly1305
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"golang.org/x/crypto/chacha20poly1305"
|
||||
)
|
||||
|
||||
func hChaCha20(out *[32]byte, nonce []byte, key *[32]byte) {
|
||||
|
||||
v00 := uint32(0x61707865)
|
||||
v01 := uint32(0x3320646e)
|
||||
v02 := uint32(0x79622d32)
|
||||
v03 := uint32(0x6b206574)
|
||||
|
||||
v04 := binary.LittleEndian.Uint32(key[0:])
|
||||
v05 := binary.LittleEndian.Uint32(key[4:])
|
||||
v06 := binary.LittleEndian.Uint32(key[8:])
|
||||
v07 := binary.LittleEndian.Uint32(key[12:])
|
||||
v08 := binary.LittleEndian.Uint32(key[16:])
|
||||
v09 := binary.LittleEndian.Uint32(key[20:])
|
||||
v10 := binary.LittleEndian.Uint32(key[24:])
|
||||
v11 := binary.LittleEndian.Uint32(key[28:])
|
||||
v12 := binary.LittleEndian.Uint32(nonce[0:])
|
||||
v13 := binary.LittleEndian.Uint32(nonce[4:])
|
||||
v14 := binary.LittleEndian.Uint32(nonce[8:])
|
||||
v15 := binary.LittleEndian.Uint32(nonce[12:])
|
||||
|
||||
for i := 0; i < 20; i += 2 {
|
||||
v00 += v04
|
||||
v12 ^= v00
|
||||
v12 = (v12 << 16) | (v12 >> 16)
|
||||
v08 += v12
|
||||
v04 ^= v08
|
||||
v04 = (v04 << 12) | (v04 >> 20)
|
||||
v00 += v04
|
||||
v12 ^= v00
|
||||
v12 = (v12 << 8) | (v12 >> 24)
|
||||
v08 += v12
|
||||
v04 ^= v08
|
||||
v04 = (v04 << 7) | (v04 >> 25)
|
||||
v01 += v05
|
||||
v13 ^= v01
|
||||
v13 = (v13 << 16) | (v13 >> 16)
|
||||
v09 += v13
|
||||
v05 ^= v09
|
||||
v05 = (v05 << 12) | (v05 >> 20)
|
||||
v01 += v05
|
||||
v13 ^= v01
|
||||
v13 = (v13 << 8) | (v13 >> 24)
|
||||
v09 += v13
|
||||
v05 ^= v09
|
||||
v05 = (v05 << 7) | (v05 >> 25)
|
||||
v02 += v06
|
||||
v14 ^= v02
|
||||
v14 = (v14 << 16) | (v14 >> 16)
|
||||
v10 += v14
|
||||
v06 ^= v10
|
||||
v06 = (v06 << 12) | (v06 >> 20)
|
||||
v02 += v06
|
||||
v14 ^= v02
|
||||
v14 = (v14 << 8) | (v14 >> 24)
|
||||
v10 += v14
|
||||
v06 ^= v10
|
||||
v06 = (v06 << 7) | (v06 >> 25)
|
||||
v03 += v07
|
||||
v15 ^= v03
|
||||
v15 = (v15 << 16) | (v15 >> 16)
|
||||
v11 += v15
|
||||
v07 ^= v11
|
||||
v07 = (v07 << 12) | (v07 >> 20)
|
||||
v03 += v07
|
||||
v15 ^= v03
|
||||
v15 = (v15 << 8) | (v15 >> 24)
|
||||
v11 += v15
|
||||
v07 ^= v11
|
||||
v07 = (v07 << 7) | (v07 >> 25)
|
||||
v00 += v05
|
||||
v15 ^= v00
|
||||
v15 = (v15 << 16) | (v15 >> 16)
|
||||
v10 += v15
|
||||
v05 ^= v10
|
||||
v05 = (v05 << 12) | (v05 >> 20)
|
||||
v00 += v05
|
||||
v15 ^= v00
|
||||
v15 = (v15 << 8) | (v15 >> 24)
|
||||
v10 += v15
|
||||
v05 ^= v10
|
||||
v05 = (v05 << 7) | (v05 >> 25)
|
||||
v01 += v06
|
||||
v12 ^= v01
|
||||
v12 = (v12 << 16) | (v12 >> 16)
|
||||
v11 += v12
|
||||
v06 ^= v11
|
||||
v06 = (v06 << 12) | (v06 >> 20)
|
||||
v01 += v06
|
||||
v12 ^= v01
|
||||
v12 = (v12 << 8) | (v12 >> 24)
|
||||
v11 += v12
|
||||
v06 ^= v11
|
||||
v06 = (v06 << 7) | (v06 >> 25)
|
||||
v02 += v07
|
||||
v13 ^= v02
|
||||
v13 = (v13 << 16) | (v13 >> 16)
|
||||
v08 += v13
|
||||
v07 ^= v08
|
||||
v07 = (v07 << 12) | (v07 >> 20)
|
||||
v02 += v07
|
||||
v13 ^= v02
|
||||
v13 = (v13 << 8) | (v13 >> 24)
|
||||
v08 += v13
|
||||
v07 ^= v08
|
||||
v07 = (v07 << 7) | (v07 >> 25)
|
||||
v03 += v04
|
||||
v14 ^= v03
|
||||
v14 = (v14 << 16) | (v14 >> 16)
|
||||
v09 += v14
|
||||
v04 ^= v09
|
||||
v04 = (v04 << 12) | (v04 >> 20)
|
||||
v03 += v04
|
||||
v14 ^= v03
|
||||
v14 = (v14 << 8) | (v14 >> 24)
|
||||
v09 += v14
|
||||
v04 ^= v09
|
||||
v04 = (v04 << 7) | (v04 >> 25)
|
||||
}
|
||||
|
||||
binary.LittleEndian.PutUint32(out[0:], v00)
|
||||
binary.LittleEndian.PutUint32(out[4:], v01)
|
||||
binary.LittleEndian.PutUint32(out[8:], v02)
|
||||
binary.LittleEndian.PutUint32(out[12:], v03)
|
||||
binary.LittleEndian.PutUint32(out[16:], v12)
|
||||
binary.LittleEndian.PutUint32(out[20:], v13)
|
||||
binary.LittleEndian.PutUint32(out[24:], v14)
|
||||
binary.LittleEndian.PutUint32(out[28:], v15)
|
||||
}
|
||||
|
||||
func Encrypt(
|
||||
dst []byte,
|
||||
nonceFull *[24]byte,
|
||||
plaintext []byte,
|
||||
additionalData []byte,
|
||||
key *[chacha20poly1305.KeySize]byte,
|
||||
) []byte {
|
||||
var nonce [chacha20poly1305.NonceSize]byte
|
||||
var derivedKey [chacha20poly1305.KeySize]byte
|
||||
hChaCha20(&derivedKey, nonceFull[:16], key)
|
||||
aead, _ := chacha20poly1305.New(derivedKey[:])
|
||||
copy(nonce[4:], nonceFull[16:])
|
||||
return aead.Seal(dst, nonce[:], plaintext, additionalData)
|
||||
}
|
||||
|
||||
func Decrypt(
|
||||
dst []byte,
|
||||
nonceFull *[24]byte,
|
||||
plaintext []byte,
|
||||
additionalData []byte,
|
||||
key *[chacha20poly1305.KeySize]byte,
|
||||
) ([]byte, error) {
|
||||
var nonce [chacha20poly1305.NonceSize]byte
|
||||
var derivedKey [chacha20poly1305.KeySize]byte
|
||||
hChaCha20(&derivedKey, nonceFull[:16], key)
|
||||
aead, _ := chacha20poly1305.New(derivedKey[:])
|
||||
copy(nonce[4:], nonceFull[16:])
|
||||
return aead.Open(dst, nonce[:], plaintext, additionalData)
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2017-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package xchacha20poly1305
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type XChaCha20Test struct {
|
||||
Nonce string
|
||||
Key string
|
||||
PT string
|
||||
CT string
|
||||
}
|
||||
|
||||
func TestXChaCha20(t *testing.T) {
|
||||
|
||||
tests := []XChaCha20Test{
|
||||
{
|
||||
Nonce: "000000000000000000000000000000000000000000000000",
|
||||
Key: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
PT: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
CT: "789e9689e5208d7fd9e1f3c5b5341f48ef18a13e418998addadd97a3693a987f8e82ecd5c1433bfed1af49750c0f1ff29c4174a05b119aa3a9e8333812e0c0feb1299c5949d895ee01dbf50f8395dd84",
|
||||
},
|
||||
{
|
||||
Nonce: "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f",
|
||||
Key: "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f",
|
||||
PT: "0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f",
|
||||
CT: "e1a046aa7f71e2af8b80b6408b2fd8d3a350278cde79c94d9efaa475e1339b3dd490127b",
|
||||
},
|
||||
{
|
||||
Nonce: "d9a8213e8a697508805c2c171ad54487ead9e3e02d82d5bc",
|
||||
Key: "979196dbd78526f2f584f7534db3f5824d8ccfa858ca7e09bdd3656ecd36033c",
|
||||
PT: "43cc6d624e451bbed952c3e071dc6c03392ce11eb14316a94b2fdc98b22fedea",
|
||||
CT: "53c1e8bef2dbb8f2505ec010a7afe21d5a8e6dd8f987e4ea1a2ed5dfbc844ea400db34496fd2153526c6e87c36694200",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
nonce, err := hex.DecodeString(test.Nonce)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
key, err := hex.DecodeString(test.Key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pt, err := hex.DecodeString(test.PT)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func() {
|
||||
var nonceArray [24]byte
|
||||
var keyArray [32]byte
|
||||
copy(nonceArray[:], nonce)
|
||||
copy(keyArray[:], key)
|
||||
|
||||
// test encryption
|
||||
|
||||
ct := Encrypt(
|
||||
nil,
|
||||
&nonceArray,
|
||||
pt,
|
||||
nil,
|
||||
&keyArray,
|
||||
)
|
||||
ctHex := hex.EncodeToString(ct)
|
||||
if ctHex != test.CT {
|
||||
t.Fatal("encryption failed, expected:", test.CT, "got", ctHex)
|
||||
}
|
||||
|
||||
// test decryption
|
||||
|
||||
ptp, err := Decrypt(
|
||||
nil,
|
||||
&nonceArray,
|
||||
ct,
|
||||
nil,
|
||||
&keyArray,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ptHex := hex.EncodeToString(ptp)
|
||||
if ptHex != test.PT {
|
||||
t.Fatal("decryption failed, expected:", test.PT, "got", ptHex)
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user