summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls <emils@mullvad.net>2020-01-23 14:12:27 +0000
committerEmīls <emils@mullvad.net>2020-01-23 14:12:27 +0000
commitf090b37b103964969d494bf7e2cae57cff0d16ea (patch)
treef429827f886d3d12323a259ed95abd25db62f1a5
parent8f9ac2d313f27d9cf9a3a9433de78619d2de44f1 (diff)
parent05478afe9a4cf4ce732504820cd41ca583ad0676 (diff)
downloadmullvadvpn-f090b37b103964969d494bf7e2cae57cff0d16ea.tar.xz
mullvadvpn-f090b37b103964969d494bf7e2cae57cff0d16ea.zip
Merge branch 'add-wireguard-go'
-rw-r--r--.editorconfig4
-rw-r--r--.gitattributes3
-rw-r--r--.gitignore1
-rw-r--r--.travis.yml9
-rw-r--r--CHANGELOG.md1
-rw-r--r--Dockerfile20
-rw-r--r--README.md7
-rwxr-xr-xbuild-apk.sh2
-rwxr-xr-xbuild.sh5
-rwxr-xr-xci/ci-rust-script.sh4
m---------dist-assets/binaries0
-rw-r--r--gui/tasks/distribution.js2
-rw-r--r--talpid-core/build.rs20
-rwxr-xr-xwireguard/build-wireguard-go.sh108
-rw-r--r--wireguard/wireguard-go-windows/go.mod21
-rw-r--r--wireguard/wireguard-go-windows/go.sum166
-rw-r--r--wireguard/wireguard-go-windows/interfacewatcher.go123
-rw-r--r--wireguard/wireguard-go-windows/libwg.go290
-rw-r--r--wireguard/wireguard-go/Android.mk55
-rwxr-xr-xwireguard/wireguard-go/build-android.sh63
-rw-r--r--wireguard/wireguard-go/go.mod8
-rw-r--r--wireguard/wireguard-go/go.sum37
-rw-r--r--wireguard/wireguard-go/goruntime-boottime-over-monotonic.diff161
-rw-r--r--wireguard/wireguard-go/libwg.go239
-rw-r--r--wireguard/wireguard-go/libwg_android.go114
25 files changed, 1453 insertions, 10 deletions
diff --git a/.editorconfig b/.editorconfig
index 353c925e45..839ca55766 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -16,3 +16,7 @@ indent_size = 4
[*.{js,json,css,html}]
indent_style = space
indent_size = 2
+
+[*.{go}]
+end_of_line = lf
+indent_style = tab
diff --git a/.gitattributes b/.gitattributes
index c63c583436..d3f9d27b27 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -6,3 +6,6 @@
# Use LF for Rust because rustfmt works best like that
*.rs text eol=lf
+
+wireguard/wireguard-go-windows/go.mod text eol=lf
+wireguard/wireguard-go-windows/go.sum text eol=lf
diff --git a/.gitignore b/.gitignore
index 7730d8900a..af08672837 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
/gui/scripts/ne_50m_admin_1_states_provinces_lines/
/gui/scripts/ne_50m_populated_places/
/gui/scripts/out/
+/build/
/dist
.DS_Store
*.log
diff --git a/.travis.yml b/.travis.yml
index 37cdddaf58..a1fd0a9ee6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -69,6 +69,7 @@ matrix:
- source env.sh aarch64-linux-android
- env
script:
+ - ./wireguard/build-wireguard-go.sh --android
- cargo build --target aarch64-linux-android --verbose --package mullvad-jni
- cd android
- ./gradlew --console plain assembleDebug
@@ -82,6 +83,10 @@ matrix:
os: osx
before_script:
- env
+ # installing Go
+ - curl -s https://dl.google.com/go/go1.13.6.darwin-amd64.pkg --output go-installer.pkg
+ - sudo installer -pkg ./go-installer.pkg -target /
+ - export PATH="/usr/local/go/bin:$PATH"
script:
- ./ci/ci-rust-script.sh stable
@@ -129,6 +134,10 @@ matrix:
- echo "34fa4c9bb790f310c908ff59071949289dc3ed503bcb44723c2e0b360c51ebab vs_BuildTools.exe" | sha256sum -c
- ./vs_BuildTools.exe --wait -q --norestart --add Microsoft.VisualStudio.Workload.VCTools\;includeRecommended --add Microsoft.Component.MSBuild --add Microsoft.VisualStudio.Component.VC.ATL
- git submodule update --init
+ # Installing Go
+ - curl -s https://dl.google.com/go/go1.13.6.windows-amd64.msi --output go-installer.msi
+ - cmd.exe '/c msiexec /i go-installer.msi /quiet /qn'
+ - export PATH="/c/Go/bin/:$PATH"
script: &rust_windows_script
- ./ci/ci-rust-script.sh $RUST_VERSION
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 947d9b4e05..7c843d7526 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@ Line wrap the file at 100 chars. Th
- Increase OpenVPN ping timeout from 20 to 25 seconds. Might make working tunnels disconnect
a bit less frequently.
- Increase WireGuard ping timeout from 7 to 15 seconds.
+- Updated `wireguard-go` to `v0.0.20200121`
#### Linux
- DNS management with static `/etc/resolv.conf` will now work even when no
diff --git a/Dockerfile b/Dockerfile
index c195a6c73b..12409f8297 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,10 +8,28 @@ RUN apt install build-essential \
gcc \
libdbus-1-dev \
rpm \
- go2 \
binutils \
curl \
p7zip-full \
git -y
+
+
+# Install golang
+ENV GOLANG_VERSION 1.13.5
+# Found on https://golang.org/dl/
+ENV GOLANG_HASH 512103d7ad296467814a6e3f635631bd35574cab3369a97a323c9a585ccaa569
+RUN curl -Lo go.tgz https://golang.org/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz && \
+ echo $(sha256sum go.tgz) && \
+ echo "${GOLANG_HASH} go.tgz" | sha256sum -c - && \
+ tar -C /usr/local -xzf go.tgz && \
+ rm go.tgz && \
+ rm -rf /var/lib/apt/lists/* && \
+ export PATH="/usr/local/go/bin:$PATH" && \
+ go version
+
+ENV GOPATH /go
+ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
+RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
+
RUN mkdir /mvd
CMD tail -f /dev/null
diff --git a/README.md b/README.md
index f3600e39b5..6ccc942b37 100644
--- a/README.md
+++ b/README.md
@@ -234,6 +234,13 @@ storePassword = keystore-password
#### Windows
Download the Node.js installer from the official website.
+
+1. Install Go (ideally version `1.13.6`) by following the [official
+ instructions](https://golang.org/doc/install). Newer versions of Go may be used. Earlier
+ versions may be used, but versions older than `1.12` are known to not work, newer versions may
+ too.
+
+
## Building and packaging the app
The simplest way to build the entire app and generate an installer is to just run the build script.
diff --git a/build-apk.sh b/build-apk.sh
index 47c42060f7..25a88a804f 100755
--- a/build-apk.sh
+++ b/build-apk.sh
@@ -5,6 +5,8 @@ set -eu
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"
+./wireguard/build-wireguard-go.sh --android
+
PRODUCT_VERSION="$(node -p "require('$SCRIPT_DIR/gui/package.json').version" | sed -Ee 's/\.0//g')"
if [[ "${1:-""}" == "--dev-build" ]]; then
diff --git a/build.sh b/build.sh
index 853cb96895..993b39933b 100755
--- a/build.sh
+++ b/build.sh
@@ -128,6 +128,11 @@ if [[ "$(uname -s)" == "MINGW"* ]]; then
CPP_BUILD_MODES="Release" ./build_windows_modules.sh $@
fi
+################################################################################
+# Compile wireguard-go
+################################################################################
+./wireguard/build-wireguard-go.sh
+
echo "Building Rust code in release mode using $RUSTC_VERSION..."
MULLVAD_ADD_MANIFEST="1" cargo +stable build $CARGO_ARGS --release
diff --git a/ci/ci-rust-script.sh b/ci/ci-rust-script.sh
index 7fc7c26eab..90863cc90d 100755
--- a/ci/ci-rust-script.sh
+++ b/ci/ci-rust-script.sh
@@ -32,6 +32,10 @@ case "$(uname -s)" in
;;
esac
+# Build wireguard-go
+# On Windows, it relies on having msbuild.exe in your path.
+./wireguard/build-wireguard-go.sh
+
# FIXME: Becaues of our old jsonrpc dependency our Rust code won't build
# on latest nightly.
if [ "${RUST_TOOLCHAIN_CHANNEL}" != "nightly" ]; then
diff --git a/dist-assets/binaries b/dist-assets/binaries
-Subproject 2cc905c88137fdae1ee416ef2062fa8f4b92883
+Subproject 90a76633747020f346f07cf7b92e6470941ad00
diff --git a/gui/tasks/distribution.js b/gui/tasks/distribution.js
index 7ae4dc3296..87a4bf3af4 100644
--- a/gui/tasks/distribution.js
+++ b/gui/tasks/distribution.js
@@ -93,7 +93,7 @@ const config = {
{ from: root('windows/winutil/bin/x64-Release/winutil.dll'), to: '.' },
{ from: distAssets('binaries/x86_64-pc-windows-msvc/openvpn.exe'), to: '.' },
{ from: distAssets('binaries/x86_64-pc-windows-msvc/sslocal.exe'), to: '.' },
- { from: distAssets('binaries/x86_64-pc-windows-msvc/wireguard/libwg.dll'), to: '.' },
+ { from: root('build/lib/x86_64-pc-windows-msvc/libwg.dll'), to: '.' },
],
},
diff --git a/talpid-core/build.rs b/talpid-core/build.rs
index 5a63a1f064..97614e8945 100644
--- a/talpid-core/build.rs
+++ b/talpid-core/build.rs
@@ -53,7 +53,7 @@ fn main() {
declare_library(WINFW_DIR_VAR, WINFW_BUILD_DIR, "winfw");
declare_library(WINDNS_DIR_VAR, WINDNS_BUILD_DIR, "windns");
declare_library(WINNET_DIR_VAR, WINNET_BUILD_DIR, "winnet");
- let lib_dir = manifest_dir().join("../dist-assets/binaries/x86_64-pc-windows-msvc/wireguard");
+ let lib_dir = manifest_dir().join("../build/lib/x86_64-pc-windows-msvc");
println!("cargo:rustc-link-search={}", &lib_dir.display());
println!("cargo:rustc-link-lib=dylib=libwg");
}
@@ -61,7 +61,9 @@ fn main() {
#[cfg(not(windows))]
fn main() {
let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS not set");
- let target_triplet = env::var("TARGET").expect("TARGET is not set");
+
+ declare_libs_dir("../dist-assets/binaries");
+ declare_libs_dir("../build/lib");
let link_type = match target_os.as_str() {
"android" => "",
@@ -69,12 +71,6 @@ fn main() {
_ => panic!("Unsupported platform: {}", target_os),
};
- let lib_dir = manifest_dir()
- .join("../dist-assets/binaries")
- .join(target_triplet);
-
- println!("cargo:rerun-if-changed={}", lib_dir.display());
- println!("cargo:rustc-link-search={}", lib_dir.display());
println!("cargo:rustc-link-lib{}=wg", link_type);
}
@@ -83,3 +79,11 @@ fn manifest_dir() -> PathBuf {
.map(PathBuf::from)
.expect("CARGO_MANIFEST_DIR env var not set")
}
+
+#[cfg(not(windows))]
+fn declare_libs_dir(base: &str) {
+ let target_triplet = env::var("TARGET").expect("TARGET is not set");
+ let lib_dir = manifest_dir().join(base).join(target_triplet);
+ println!("cargo:rerun-if-changed={}", lib_dir.display());
+ println!("cargo:rustc-link-search={}", lib_dir.display());
+}
diff --git a/wireguard/build-wireguard-go.sh b/wireguard/build-wireguard-go.sh
new file mode 100755
index 0000000000..a4ff7feb49
--- /dev/null
+++ b/wireguard/build-wireguard-go.sh
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+
+# This script is used to build wireguard-go libraries for all the platforms.
+
+set -eu
+
+function is_android_build {
+ for arg in "$@"
+ do
+ case "$arg" in
+ "--android")
+ return 0
+ esac
+ done
+ return 1
+}
+
+
+function win_deduce_lib_executable_path {
+ msbuild_path="$(which msbuild.exe)"
+ msbuild_dir=$(dirname "$msbuild_path")
+ find "$msbuild_dir/../../../../" -name "lib.exe" | \
+ grep -i "hostx64/x64" | \
+ head -n1
+}
+
+function win_gather_export_symbols {
+ grep -Eo "\/\/export \w+" libwg.go | cut -d' ' -f2
+}
+
+function win_create_lib_file {
+ echo "LIBRARY libwg" > exports.def
+ echo "EXPORTS" >> exports.def
+
+ for symbol in $(win_gather_export_symbols); do
+ printf "\t%s\n" "$symbol" >> exports.def
+ done
+
+ lib_path="$(win_deduce_lib_executable_path)"
+ "$lib_path" \
+ "/def:exports.def" \
+ "/out:libwg.lib" \
+ "/machine:X64"
+
+}
+
+function build_windows {
+ echo "Building wireguard-go for Windows"
+ pushd wireguard-go-windows
+ go build -v -o libwg.dll -buildmode c-shared
+ win_create_lib_file
+
+ target_dir=../../build/lib/x86_64-pc-windows-msvc/
+ mkdir -p $target_dir
+ cp libwg.dll libwg.lib $target_dir
+ popd
+}
+
+function unix_target_triple {
+ local platform="$(uname -s)"
+ if [[ ("${platform}" == "Linux") ]]; then
+ echo "x86_64-unknown-linux-gnu"
+ elif [[ ("${platform}" == "Darwin") ]]; then
+ echo "x86_64-apple-darwin"
+ else
+ echo "Can't deduce target dir for $platform"
+ return 1
+ fi
+}
+
+
+function build_unix {
+ echo "Building wireguard-go for $1"
+ pushd wireguard-go
+ go build -v -o libwg.a -buildmode c-archive
+ target_triple_dir="../../build/lib/$(unix_target_triple)"
+ mkdir -p $target_triple_dir
+ cp libwg.a $target_triple_dir
+ popd
+}
+
+function build_android {
+ echo "Building for android"
+ local docker_image_hash="d73fdea1108cd75d7eb09f8894fe6892dc502a2d62c39b4f75072e777398f477"
+
+ docker run --rm \
+ -v "$(pwd)/../":/workspace \
+ --entrypoint "/workspace/wireguard/wireguard-go/build-android.sh" \
+ mullvadvpn/mullvad-android-app-build@sha256:$docker_image_hash
+}
+
+function build_wireguard_go {
+ if is_android_build $@; then
+ build_android
+ return
+ fi
+
+ local platform="$(uname -s)";
+ case "$platform" in
+ Linux*|Darwin*) build_unix $platform;;
+ MINGW*|MSYS_NT*) build_windows;;
+ esac
+}
+
+# Ensure we are in the correct directory for the execution of this script
+script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $script_dir
+build_wireguard_go $@
diff --git a/wireguard/wireguard-go-windows/go.mod b/wireguard/wireguard-go-windows/go.mod
new file mode 100644
index 0000000000..35b78ec484
--- /dev/null
+++ b/wireguard/wireguard-go-windows/go.mod
@@ -0,0 +1,21 @@
+module github.com/mullvad/mullvadvpn-app/wireguard-go-windows
+
+go 1.12
+
+require (
+ github.com/Microsoft/go-winio v0.4.14 // indirect
+ github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
+ github.com/sirupsen/logrus v1.4.2 // indirect
+ github.com/stretchr/objx v0.2.0 // indirect
+ github.com/stretchr/testify v1.4.0 // indirect
+ golang.org/x/crypto v0.0.0-20200108215511-5d647ca15757 // indirect
+ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
+ golang.org/x/sys v0.0.0-20200107162124-548cf772de50
+ golang.org/x/tools v0.0.0-20200108203644-89082a384178 // indirect
+ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
+ golang.zx2c4.com/wireguard v0.0.20200121
+ golang.zx2c4.com/wireguard/windows v0.0.38
+ gopkg.in/Knetic/govaluate.v3 v3.0.0 // indirect
+ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
+ gopkg.in/yaml.v2 v2.2.7 // indirect
+)
diff --git a/wireguard/wireguard-go-windows/go.sum b/wireguard/wireguard-go-windows/go.sum
new file mode 100644
index 0000000000..9ed4c430b6
--- /dev/null
+++ b/wireguard/wireguard-go-windows/go.sum
@@ -0,0 +1,166 @@
+github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
+github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
+github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/lxn/walk v0.0.0-20190923074432-2011aca68435/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
+github.com/lxn/walk v0.0.0-20191024083542-9936f81d38c5/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
+github.com/lxn/walk v0.0.0-20191024161928-0ee7d2cded97 h1:3zBUhgnxeLyaImKEtPfKWipiHyI5zYp/V2NN967zPFo=
+github.com/lxn/walk v0.0.0-20191024161928-0ee7d2cded97/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
+github.com/lxn/walk v0.0.0-20191128110447-55ccb3a9f5c1/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
+github.com/lxn/win v0.0.0-20190919090605-24c5960b03d8/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA=
+github.com/lxn/win v0.0.0-20191024092953-c0107e6cbbfb/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA=
+github.com/lxn/win v0.0.0-20191024121223-cc00c7492fe1 h1:h0wbuSK8xUNmMwDdCxZx2OLdkVck6Bb31zj4CxCN5I4=
+github.com/lxn/win v0.0.0-20191024121223-cc00c7492fe1/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA=
+github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734 h1:p/H982KKEjUnLJkM3tt/LemDnOc1GiZL5FCVlORJ5zo=
+golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
+golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
+golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
+golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
+golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
+golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIoF2s4qxv0xSSS0BVZUE/ss=
+golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba h1:9bFeDpN3gTqNanMVqNcoR/pJQuP5uroC3t1D7eXozTE=
+golang.org/x/crypto v0.0.0-20191119213627-4f8c1d86b1ba/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200108215511-5d647ca15757 h1:pJ9H8lzdBh301qPX4VpwJ8TRpLt1IhNK1PxVOICyP54=
+golang.org/x/crypto v0.0.0-20200108215511-5d647ca15757/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190502183928-7f726cade0ab h1:9RfW3ktsOZxgo9YNbBAjq1FWzc/igwEcUzZz8IXgSbk=
+golang.org/x/net v0.0.0-20190502183928-7f726cade0ab/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190909003024-a7b16738d86b h1:XfVGCX+0T4WOStkaOsJRllbsiImhB2jgVBGc9L0lPGc=
+golang.org/x/net v0.0.0-20190909003024-a7b16738d86b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2 h1:4dVFTC832rPn4pomLSz1vA+are2+dU19w1H8OngV7nc=
+golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190916140828-c8589233b77d h1:mCMDWKhNO37A7GAhOpHPbIw1cjd0V86kX1/WA9c7FZ8=
+golang.org/x/net v0.0.0-20190916140828-c8589233b77d/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
+golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191021144547-ec77196f6094 h1:5O4U9trLjNpuhpynaDsqwCk+Tw6seqJz1EbqbnzHrc8=
+golang.org/x/net v0.0.0-20191021144547-ec77196f6094/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9 h1:DPz9iiH3YoKiKhX/ijjoZvT0VFwK2c6CWYWQ7Zyr8TU=
+golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914 h1:MlY3mEfbnWGmUi4rtHOtNnnnN4UJRGSyLPx+DXA5Sq4=
+golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2 h1:T5DasATyLQfmbTpfEXx/IOL9vfjzW6up+ZDkmHvIf2s=
+golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190618155005-516e3c20635f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190830023255-19e00faab6ad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190830142957-1e83adbbebd0 h1:7z820YPX9pxWR59qM7BE5+fglp4D/mKqAwCvGt11b+8=
+golang.org/x/sys v0.0.0-20190830142957-1e83adbbebd0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5 h1:SW/0nsKCUaozCUtZTakri5laocGx/5bkDSSLrFUsa5s=
+golang.org/x/sys v0.0.0-20190911201528-7ad0cfa0b7b5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7 h1:wYqz/tQaWUgGKyx+B/rssSE6wkIKdY5Ee6ryOmzarIg=
+golang.org/x/sys v0.0.0-20190913121621-c3b328c6e5a7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190924062700-2aa67d56cdd7 h1:9Vs0Vm0p/0tnWLBWn79aav6fpcxKjBZbd21Lhxzit4k=
+golang.org/x/sys v0.0.0-20190924062700-2aa67d56cdd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191024073052-e66fe6eb8e0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae h1:QoJmnb9uyPCrH8GIg9uRLn4Ta45yhcQtpymCd0AavO8=
+golang.org/x/sys v0.0.0-20191025021431-6c3a3bfe00ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191104094858-e8c54fb511f6 h1:ZJUmhYTp8GbGC0ViZRc2U+MIYQ8xx9MscsdXnclfIhw=
+golang.org/x/sys v0.0.0-20191104094858-e8c54fb511f6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200107162124-548cf772de50 h1:YvQ10rzcqWXLlJZ3XCUoO25savxmscf4+SC+ZqiCHhA=
+golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190822000311-fc82fb2afd64/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190823093517-aa644d2adf2a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190830223141-573d9926052a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911230505-6bfd74cf029c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190917144518-6c790d64586a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190924052046-3ac2a5bbd98a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191025023517-2077df36852e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.zx2c4.com/wireguard v0.0.20190517 h1:FQ539AeNmsDek0BvWlaQId62Qe1bJsTwY/hse7SPRus=
+golang.zx2c4.com/wireguard v0.0.20190517/go.mod h1:+Ks6M+8QvlG7Er8n35VNd/G5QnUQsypmpxIdPiAg48A=
+golang.zx2c4.com/wireguard v0.0.20190805 h1:qPzediAzPEswzRxx2GzzPzNqnwqBZUUxEKTnC+7vjng=
+golang.zx2c4.com/wireguard v0.0.20190805/go.mod h1:NFs2tkQT6xXo9kzqGJxObM2MzHhraJi7ZQUmwIqT+tE=
+golang.zx2c4.com/wireguard v0.0.20190908 h1:SUoXDdwSMtomLdvke+zz83/u9tNvl4hHmcTIWp38tow=
+golang.zx2c4.com/wireguard v0.0.20190908/go.mod h1:LhfXh5z6bLC2lW2ve6BzYZFwnnsXK3OQjySR0Yh2dO8=
+golang.zx2c4.com/wireguard v0.0.20190909-0.20190917013833-70f6c42556af h1:0Z1CA9P1u7JLb7ixHREM/XH8wFkM+9t9LrQDeoJkBik=
+golang.zx2c4.com/wireguard v0.0.20190909-0.20190917013833-70f6c42556af/go.mod h1:LhfXh5z6bLC2lW2ve6BzYZFwnnsXK3OQjySR0Yh2dO8=
+golang.zx2c4.com/wireguard v0.0.20190909-0.20190917053916-01f8ef4e84a0 h1:BVNh+sWik8qlOqQ8Ef64s8bYxv7ka+MkPA7AT+Gk0M8=
+golang.zx2c4.com/wireguard v0.0.20190909-0.20190917053916-01f8ef4e84a0/go.mod h1:LhfXh5z6bLC2lW2ve6BzYZFwnnsXK3OQjySR0Yh2dO8=
+golang.zx2c4.com/wireguard v0.0.20190909-0.20190922100135-5774e6be91d3 h1:kpi3yed7t47yI5s7u8Z3AXqC0FfMxrCfwIsITux2VrA=
+golang.zx2c4.com/wireguard v0.0.20190909-0.20190922100135-5774e6be91d3/go.mod h1:kknHs/HWB+cZKvHHzBldTe9HL6GEOpFswULW8LBwL4I=
+golang.zx2c4.com/wireguard v0.0.20191012/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
+golang.zx2c4.com/wireguard v0.0.20191013-0.20191022095125-f7d0edd2ecf5 h1:tijV0YMbg6JbCA9TNaNVjAK2+6KefpNwF4coc6UkNkQ=
+golang.zx2c4.com/wireguard v0.0.20191013-0.20191022095125-f7d0edd2ecf5/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
+golang.zx2c4.com/wireguard v0.0.20191013-0.20191121140156-3d0bb4c07f85 h1:5N1BJDaQnQAfcqY7MT1QoAAkPOj4gGs4/MC3TsxI12E=
+golang.zx2c4.com/wireguard v0.0.20191013-0.20191121140156-3d0bb4c07f85/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
+golang.zx2c4.com/wireguard v0.0.20191013-0.20200107164045-4fa2ea6a2dab h1:HVdRO4CGjul3Pj1BD1K5uThcFtrwXEF+F5qI+//V0mw=
+golang.zx2c4.com/wireguard v0.0.20191013-0.20200107164045-4fa2ea6a2dab/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
+golang.zx2c4.com/wireguard v0.0.20200121 h1:vcswa5Q6f+sylDfjqyrVNNrjsFUUbPsgAQTBCAg/Qf8=
+golang.zx2c4.com/wireguard v0.0.20200121/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
+golang.zx2c4.com/wireguard/windows v0.0.27 h1:mWNJM+ljcCkHY6tl/yrgaYnzl8GDXkBw/lwVAULZPUQ=
+golang.zx2c4.com/wireguard/windows v0.0.27/go.mod h1:52MuSjwe0l0Hiv3wyu3Fq2dRkFXwbooym2zfmItvPGY=
+golang.zx2c4.com/wireguard/windows v0.0.34 h1:u/r6uDRXVLZMISJoIMsOvih5hVwR3CIW5c8ZzeNMk6U=
+golang.zx2c4.com/wireguard/windows v0.0.34/go.mod h1:dOEC5Ypgn5LE/VR+Fhcs2nDz3BzMYquODzA3JjurnnE=
+golang.zx2c4.com/wireguard/windows v0.0.35 h1:egyV5IRbpKr78b+9gkB8AMQ32TtCo0NO//rfh10OSDg=
+golang.zx2c4.com/wireguard/windows v0.0.35/go.mod h1:A3MmRXpatlao+Zty3Zxe2nqZ/sQCGYvnMVZ4z7TQY2w=
+golang.zx2c4.com/wireguard/windows v0.0.38 h1:RIXfYUYDCBk5+tsxrnNBRXxIvgnXJc544MrDMFFXj4I=
+golang.zx2c4.com/wireguard/windows v0.0.38/go.mod h1:bVbqKzpu4jLrEA2nVNn/WdWyyXGZARZNqkoGHd61DuM=
+gopkg.in/Knetic/govaluate.v3 v3.0.0 h1:18mUyIt4ZlRlFZAAfVetz4/rzlJs9yhN+U02F4u1AOc=
+gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/wireguard/wireguard-go-windows/interfacewatcher.go b/wireguard/wireguard-go-windows/interfacewatcher.go
new file mode 100644
index 0000000000..d1a2a008bf
--- /dev/null
+++ b/wireguard/wireguard-go-windows/interfacewatcher.go
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019 Amagicom AB. All Rights Reserved.
+ */
+
+package main
+
+import (
+ "sync"
+ "time"
+
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+type interfaceWatcherEvent struct {
+ luid winipcfg.LUID
+ family winipcfg.AddressFamily
+}
+
+type interfaceWatcher struct {
+ ready chan bool
+ processingMutex sync.Mutex
+ interfaceChangeCallback *winipcfg.InterfaceChangeCallback
+ seenEvents []interfaceWatcherEvent
+ wantedEvents []interfaceWatcherEvent
+ expired bool
+}
+
+func watchInterfaces() (*interfaceWatcher, error) {
+ iw := &interfaceWatcher{
+ ready: make(chan bool, 1),
+ expired: false,
+ }
+ var err error
+ iw.interfaceChangeCallback, err = winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) {
+ if notificationType != winipcfg.MibAddInstance {
+ return
+ }
+
+ iw.processingMutex.Lock()
+ defer iw.processingMutex.Unlock()
+
+ if iw.expired {
+ return
+ }
+
+ iw.seenEvents = append(iw.seenEvents, interfaceWatcherEvent{iface.InterfaceLUID, iface.Family})
+
+ if len(iw.wantedEvents) != 0 {
+ iw.evaluateEvents()
+ }
+ })
+ if err != nil {
+ return nil, err
+ }
+ return iw, nil
+}
+
+func (iw *interfaceWatcher) evaluateEvents() {
+ matched := 0
+
+ // This is n*n, but typically very few items in both slices :-)
+ for _, wanted := range iw.wantedEvents {
+ for _, seen := range iw.seenEvents {
+ if seen == wanted {
+ matched += 1
+ break
+ }
+ }
+ }
+
+ if len(iw.wantedEvents) != matched {
+ return
+ }
+
+ iw.expired = true
+ iw.ready <- true
+}
+
+// You can only join() once after which the watcher becomes expired.
+func (iw *interfaceWatcher) join(wantedEvents []interfaceWatcherEvent, timeoutSeconds int) bool {
+ {
+ iw.processingMutex.Lock()
+
+ if iw.expired || len(wantedEvents) == 0 {
+ iw.processingMutex.Unlock()
+ return false
+ }
+
+ iw.wantedEvents = wantedEvents
+ iw.evaluateEvents()
+
+ iw.processingMutex.Unlock()
+ }
+
+ result := false
+
+ select {
+ case <- iw.ready:
+ result = true
+ case <- time.After(time.Duration(timeoutSeconds) * time.Second):
+ result = false
+ }
+
+ {
+ iw.processingMutex.Lock()
+
+ iw.wantedEvents = nil
+ iw.expired = true
+
+ iw.processingMutex.Unlock()
+ }
+
+ return result
+}
+
+func (iw *interfaceWatcher) destroy() {
+ if iw.interfaceChangeCallback != nil {
+ iw.interfaceChangeCallback.Unregister()
+ iw.interfaceChangeCallback = nil
+ }
+}
diff --git a/wireguard/wireguard-go-windows/libwg.go b/wireguard/wireguard-go-windows/libwg.go
new file mode 100644
index 0000000000..a8a5fe50fd
--- /dev/null
+++ b/wireguard/wireguard-go-windows/libwg.go
@@ -0,0 +1,290 @@
+/* SPDX-License-Identifier: Apache-2.0
+ *
+ * Copyright (C) 2017-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ * Copyright (C) 2019 Amagicom AB. All Rights Reserved.
+ */
+
+package main
+
+// #include <stdlib.h>
+// #include <sys/types.h>
+// typedef void (__stdcall *LogSink)(unsigned int, const char *, void *);
+// static void callLogSink(void *logSink, int level, const char *message, void *context)
+// {
+// ((LogSink)logSink)((unsigned int)level, message, context);
+// }
+import "C"
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "log"
+ "math"
+ "net"
+ "runtime"
+ "strings"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+
+ "golang.zx2c4.com/wireguard/device"
+ "golang.zx2c4.com/wireguard/ipc"
+ "golang.zx2c4.com/wireguard/tun"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+// Define type aliases.
+type LogSink = unsafe.Pointer
+type LogContext = unsafe.Pointer
+
+type Logger struct {
+ sink LogSink
+ context LogContext
+ level C.int
+}
+
+func (l *Logger) Write(message []byte) (int, error) {
+ msg := C.CString(string(message))
+ C.callLogSink(l.sink, l.level, msg, l.context)
+ C.free(unsafe.Pointer(msg))
+ return len(message), nil
+}
+
+type TunnelContext struct {
+ device *device.Device
+ uapi net.Listener
+ logger *device.Logger
+}
+
+var tunnels map[int32]TunnelContext
+
+func init() {
+ device.RoamingDisabled = true
+ tunnels = make(map[int32]TunnelContext)
+}
+
+func newLogger(logSink LogSink, logContext LogContext) *device.Logger {
+ logger := new(device.Logger)
+
+ logger.Debug = log.New(
+ &Logger{sink: logSink, context: logContext, level: device.LogLevelDebug},
+ "",
+ 0,
+ )
+ logger.Info = log.New(
+ &Logger{sink: logSink, context: logContext, level: device.LogLevelInfo},
+ "",
+ 0,
+ )
+ logger.Error = log.New(
+ &Logger{sink: logSink, context: logContext, level: device.LogLevelError},
+ "",
+ 0,
+ )
+
+ return logger
+}
+
+// Find next free context slot
+func getContextHandle() (int32, error) {
+ var i int32
+ for i = 0; i < math.MaxInt32; i++ {
+ if _, exists := tunnels[i]; !exists {
+ break
+ }
+ }
+
+ if i == math.MaxInt32 {
+ return 0, errors.New("Handle table is full")
+ }
+
+ return i, nil
+}
+
+//export wgTurnOn
+func wgTurnOn(cIfaceName *C.char, mtu int, cSettings *C.char, logSink LogSink, logContext LogContext) int32 {
+ logger := newLogger(logSink, logContext)
+
+ if cIfaceName == nil {
+ logger.Error.Println("cIfaceName is null")
+ return -1
+ }
+
+ if cSettings == nil {
+ logger.Error.Println("cSettings is null")
+ return -1
+ }
+
+ contextHandle, err := getContextHandle()
+ if err != nil {
+ logger.Error.Println(err)
+ return -1
+ }
+
+ settings := C.GoString(cSettings)
+ ifaceName := C.GoString(cIfaceName)
+
+ // {AFE43773-E1F8-4EBB-8536-576AB86AFE9A}
+ networkId := windows.GUID { 0xafe43773, 0xe1f8, 0x4ebb, [8]byte{ 0x85, 0x36, 0x57, 0x6a, 0xb8, 0x6a, 0xfe, 0x9a } }
+
+ watcher, err := watchInterfaces()
+ if err != nil {
+ logger.Error.Println(err)
+ return -1
+ }
+ defer watcher.destroy()
+
+ wintun, err := tun.CreateTUNWithRequestedGUID(ifaceName, &networkId, mtu)
+ if err != nil {
+ logger.Error.Println("Failed to create tunnel")
+ logger.Error.Println(err)
+ return -1
+ }
+
+ nativeTun := wintun.(*tun.NativeTun)
+
+ actualInterfaceName, err := nativeTun.Name()
+ if err != nil {
+ nativeTun.Close()
+ logger.Error.Println("Failed to determine name of wintun adapter")
+ return -1
+ }
+
+ if actualInterfaceName != ifaceName {
+ // WireGuard picked a different name for the adapter than the one we expected.
+ // This indicates there is already an adapter with the name we intended to use.
+ nativeTun.Close()
+ logger.Error.Println("Failed to create adapter with specific name")
+ return -1
+ }
+
+ device := device.NewDevice(wintun, logger)
+
+ uapi, err := ipc.UAPIListen(ifaceName)
+ if err != nil {
+ logger.Error.Println("Failed to start UAPI")
+ logger.Error.Println(err)
+ device.Close()
+ return -1
+ }
+
+ setError := device.IpcSetOperation(bufio.NewReader(strings.NewReader(settings)))
+ if setError != nil {
+ logger.Error.Println("Failed to set device configuration")
+ logger.Error.Println(setError)
+ uapi.Close()
+ device.Close()
+ return -1
+ }
+
+ device.Up()
+
+ interfaces := []interfaceWatcherEvent{
+ {
+ luid: winipcfg.LUID(nativeTun.LUID()),
+ family: windows.AF_INET,
+ },
+ {
+ luid: winipcfg.LUID(nativeTun.LUID()),
+ family: windows.AF_INET6,
+ },
+ }
+
+ logger.Debug.Println("Waiting for interfaces to attach")
+
+ if !watcher.join(interfaces, 5) {
+ logger.Error.Println("Failed to wait for IP interfaces to become available")
+ uapi.Close()
+ device.Close()
+ return -1
+ }
+
+ logger.Debug.Println("Interfaces OK")
+
+ // Service UAPI.
+ go func() {
+ for {
+ conn, err := uapi.Accept()
+ if err != nil {
+ logger.Info.Println("UAPI Accept() failed")
+ logger.Info.Println(err)
+ return
+ }
+ go device.IpcHandle(conn)
+ }
+ }()
+
+ tunnels[contextHandle] = TunnelContext{
+ device: device,
+ uapi: uapi,
+ logger: logger,
+ }
+
+ return contextHandle
+}
+
+//export wgTurnOff
+func wgTurnOff(contextHandle int32) {
+ {
+ context, ok := tunnels[contextHandle]
+ if !ok {
+ return
+ }
+ delete(tunnels, contextHandle)
+ context.uapi.Close()
+ context.device.Close()
+ }
+ // Calling twice convinces the GC to release NOW.
+ runtime.GC()
+ runtime.GC()
+}
+
+//export wgRebindTunnelSocket
+func wgRebindTunnelSocket(family uint16, interfaceIndex uint32) {
+ for _, tunnel := range tunnels {
+ blackhole := (interfaceIndex == 0)
+ if family == windows.AF_INET {
+ tunnel.logger.Info.Printf("Binding v4 socket to interface %d (blackhole=%v)", interfaceIndex, blackhole)
+ err := tunnel.device.BindSocketToInterface4(interfaceIndex, blackhole)
+ if err != nil {
+ tunnel.logger.Info.Println(err)
+ }
+ } else if family == windows.AF_INET6 {
+ tunnel.logger.Info.Printf("Binding v6 socket to interface %d (blackhole=%v)", interfaceIndex, blackhole)
+ err := tunnel.device.BindSocketToInterface6(interfaceIndex, blackhole)
+ if err != nil {
+ tunnel.logger.Info.Println(err)
+ }
+ }
+ }
+}
+
+//export wgVersion
+func wgVersion() *C.char {
+ return C.CString(device.WireGuardGoVersion)
+}
+
+//export wgGetConfig
+func wgGetConfig(tunnelHandle int32) *C.char {
+ tunnel, ok := tunnels[tunnelHandle]
+ if !ok {
+ return nil
+ }
+
+ settings := new(bytes.Buffer)
+ writer := bufio.NewWriter(settings)
+ if err := tunnel.device.IpcGetOperation(writer); err != nil {
+ tunnel.logger.Error.Println("Failed to get config for tunnel: ", err)
+ return nil
+ }
+ writer.Flush()
+ return C.CString(settings.String())
+}
+
+//export wgFreePtr
+func wgFreePtr(ptr unsafe.Pointer) {
+ C.free(ptr)
+}
+
+func main() {}
diff --git a/wireguard/wireguard-go/Android.mk b/wireguard/wireguard-go/Android.mk
new file mode 100644
index 0000000000..0273a4adb1
--- /dev/null
+++ b/wireguard/wireguard-go/Android.mk
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: Apache-2.0
+#
+# Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
+
+BUILDDIR ?= $(CURDIR)/build
+DESTDIR ?= $(CURDIR)/../../android/build/extraJni/$(ANDROID_ABI)
+
+NDK_GO_ARCH_MAP_x86 := 386
+NDK_GO_ARCH_MAP_x86_64 := amd64
+NDK_GO_ARCH_MAP_arm := arm
+NDK_GO_ARCH_MAP_arm64 := arm64
+NDK_GO_ARCH_MAP_mips := mipsx
+NDK_GO_ARCH_MAP_mips64 := mips64x
+
+CLANG_FLAGS := --target=$(ANDROID_LLVM_TRIPLE) --gcc-toolchain=$(ANDROID_TOOLCHAIN_ROOT) --sysroot=$(ANDROID_SYSROOT)
+export CGO_CFLAGS := $(CLANG_FLAGS) $(CFLAGS)
+export CGO_LDFLAGS := $(CLANG_FLAGS) $(LDFLAGS)
+export CC := $(ANDROID_C_COMPILER)
+export GOARCH := $(NDK_GO_ARCH_MAP_$(ANDROID_ARCH_NAME))
+export GOOS := android
+export CGO_ENABLED := 1
+
+default: $(DESTDIR)/libwg.so
+
+GOBUILDARCH := $(NDK_GO_ARCH_MAP_$(shell uname -m))
+GOBUILDOS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
+GOBUILDVERSION := 1.12
+GOBUILDTARBALL := https://dl.google.com/go/go$(GOBUILDVERSION).$(GOBUILDOS)-$(GOBUILDARCH).tar.gz
+GOBUILDVERSION_NEEDED := go version go$(GOBUILDVERSION) $(GOBUILDOS)/$(GOBUILDARCH)
+export GOROOT := $(BUILDDIR)/goroot
+export GOPATH := $(BUILDDIR)/gopath
+export PATH := $(GOROOT)/bin:$(PATH)
+GOBUILDVERSION_CURRENT := $(shell $(GOROOT)/bin/go version 2>/dev/null)
+ifneq ($(GOBUILDVERSION_NEEDED),$(GOBUILDVERSION_CURRENT))
+$(shell rm -f $(GOROOT)/bin/go)
+endif
+$(GOROOT)/bin/go:
+ rm -rf "$(GOROOT)"
+ mkdir -p "$(GOROOT)"
+ curl "$(GOBUILDTARBALL)" | tar -C "$(GOROOT)" --strip-components=1 -xzf - || { rm -rf "$(GOROOT)"; exit 1; }
+ patch -p1 -f -N -r- -d "$(GOROOT)" < goruntime-boottime-over-monotonic.diff || { rm -rf "$(GOROOT)"; exit 1; }
+
+$(shell test "$$(cat $(BUILDDIR)/.gobuildversion 2>/dev/null)" = "$(GOBUILDVERSION_CURRENT)" || rm -f "$(DESTDIR)/libwg.so")
+
+$(DESTDIR)/libwg.so: $(GOROOT)/bin/go
+ mkdir -p $(DESTDIR)
+ go get -tags "linux android" || { chmod -fR +w "$(GOPATH)/pkg/mod"; rm -rf "$(GOPATH)/pkg/mod"; exit 1; }
+ chmod -fR +w "$(GOPATH)/pkg/mod"
+ go build -tags "linux android" -ldflags="-X main.socketDirectory=/data/data/$(ANDROID_PACKAGE_NAME)/cache/wireguard" -v -o "$@" -buildmode c-shared
+ go version > $(BUILDDIR)/.gobuildversion
+ rm -f $(DESTDIR)/libwg.h
+
+
+clean:
+ rm -f $(DESTDIR)/libwg.so
diff --git a/wireguard/wireguard-go/build-android.sh b/wireguard/wireguard-go/build-android.sh
new file mode 100755
index 0000000000..335b88fb3b
--- /dev/null
+++ b/wireguard/wireguard-go/build-android.sh
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+
+set -e
+
+# Ensure we are in the correct directory for the execution of this script
+script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $script_dir
+
+
+for arch in arm arm64 x86_64 x86; do
+ case "$arch" in
+ "arm64")
+ export ANDROID_LLVM_TRIPLE="aarch64-linux-android"
+ export ANDROID_LIB_TRIPLE="aarch64-linux-android"
+ export RUST_TARGET_TRIPLE="aarch64-linux-android"
+ export RUST_LLVM_ARCH="aarch64"
+ export ANDROID_ABI="arm64-v8a"
+ ;;
+ "x86_64")
+ export ANDROID_LLVM_TRIPLE="x86_64-linux-android"
+ export ANDROID_LIB_TRIPLE="x86_64-linux-android"
+ export RUST_TARGET_TRIPLE="x86_64-linux-android"
+ export RUST_LLVM_ARCH="x86_64"
+ export ANDROID_ABI="x86_64"
+ ;;
+ "arm")
+ export ANDROID_LLVM_TRIPLE="armv7a-linux-androideabi"
+ export ANDROID_LIB_TRIPLE="arm-linux-androideabi"
+ export RUST_TARGET_TRIPLE="armv7-linux-androideabi"
+ export RUST_LLVM_ARCH="armv7"
+ export ANDROID_ABI="armeabi-v7a"
+ ;;
+ "x86")
+ export ANDROID_LLVM_TRIPLE="i686-linux-android"
+ export ANDROID_LIB_TRIPLE="i686-linux-android"
+ export RUST_TARGET_TRIPLE="i686-linux-android"
+ export RUST_LLVM_ARCH="i686"
+ export ANDROID_ABI="i686"
+ ;;
+ esac
+
+ export ANDROID_ARCH_NAME="$arch"
+ export ANDROID_TOOLCHAIN_ROOT="/opt/android/toolchains/android21-${RUST_LLVM_ARCH}"
+ export ANDROID_SYSROOT="${ANDROID_TOOLCHAIN_ROOT}/sysroot"
+ export ANDROID_C_COMPILER="${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_LLVM_TRIPLE}21-clang"
+
+ export PATH="$PATH:${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/bin"
+
+ # Build Wireguard-Go
+ echo $(pwd)
+ make -f Android.mk clean
+
+ export CFLAGS="-D__ANDROID_API__=21"
+ export LDFLAGS="-L${ANDROID_SYSROOT}/usr/lib/${ANDROID_LIB_TRIPLE}/21"
+
+ make -f Android.mk
+ # Copy build artifacts to `build/libs/$RUST_TARGET_TRIPLE` to be able to build `mullvad-jni`
+ chmod 777 ../../android/build/
+ chmod 777 ../../android/build/extraJni
+ chmod 777 ../../android/build/extraJni/*
+ mkdir -p ../../build/lib/$RUST_TARGET_TRIPLE
+ cp ../../android/build/extraJni/$ANDROID_ABI/libwg.so ../../build/lib/$RUST_TARGET_TRIPLE
+done
diff --git a/wireguard/wireguard-go/go.mod b/wireguard/wireguard-go/go.mod
new file mode 100644
index 0000000000..7827c2848e
--- /dev/null
+++ b/wireguard/wireguard-go/go.mod
@@ -0,0 +1,8 @@
+module github.com/mullvad/mullvadvpn-app/wireguard-go
+
+go 1.12
+
+require (
+ golang.org/x/sys v0.0.0-20191003212358-c178f38b412c
+ golang.zx2c4.com/wireguard v0.0.20200121
+)
diff --git a/wireguard/wireguard-go/go.sum b/wireguard/wireguard-go/go.sum
new file mode 100644
index 0000000000..d81030de9e
--- /dev/null
+++ b/wireguard/wireguard-go/go.sum
@@ -0,0 +1,37 @@
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo=
+golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56 h1:ZpKuNIejY8P0ExLOVyKhb0WsgG8UdvHXe6TWjY7eL6k=
+golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc h1:c0o/qxkaO2LF5t6fQrT4b5hzyggAkLLlCUjqfRxd8Q4=
+golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
+golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
+golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191003171128-d98b1b443823 h1:Ypyv6BNJh07T1pUSrehkLemqPKXhus2MkfktJ91kRh4=
+golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5 h1:f005F/Jl5JLP036x7QIvUVhNTqxvSYwFIiyOh2q12iU=
+golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190618155005-516e3c20635f h1:dHNZYIYdq2QuU6w73vZ/DzesPbVlZVYZTtTZmrnsbQ8=
+golang.org/x/sys v0.0.0-20190618155005-516e3c20635f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191003212358-c178f38b412c h1:6Zx7DRlKXf79yfxuQ/7GqV3w2y7aDsk6bGg0MzF5RVU=
+golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.zx2c4.com/wireguard v0.0.20190518-0.20190605110920-108c37a05639 h1:AoX5+g0OBk+KqTTMVl4YPFZ9ioU2tPW1YwtzaVWdORA=
+golang.zx2c4.com/wireguard v0.0.20190518-0.20190605110920-108c37a05639/go.mod h1:8X7vp4RrsvM83bde6vQ94DsL4ZpjUViVUym8aa8zGhs=
+golang.zx2c4.com/wireguard v0.0.20190805-0.20190805190438-a6aae7b14166 h1:T9pj0ZaaF8Fjy9HraORGjgpY/NxmIFYYc607yVzAsIw=
+golang.zx2c4.com/wireguard v0.0.20190805-0.20190805190438-a6aae7b14166/go.mod h1:NFs2tkQT6xXo9kzqGJxObM2MzHhraJi7ZQUmwIqT+tE=
+golang.zx2c4.com/wireguard v0.0.20190805-0.20190805190438-b16dba4 h1:vb+nILAYnYsLWs942XZIbSbhHzjezHRl3p7Hqzkx8yE=
+golang.zx2c4.com/wireguard v0.0.20190805-0.20190805190438-b16dba4/go.mod h1:NFs2tkQT6xXo9kzqGJxObM2MzHhraJi7ZQUmwIqT+tE=
+golang.zx2c4.com/wireguard v0.0.20191012 h1:sdX+y3hrHkW8KJkjY7ZgzpT5Tqo8XnBkH55U1klphko=
+golang.zx2c4.com/wireguard v0.0.20191012/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
+golang.zx2c4.com/wireguard v0.0.20191013-0.20191017134306-ae492d1b3599 h1:fHOjo1GyHRI2q/LcFB9NiFTqXB7WRiu2idShqqTwrZ4=
+golang.zx2c4.com/wireguard v0.0.20191013-0.20191017134306-ae492d1b3599/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
+golang.zx2c4.com/wireguard v0.0.20200121 h1:vcswa5Q6f+sylDfjqyrVNNrjsFUUbPsgAQTBCAg/Qf8=
+golang.zx2c4.com/wireguard v0.0.20200121/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
diff --git a/wireguard/wireguard-go/goruntime-boottime-over-monotonic.diff b/wireguard/wireguard-go/goruntime-boottime-over-monotonic.diff
new file mode 100644
index 0000000000..e5c668bde1
--- /dev/null
+++ b/wireguard/wireguard-go/goruntime-boottime-over-monotonic.diff
@@ -0,0 +1,161 @@
+From 6998a7866b8428fd49c31506795c9f8154826d13 Mon Sep 17 00:00:00 2001
+From: "Jason A. Donenfeld" <Jason@zx2c4.com>
+Date: Wed, 27 Feb 2019 05:05:44 +0100
+Subject: [PATCH] runtime: use CLOCK_BOOTTIME in nanotime on Linux
+
+This makes timers account for having expired while a computer was
+asleep, which is quite common on mobile devices. Note that BOOTTIME is
+identical to MONOTONIC, except that it takes into account time spent
+in suspend. In Linux 4.17, the kernel will actually make MONOTONIC act
+like BOOTTIME anyway, so this switch will additionally unify the
+timer behavior across kernels.
+
+BOOTTIME was introduced into Linux 2.6.39-rc1 with 70a08cca1227d in
+2011.
+
+Fixes #24595
+
+Change-Id: I7b2a6ca0c5bc5fce57ec0eeafe7b68270b429321
+---
+ src/runtime/sys_linux_386.s | 4 ++--
+ src/runtime/sys_linux_amd64.s | 2 +-
+ src/runtime/sys_linux_arm.s | 4 ++--
+ src/runtime/sys_linux_arm64.s | 4 ++--
+ src/runtime/sys_linux_mips64x.s | 2 +-
+ src/runtime/sys_linux_mipsx.s | 2 +-
+ src/runtime/sys_linux_ppc64x.s | 2 +-
+ src/runtime/sys_linux_s390x.s | 2 +-
+ 8 files changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s
+index 40b55a67eb..6105780ff4 100644
+--- a/src/runtime/sys_linux_386.s
++++ b/src/runtime/sys_linux_386.s
+@@ -288,13 +288,13 @@ noswitch:
+
+ LEAL 8(SP), BX // &ts (struct timespec)
+ MOVL BX, 4(SP)
+- MOVL $1, 0(SP) // CLOCK_MONOTONIC
++ MOVL $7, 0(SP) // CLOCK_BOOTTIME
+ CALL AX
+ JMP finish
+
+ fallback:
+ MOVL $SYS_clock_gettime, AX
+- MOVL $1, BX // CLOCK_MONOTONIC
++ MOVL $7, BX // CLOCK_BOOTTIME
+ LEAL 8(SP), CX
+ INVOKE_SYSCALL
+
+diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
+index b709f77060..18a1f1d43a 100644
+--- a/src/runtime/sys_linux_amd64.s
++++ b/src/runtime/sys_linux_amd64.s
+@@ -261,7 +261,7 @@ noswitch:
+ MOVQ runtime·vdsoClockgettimeSym(SB), AX
+ CMPQ AX, $0
+ JEQ fallback
+- MOVL $1, DI // CLOCK_MONOTONIC
++ MOVL $7, DI // CLOCK_BOOTTIME
+ LEAQ 0(SP), SI
+ CALL AX
+ MOVQ 0(SP), AX // sec
+diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s
+index 43a58335c8..8b93635f4f 100644
+--- a/src/runtime/sys_linux_arm.s
++++ b/src/runtime/sys_linux_arm.s
+@@ -11,7 +11,7 @@
+ #include "textflag.h"
+
+ #define CLOCK_REALTIME 0
+-#define CLOCK_MONOTONIC 1
++#define CLOCK_BOOTTIME 7
+
+ // for EABI, as we don't support OABI
+ #define SYS_BASE 0x0
+@@ -291,7 +291,7 @@ noswitch:
+ SUB $24, R13 // Space for results
+ BIC $0x7, R13 // Align for C code
+
+- MOVW $CLOCK_MONOTONIC, R0
++ MOVW $CLOCK_BOOTTIME, R0
+ MOVW $8(R13), R1 // timespec
+ MOVW runtime·vdsoClockgettimeSym(SB), R11
+ CMP $0, R11
+diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s
+index 8b344be8f8..daf142fba0 100644
+--- a/src/runtime/sys_linux_arm64.s
++++ b/src/runtime/sys_linux_arm64.s
+@@ -13,7 +13,7 @@
+ #define AT_FDCWD -100
+
+ #define CLOCK_REALTIME 0
+-#define CLOCK_MONOTONIC 1
++#define CLOCK_BOOTTIME 7
+
+ #define SYS_exit 93
+ #define SYS_read 63
+@@ -247,7 +247,7 @@ noswitch:
+ BIC $15, R1
+ MOVD R1, RSP
+
+- MOVW $CLOCK_MONOTONIC, R0
++ MOVW $CLOCK_BOOTTIME, R0
+ MOVD runtime·vdsoClockgettimeSym(SB), R2
+ CBZ R2, fallback
+ BL (R2)
+diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s
+index c45703d228..9842b596e7 100644
+--- a/src/runtime/sys_linux_mips64x.s
++++ b/src/runtime/sys_linux_mips64x.s
+@@ -189,7 +189,7 @@ TEXT runtime·walltime(SB),NOSPLIT,$16
+ RET
+
+ TEXT runtime·nanotime(SB),NOSPLIT,$16
+- MOVW $1, R4 // CLOCK_MONOTONIC
++ MOVW $7, R4 // CLOCK_BOOTTIME
+ MOVV $0(R29), R5
+ MOVV $SYS_clock_gettime, R2
+ SYSCALL
+diff --git a/src/runtime/sys_linux_mipsx.s b/src/runtime/sys_linux_mipsx.s
+index f362b0f3f1..5ab866e047 100644
+--- a/src/runtime/sys_linux_mipsx.s
++++ b/src/runtime/sys_linux_mipsx.s
+@@ -193,7 +193,7 @@ TEXT runtime·walltime(SB),NOSPLIT,$8-12
+ RET
+
+ TEXT runtime·nanotime(SB),NOSPLIT,$8-8
+- MOVW $1, R4 // CLOCK_MONOTONIC
++ MOVW $7, R4 // CLOCK_BOOTTIME
+ MOVW $4(R29), R5
+ MOVW $SYS_clock_gettime, R2
+ SYSCALL
+diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s
+index 6835f434de..46618b2d91 100644
+--- a/src/runtime/sys_linux_ppc64x.s
++++ b/src/runtime/sys_linux_ppc64x.s
+@@ -204,7 +204,7 @@ fallback:
+ JMP finish
+
+ TEXT runtime·nanotime(SB),NOSPLIT,$16
+- MOVD $1, R3 // CLOCK_MONOTONIC
++ MOVD $7, R3 // CLOCK_BOOTTIME
+
+ MOVD R1, R15 // R15 is unchanged by C code
+ MOVD g_m(g), R21 // R21 = m
+diff --git a/src/runtime/sys_linux_s390x.s b/src/runtime/sys_linux_s390x.s
+index c79ceea751..44e3258e60 100644
+--- a/src/runtime/sys_linux_s390x.s
++++ b/src/runtime/sys_linux_s390x.s
+@@ -180,7 +180,7 @@ TEXT runtime·walltime(SB),NOSPLIT,$16
+ RET
+
+ TEXT runtime·nanotime(SB),NOSPLIT,$16
+- MOVW $1, R2 // CLOCK_MONOTONIC
++ MOVW $7, R2 // CLOCK_BOOTTIME
+ MOVD $tp-16(SP), R3
+ MOVW $SYS_clock_gettime, R1
+ SYSCALL
+--
+2.20.1
+
diff --git a/wireguard/wireguard-go/libwg.go b/wireguard/wireguard-go/libwg.go
new file mode 100644
index 0000000000..5f2366c523
--- /dev/null
+++ b/wireguard/wireguard-go/libwg.go
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: Apache-2.0
+ *
+ * Copyright (C) 2017-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ * Copyright (C) 2019 Amagicom AB. All Rights Reserved.
+ */
+
+package main
+
+// #include <stdlib.h>
+import "C"
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "math"
+ "net"
+ "os"
+ "os/signal"
+ "runtime"
+ "strings"
+ "sync"
+ "unsafe"
+
+ "golang.org/x/sys/unix"
+
+ "golang.zx2c4.com/wireguard/device"
+ "golang.zx2c4.com/wireguard/ipc"
+ "golang.zx2c4.com/wireguard/tun"
+)
+
+var (
+ logFile *os.File
+ logFilePath *string
+ logFileLock sync.RWMutex
+)
+
+type FileLogger struct{}
+
+func (logger FileLogger) Write(buffer []byte) (int, error) {
+ logFileLock.RLock()
+ defer logFileLock.RUnlock()
+
+ return logFile.Write(buffer)
+}
+
+type TunnelHandle struct {
+ device *device.Device
+ uapi net.Listener
+}
+
+var tunnelHandles map[int32]TunnelHandle
+
+func init() {
+ device.RoamingDisabled = true
+ tunnelHandles = make(map[int32]TunnelHandle)
+ signals := make(chan os.Signal)
+ signal.Notify(signals, unix.SIGUSR2)
+ go func() {
+ buf := make([]byte, os.Getpagesize())
+ for {
+ select {
+ case <-signals:
+ n := runtime.Stack(buf, true)
+ buf[n] = 0
+ log.Println("WireGuard/GoBackend/StackTrace - ", buf)
+ }
+ }
+ }()
+}
+
+func newLogger(newLogFilePath string, level int) *device.Logger {
+ openLogFile(newLogFilePath)
+
+ logger := &device.Logger{
+ Debug: newLogForLevel(device.LogLevelDebug, level),
+ Info: newLogForLevel(device.LogLevelInfo, level),
+ Error: newLogForLevel(device.LogLevelError, level),
+ }
+
+ return logger
+}
+
+func openLogFile(newLogFilePath string) {
+ logFileLock.Lock()
+ defer logFileLock.Unlock()
+
+ if logFilePath == nil || *logFilePath != newLogFilePath {
+ if logFile != nil {
+ logFile.Close()
+ }
+
+ logFilePath = &newLogFilePath
+ backupLogFile(newLogFilePath)
+ logFile, _ = os.Create(newLogFilePath)
+ }
+}
+
+func backupLogFile(path string) {
+ backupPath := fmt.Sprintf("%s.old.log", strings.TrimSuffix(path, ".log"))
+
+ os.Rename(path, backupPath)
+}
+
+func newLogForLevel(level int, maxLevel int) *log.Logger {
+ if level > maxLevel {
+ return log.New(ioutil.Discard, "", log.Ldate|log.Ltime)
+ }
+
+ logger := &FileLogger{}
+
+ prefix := ""
+ switch level {
+ case device.LogLevelDebug:
+ prefix = "DEBUG: "
+ case device.LogLevelInfo:
+ prefix = "INFO: "
+ case device.LogLevelError:
+ prefix = "ERROR: "
+ }
+
+ return log.New(logger, prefix, log.Ldate|log.Ltime)
+}
+
+//export wgTurnOnWithFd
+func wgTurnOnWithFd(cIfaceName *C.char, mtu int, cSettings *C.char, fd int, logFilePath *C.char, level int) int32 {
+
+ logger := newLogger(C.GoString(logFilePath), level)
+ if cIfaceName == nil {
+ logger.Error.Println("cIfaceName is null")
+ return -1
+ }
+
+ if cSettings == nil {
+ logger.Error.Println("cSettings is null")
+ return -1
+ }
+ settings := C.GoString(cSettings)
+ ifaceName := C.GoString(cIfaceName)
+
+ file := os.NewFile(uintptr(fd), "")
+ tunDevice, err := tun.CreateTUNFromFile(file, mtu)
+ if err != nil {
+ logger.Error.Println(err)
+ if err.Error() == "bad file descriptor" {
+ return -2
+ }
+ return -1
+ }
+
+ device := device.NewDevice(tunDevice, logger)
+
+ var uapi net.Listener
+
+ uapiFile, err := ipc.UAPIOpen(ifaceName)
+ if err != nil {
+ logger.Error.Println(err)
+ } else {
+ uapi, err = ipc.UAPIListen(ifaceName, uapiFile)
+ if err != nil {
+ logger.Error.Println("Failed to start the UAPI")
+ logger.Error.Println(err)
+ uapiFile.Close()
+ } else {
+ go func() {
+ for {
+ conn, err := uapi.Accept()
+ if err != nil {
+ return
+ }
+ go device.IpcHandle(conn)
+ }
+ }()
+ }
+ }
+
+ setError := device.IpcSetOperation(bufio.NewReader(strings.NewReader(settings)))
+ if setError != nil {
+ logger.Error.Println(setError)
+ device.Close()
+ return -2
+ }
+ var i int32
+ for i = 0; i < math.MaxInt32; i++ {
+ if _, exists := tunnelHandles[i]; !exists {
+ break
+ }
+ }
+ if i == math.MaxInt32 {
+ device.Close()
+ return -1
+ }
+ tunnelHandles[i] = TunnelHandle{device: device, uapi: uapi}
+ device.Up()
+ return i
+}
+
+//export wgGetConfig
+func wgGetConfig(index int32) *C.char {
+ handle, ok := tunnelHandles[index]
+ if !ok {
+ return nil
+ }
+
+ settings := new(bytes.Buffer)
+ writer := bufio.NewWriter(settings)
+ if err := handle.device.IpcGetOperation(writer); err != nil {
+ return nil
+ }
+ writer.Flush()
+ return C.CString(settings.String())
+}
+
+//export wgFreePtr
+func wgFreePtr(ptr unsafe.Pointer) {
+ C.free(ptr)
+}
+
+
+//export wgTurnOff
+func wgTurnOff(tunnelHandle int32) {
+ handle, ok := tunnelHandles[tunnelHandle]
+ if !ok {
+ return
+ }
+ delete(tunnelHandles, tunnelHandle)
+ if handle.uapi != nil {
+ handle.uapi.Close()
+ }
+ handle.device.Close()
+}
+
+//export wgVersion
+func wgVersion() *C.char {
+ return C.CString(device.WireGuardGoVersion)
+}
+
+func main() {}
diff --git a/wireguard/wireguard-go/libwg_android.go b/wireguard/wireguard-go/libwg_android.go
new file mode 100644
index 0000000000..778bd59055
--- /dev/null
+++ b/wireguard/wireguard-go/libwg_android.go
@@ -0,0 +1,114 @@
+// +build android
+package main
+
+import (
+ "C"
+ "bufio"
+ "math"
+ "net"
+ "strings"
+
+ "golang.org/x/sys/unix"
+
+ "golang.zx2c4.com/wireguard/device"
+ "golang.zx2c4.com/wireguard/ipc"
+ "golang.zx2c4.com/wireguard/tun"
+)
+
+//export wgGetSocketV4
+func wgGetSocketV4(tunnelHandle int32) int32 {
+ handle, ok := tunnelHandles[tunnelHandle]
+ if !ok {
+ return -1
+ }
+ fd, err := handle.device.PeekLookAtSocketFd4()
+ if err != nil {
+ return -1
+ }
+ return int32(fd)
+}
+
+//export wgGetSocketV6
+func wgGetSocketV6(tunnelHandle int32) int32 {
+ handle, ok := tunnelHandles[tunnelHandle]
+ if !ok {
+ return -1
+ }
+ fd, err := handle.device.PeekLookAtSocketFd6()
+ if err != nil {
+ return -1
+ }
+ return int32(fd)
+}
+
+//export wgTurnOnWithFdAndroid
+func wgTurnOnWithFdAndroid(cIfaceName *C.char, mtu int, cSettings *C.char, fd int, logFilePath *C.char, level int) int32 {
+
+ logger := newLogger(C.GoString(logFilePath), level)
+ if cIfaceName == nil {
+ logger.Error.Println("cIfaceName is null")
+ return -1
+ }
+
+ if cSettings == nil {
+ logger.Error.Println("cSettings is null")
+ return -1
+ }
+ settings := C.GoString(cSettings)
+ ifaceName := C.GoString(cIfaceName)
+
+ tunDevice, ifaceName, err := tun.CreateUnmonitoredTUNFromFD(fd)
+ if err != nil {
+ logger.Error.Println(err)
+ unix.Close(fd)
+ if err.Error() == "bad file descriptor" {
+ return -2
+ }
+ return -1
+ }
+ device := device.NewDevice(tunDevice, logger)
+
+ var uapi net.Listener
+
+ uapiFile, err := ipc.UAPIOpen(ifaceName)
+ if err != nil {
+ logger.Error.Println(err)
+ } else {
+ uapi, err = ipc.UAPIListen(ifaceName, uapiFile)
+ if err != nil {
+ logger.Error.Println("Failed to start the UAPI")
+ logger.Error.Println(err)
+ uapiFile.Close()
+ } else {
+ go func() {
+ for {
+ conn, err := uapi.Accept()
+ if err != nil {
+ return
+ }
+ go device.IpcHandle(conn)
+ }
+ }()
+ }
+ }
+
+ setError := device.IpcSetOperation(bufio.NewReader(strings.NewReader(settings)))
+ if setError != nil {
+ logger.Error.Println(setError)
+ device.Close()
+ return -2
+ }
+ var i int32
+ for i = 0; i < math.MaxInt32; i++ {
+ if _, exists := tunnelHandles[i]; !exists {
+ break
+ }
+ }
+ if i == math.MaxInt32 {
+ device.Close()
+ return -1
+ }
+ tunnelHandles[i] = TunnelHandle{device: device, uapi: uapi}
+ device.Up()
+ return i
+}