aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJake McGinty <me@jake.su>2017-12-22 13:59:24 -0600
committerJake McGinty <me@jake.su>2017-12-22 14:00:06 -0600
commite6aadd208877f7b187046d0656f72dd39501a0a1 (patch)
treed27e80246ad503615909eda752281f26db5ff457
downloadwireguard-rs-e6aadd208877f7b187046d0656f72dd39501a0a1.tar.xz
wireguard-rs-e6aadd208877f7b187046d0656f72dd39501a0a1.zip
early, early rough draft
-rw-r--r--.gitignore5
-rw-r--r--Cargo.lock1103
-rw-r--r--Cargo.toml45
-rw-r--r--src/error.rs27
-rw-r--r--src/interface/config.rs300
-rw-r--r--src/interface/mod.rs317
-rw-r--r--src/main.rs100
-rw-r--r--src/protocol/mod.rs3
-rw-r--r--src/protocol/peer.rs189
-rw-r--r--src/types.rs107
10 files changed, 2196 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d6b8a48
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+
+/target/
+**/*.rs.bk
+.idea/
+up.sh
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..41ba6f5
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,1103 @@
+[[package]]
+name = "aho-corasick"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ansi_term"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "arrayvec"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "arrayvec"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "backtrace-sys"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "base64"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "bitflags"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bitflags"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "blake2-rfc"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "byteorder"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "bytes"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "cc"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "cfg-if"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "chacha20-poly1305-aead"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "chashmap"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "clap"
+version = "2.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "constant_time_eq"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "daemonize"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "dbghelp-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "error-chain"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "futures"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "gcc"
+version = "0.3.54"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "glob"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "hex"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "iovec"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ipnetwork"
+version = "0.12.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "lazycell"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "libc"
+version = "0.2.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "log"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "memchr"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "mio"
+version = "0.6.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "mio-uds"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "mio-utun"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "net2"
+version = "0.2.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "nix"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "nodrop"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "odds"
+version = "0.2.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "owning_ref"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "parking_lot"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread-id 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pnet"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_base 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_datalink 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_packet 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_sys 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_transport 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pnet_base"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "pnet_datalink"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_base 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_sys 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pnet_macros"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pnet_macros_support"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "pnet_base 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pnet_packet"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_base 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_macros 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_macros_support 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pnet_sys"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pnet_transport"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_base 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_packet 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet_sys 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "quote"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rand"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rand"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "redox_termios"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rust-crypto"
+version = "0.2.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-demangle"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-serialize"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc_version"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "scoped-tls"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "semver"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "slab"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "slab"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "smallvec"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "smallvec"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "snow"
+version = "0.1.8-preview"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "arrayvec 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chacha20-poly1305-aead 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "static_slice"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "strsim"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "structopt"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syn"
+version = "0.11.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "synom"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_errors"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_pos"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_syntax"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tai64"
+version = "0.1.0"
+source = "git+https://github.com/sopium/tai64#f43108fdb71075c2ee72351713c64da6fd88f9a8"
+dependencies = [
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "take"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "term"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "termion"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread-id"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "thread_local"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "time"
+version = "0.1.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-core"
+version = "0.1.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-io"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-proto"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-service"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-timer"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-uds"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-uds-proto"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "tokio-utun"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio-utun 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "treebitmap"
+version = "0.2.2"
+source = "git+https://github.com/sopium/treebitmap#fb5f2235c9841d2a4acb4f0b64a13c268bae58e7"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unicode-xid"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "unreachable"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "utf8-ranges"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "vec_map"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "void"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "wgrs"
+version = "0.6.0"
+dependencies = [
+ "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chashmap 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "daemonize 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pnet 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "snow 0.1.8-preview (registry+https://github.com/rust-lang/crates.io-index)",
+ "structopt 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "structopt-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tai64 0.1.0 (git+https://github.com/sopium/tai64)",
+ "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-uds-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-utun 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "treebitmap 0.2.2 (git+https://github.com/sopium/treebitmap)",
+]
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[metadata]
+"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
+"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
+"checksum arrayvec 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "e003cbf6e0e1c43a0fc8df2ea8ea24174514d35cbcf60c35ca6112e0139f65e2"
+"checksum arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2f0ef4a9820019a0c91d918918c93dc71d469f581a49b47ddc1d285d4270bbe2"
+"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
+"checksum backtrace 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8709cc7ec06f6f0ae6c2c7e12f6ed41540781f72b488d83734978295ceae182e"
+"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
+"checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557"
+"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
+"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
+"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
+"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
+"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400"
+"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
+"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
+"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
+"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
+"checksum chacha20-poly1305-aead 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77d2058ba29594f69c75e8a9018e0485e3914ca5084e3613cd64529042f5423b"
+"checksum chashmap 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47e651a8c1eb0cbbaa730f705e2531e75276c6f2bbe2eb12662cfd305213dff8"
+"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
+"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
+"checksum daemonize 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0239832c1b4ca406d5ec73728cf4c7336d25cf85dd32db9e047e9e706ee0e935"
+"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
+"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
+"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
+"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
+"checksum fuchsia-zircon 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bd510087c325af53ba24f3be8f1c081b0982319adcb8b03cad764512923ccc19"
+"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
+"checksum fuchsia-zircon-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "08b3a6f13ad6b96572b53ce7af74543132f1a7055ccceb6d073dd36c54481859"
+"checksum futures 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "118b49cac82e04121117cbd3121ede3147e885627d82c4546b87c702debb90c1"
+"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
+"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
+"checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc"
+"checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7"
+"checksum ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2134e210e2a024b5684f90e1556d5f71a1ce7f8b12e9ac9924c67fb36f63b336"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
+"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
+"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
+"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
+"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
+"checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb"
+"checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673"
+"checksum mio-utun 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ed33b4a824985cedd49c2efde3d90487b7801ab98917c2ed8bb2acdbe08a3e5"
+"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
+"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
+"checksum nix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2c5afeb0198ec7be8569d666644b574345aad2e95a53baf3a532da3e0f3fb32"
+"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
+"checksum odds 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "4eae0151b9dacf24fcc170d9995e511669a082856a91f958a2fe380bfab3fb22"
+"checksum owning_ref 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9d52571ddcb42e9c900c901a18d8d67e393df723fcd51dd59c5b1a85d0acb6cc"
+"checksum parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fa12d706797d42551663426a45e2db2e0364bd1dbf6aeada87e89c5f981f43e9"
+"checksum parking_lot_core 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "12d20aac4f67aa75f681aded784bac91f910ba3f2af1812573cdcf687414e122"
+"checksum pnet 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e866218222e997f8aeebbbda7761d29c3b75772573e65da68fff97c21c5754ad"
+"checksum pnet_base 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ef91690b568c732663a6b4ccaf6e14fb62b985c9edee933c32c42d55f05a7b5"
+"checksum pnet_datalink 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf82511ad5ea82f6d632a624edf7c60592271a1f76ecaeb7a7f2ae55f6e0c38a"
+"checksum pnet_macros 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60fa5bee262cdfd7cb3871a9b205b2858c262e2e90e48b5e00626f5c0fa32182"
+"checksum pnet_macros_support 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc4fa05e0ee7d4911bc88f9da16eb0c8f238c5e001f45379e42c2b7cb35e53fc"
+"checksum pnet_packet 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "081e4b575f26366f33f195281e07a0bde6f2be810f904921887b15a3e82e58e4"
+"checksum pnet_sys 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b834fac796acd6a4c66010d7fa14aa34d8a69d780e28aa754a24661d3738df3"
+"checksum pnet_transport 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "257eec056138182230f7f3c5dd065848fdfb09c93456adfdb583ec457dd3ed5a"
+"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
+"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
+"checksum rand 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d5f78082e6a6d042862611e9640cf20776185fee506cf6cf67e93c6225cee31"
+"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
+"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
+"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322"
+"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
+"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
+"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
+"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
+"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"
+"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
+"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
+"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
+"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d"
+"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
+"checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
+"checksum snow 0.1.8-preview (registry+https://github.com/rust-lang/crates.io-index)" = "f48c2e9c3e713e6e17beedb4ae145f1f4b6c7bd2e8ee993cece40607dd09d49e"
+"checksum static_slice 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92a7e0c5e3dfb52e8fbe0e63a1b947bbb17b4036408b151353c4491374931362"
+"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
+"checksum structopt 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "daed460ef88cdfdc6cc665f974feea29883c40f479b6976302c8ad8bf05de722"
+"checksum structopt-derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4da119c9a7a1eccb7c6de0c1eb3f7ed1c11138624d092b3687222aeed8f1375c"
+"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
+"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
+"checksum syntex 0.42.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a30b08a6b383a22e5f6edc127d169670d48f905bb00ca79a00ea3e442ebe317"
+"checksum syntex_errors 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "04c48f32867b6114449155b2a82114b86d4b09e1bddb21c47ff104ab9172b646"
+"checksum syntex_pos 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd49988e52451813c61fecbe9abb5cfd4e1b7bb6cdbb980a6fbcbab859171a6"
+"checksum syntex_syntax 0.42.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7628a0506e8f9666fdabb5f265d0059b059edac9a3f810bda077abb5d826bd8d"
+"checksum tai64 0.1.0 (git+https://github.com/sopium/tai64)" = "<none>"
+"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5"
+"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
+"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
+"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
+"checksum thread-id 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2af4d6289a69a35c4d3aea737add39685f2784122c28119a7713165a63d68c9d"
+"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
+"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
+"checksum tokio-core 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c87c27560184212c9dc45cd8f38623f37918248aad5b58fb65303b5d07a98c6e"
+"checksum tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "514aae203178929dbf03318ad7c683126672d4d96eccb77b29603d33c9e25743"
+"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389"
+"checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
+"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc"
+"checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9"
+"checksum tokio-uds-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93842f83f760d2a48eb54225f819d05549e69c481f56be4a1b1f51decf99da5b"
+"checksum tokio-utun 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e44b976406c6edfd4bede61feb70f5f0751d6dc5e965e5d817136cdc6051a2d"
+"checksum treebitmap 0.2.2 (git+https://github.com/sopium/treebitmap)" = "<none>"
+"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
+"checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
+"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
+"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
+"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
+"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
+"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..5764a2e
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,45 @@
+[package]
+name = "wgrs"
+version = "0.6.0"
+authors = ["Jake McGinty <me@jake.su>"]
+license = "GPL-3.0"
+repository = "https://git.zx2c4.com/wireguard-rs/"
+description = "Userspace implementation of WireGuard, a fast, modern and secure VPN tunnel."
+
+[dependencies]
+blake2-rfc = "0.2"
+byteorder = "^1.2"
+structopt = "^0.1"
+structopt-derive = "^0.1"
+daemonize = "0.2"
+error-chain = "^0.11"
+rand = "^0.4"
+libc = "0.2"
+nix = "0.9"
+rustc-serialize = "0.3.22"
+tai64 = { git = "https://github.com/sopium/tai64" }
+treebitmap = { git = "https://github.com/sopium/treebitmap" }
+chashmap = "^2.2"
+
+env_logger = "^0.4"
+log = "^0.3"
+
+mio = "^0.6"
+mio-uds = "^0.6"
+bytes = "0.4"
+futures = "0.1"
+tokio-io = "0.1"
+tokio-core = "0.1"
+tokio-proto = "0.1"
+tokio-service = "0.1"
+tokio-uds = "0.1"
+tokio-uds-proto = "0.1"
+tokio-utun = "0.1"
+tokio-timer = "^0.1"
+
+snow = "^0.1.8-preview"
+base64 = "^0.5"
+hex = "^0.3"
+rust-crypto = "*"
+time = "*"
+pnet = "*"
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000..4492444
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,27 @@
+use daemonize;
+use std::io;
+
+ error_chain! {
+ foreign_links {
+ Io(io::Error) #[doc = "Error during IO"];
+ Daemonize(daemonize::DaemonizeError) #[doc = "Error during IO"];
+ }
+
+ errors {
+// Launch(phase: LaunchStage) {
+// description("An error occurred during startup")
+// display("Startup aborted: {:?} did not complete successfully", phase)
+// }
+//
+// ConfigLoad(path: String) {
+// description("Config file not found")
+// display("Unable to read file `{}`", path)
+// }
+ }
+ }
+
+// impl From<LaunchStage> for ErrorKind {
+// fn from(v: LaunchStage) -> Self {
+// ErrorKind::Launch(v)
+// }
+// }
diff --git a/src/interface/config.rs b/src/interface/config.rs
new file mode 100644
index 0000000..6a76a23
--- /dev/null
+++ b/src/interface/config.rs
@@ -0,0 +1,300 @@
+//! The configuration logic for userspace WireGuard.
+
+// Dev notes:
+// * Configuration service should use channels to report updates it receives over its interface.
+
+use bytes::BytesMut;
+use error::Result;
+use std;
+use std::fs::{create_dir, remove_file};
+use std::iter::Iterator;
+use std::path::{Path, PathBuf};
+use std::io;
+use std::str;
+use std::net::{SocketAddr, IpAddr};
+use types::{PeerInfo, InterfaceInfo};
+use hex::{FromHex};
+
+use futures::{Future, Stream};
+use futures::unsync::mpsc;
+use tokio_io::{AsyncRead, AsyncWrite};
+use tokio_io::codec::{Encoder, Decoder};
+
+#[derive(Debug)]
+pub enum Command {
+ Set(usize, Vec<UpdateEvent>),
+ Get(usize)
+}
+
+#[derive(Debug)]
+#[allow(dead_code)]
+pub enum UpdateEvent {
+ PrivateKey([u8; 32]),
+ ListenPort(u16),
+ UpdatePeer(PeerInfo),
+ RemovePeer([u8; 32]),
+ RemoveAllPeers,
+}
+
+impl UpdateEvent {
+ fn from(items: Vec<(String, String)>) -> Vec<UpdateEvent> {
+ let mut events = vec![];
+ let mut public_key: Option<[u8; 32]> = None;
+ let mut preshared_key: Option<[u8; 32]> = None;
+ let mut allowed_ips: Vec<(IpAddr, u32)> = vec![];
+ let mut keep_alive_interval: Option<u16> = None;
+ let mut endpoint: Option<SocketAddr> = None;
+
+ for (key, value) in items {
+ match key.as_ref() {
+ "private_key" => {
+ let key = <[u8; 32]>::from_hex(&value).unwrap();
+ events.push(UpdateEvent::PrivateKey(key));
+ },
+ "listen_port" => { events.push(UpdateEvent::ListenPort(value.parse().unwrap())); },
+ "public_key" => {
+ if let Some(ref pubkey) = public_key {
+ events.push(UpdateEvent::UpdatePeer(PeerInfo {
+ pub_key: pubkey.clone(),
+ psk: preshared_key.clone(),
+ endpoint: endpoint.clone(),
+ allowed_ips: allowed_ips.clone(),
+ keep_alive_interval: keep_alive_interval.clone(),
+ }));
+ }
+ let key = <[u8; 32]>::from_hex(&value).unwrap();
+ public_key = Some(key);
+ },
+ "preshared_key" => { preshared_key = Some(<[u8; 32]>::from_hex(&value).unwrap()); },
+ "allowed_ip" => {
+ let (ip, cidr) = value.split_at(value.find('/').unwrap());
+ allowed_ips.push((ip.parse().unwrap(), (&cidr[1..]).parse().unwrap()))
+ },
+ "persistent_keepalive_interval" => {
+ keep_alive_interval = Some(value.parse().unwrap());
+ },
+ "endpoint" => { endpoint = Some(value.parse().unwrap()); },
+ _ => {}
+ }
+ }
+
+ if let Some(ref pubkey) = public_key {
+ events.push(UpdateEvent::UpdatePeer(PeerInfo {
+ pub_key: pubkey.clone(),
+ psk: preshared_key.clone(),
+ endpoint: endpoint.clone(),
+ allowed_ips: allowed_ips.clone(),
+ keep_alive_interval: keep_alive_interval.clone(),
+ }));
+ }
+ debug!("events {:?}", events);
+ events
+ }
+}
+
+pub struct ConfigurationCodec;
+
+impl Decoder for ConfigurationCodec {
+ type Item = Command;
+ type Error = io::Error;
+
+ fn decode(&mut self, buf: &mut BytesMut) -> std::result::Result<Option<Self::Item>, Self::Error> {
+ // Determine we have a full command ready for parsing.
+ let mut items = Vec::new();
+ let utf8 = String::from_utf8(buf.to_vec()).unwrap();
+ let mut data_iter = utf8.split("\n\n");
+ let blob = data_iter.next().unwrap();
+ if data_iter.next().is_none() {
+ return Ok(None)
+ }
+
+ // Parse the key-value pairs into something more usable
+ for line in blob.split('\n') {
+ let mut entry = line.split('=');
+ items.push((entry.next().unwrap().to_owned(), entry.next().unwrap().to_owned()));
+ }
+ buf.split_to(blob.len()+1);
+
+ let (ref cmd, ref version) = items.remove(0);
+ let command = if cmd == "get" {
+ Command::Get(version.parse().unwrap())
+ } else {
+ Command::Set(version.parse().unwrap(), UpdateEvent::from(items))
+ };
+
+ Ok(Some(command))
+ }
+}
+
+impl Encoder for ConfigurationCodec {
+ type Item = String;
+ type Error = io::Error;
+
+ fn encode(&mut self, msg: Self::Item, buf: &mut BytesMut) -> std::result::Result<(), Self::Error> {
+ buf.extend(msg.as_bytes());
+ buf.extend(b"\n\n");
+ Ok(())
+ }
+}
+
+
+//pub struct ConfigurationService {
+// interface_name: String,
+// peers: Rc<RefCell<HashMap<[u8; 32], Rc<RefCell<Peer>>>>>,
+// interface_info: Rc<RefCell<InterfaceInfo>>,
+// tx: mpsc::Sender<UpdateEvent>,
+//}
+
+//impl Service for ConfigurationService {
+// type Request = Command;
+// type Response = String;
+// type Error = io::Error;
+// type Future = Box<Future<Item=Self::Response, Error=Self::Error>>;
+//
+// fn call(&self, req: Self::Request) -> Self::Future {
+// debug!("{:?}", req);
+// match req {
+// Command::Get(version) => {
+// // see: https://www.wireguard.com/xplatform/
+// // this is just bullshit fillin
+// let buf = "private_key=e84b5a6d2717c1003a13b431570353dbaca9146cf150c5f8575680feba52027a
+//listen_port=12912
+//public_key=b85996fecc9c7f1fc6d2572a76eda11d59bcd20be8e543b15ce4bd85a8e75a33
+//preshared_key=188515093e952f5f22e865cef3012e72f8b5f0b598ac0309d5dacce3b70fcf52
+//allowed_ip=192.168.4.4/32
+//endpoint=[abcd:23::33%2]:51820
+//public_key=58402e695ba1772b1cc9309755f043251ea77fdcf10fbe63989ceb7e19321376
+//tx_bytes=38333
+//rx_bytes=2224
+//allowed_ip=192.168.4.6/32
+//persistent_keepalive_interval=111
+//endpoint=182.122.22.19:3233
+//public_key=662e14fd594556f522604703340351258903b64f35553763f19426ab2a515c58
+//endpoint=5.152.198.39:51820
+//allowed_ip=192.168.4.10/32
+//allowed_ip=192.168.4.11/32
+//tx_bytes=1212111
+//rx_bytes=1929999999
+//errno=0
+//\n";
+// Box::new(future::ok(buf.into()))
+// },
+// Command::Set(version, items) => {
+// let mut public_key = None;
+// let mut preshared_key = None;
+// let mut allowed_ips: Vec<(IpAddr, u32)> = vec![];
+// let mut persistent_keepalive_interval: Option<u16> = None;
+// let mut endpoint: Option<SocketAddr> = None;
+//
+// for (key, value) in items {
+// match key.as_ref() {
+//// "private_key" => { config.key = Some(value); },
+//// "fwmark" => { config.fwmark = Some(value.parse().unwrap()); },
+//// "listen_port" => { config.listen_port = Some(value.parse().unwrap()); },
+// "public_key" => {
+// if let Some(ref pubkey) = public_key {
+//// config.peers.push(Peer {
+//// peer_pubkey: [0u8; 32],
+//// psk: preshared_key,
+//// endpoint: endpoint,
+//// allowed_ips: allowed_ips.clone(),
+//// keep_alive_interval: persistent_keepalive_interval,
+//// });
+// }
+// public_key = Some(value);
+// },
+// "preshared_key" => { preshared_key = Some([0u8; 32]); },
+// "allowed_ip" => {
+// let (ip, cidr) = value.split_at(value.find('/').unwrap());
+// debug!("parsed allowed ip as ({}, {})", ip, &cidr[1..]);
+// allowed_ips.push((ip.parse().unwrap(), (&cidr[1..]).parse().unwrap()))
+// },
+// "persistent_keepalive_interval" => {
+// debug!("persistent_keepalive_interval");
+// persistent_keepalive_interval = Some(value.parse().unwrap());
+// },
+// "endpoint" => { endpoint = Some(value.parse().unwrap()); },
+// _ => {}
+// }
+// }
+// Box::new(future::ok("errno=0\nerrno=0\n\n".into()))
+// },
+// _ => {
+// Box::new(future::ok("errno=1\nerrno=1\n\n".into()))
+// }
+// }
+// }
+//}
+
+pub struct ConfigurationServiceManager {
+ interface_name: String,
+}
+
+impl ConfigurationServiceManager {
+ pub fn new(interface_name: &str) -> Self {
+ ConfigurationServiceManager {
+ interface_name: interface_name.into(),
+ }
+ }
+
+ /// Creates a new `WireGuard` instance
+ pub fn get_path(name: &str) -> Result<PathBuf> {
+ // let _tun = Tun::create(Some("hey"));
+ // Create the socket directory if not existing
+ let mut socket_path = Self::get_run_path().join("wireguard");
+
+ if !socket_path.exists() {
+ debug!("Creating socket path: {}", socket_path.display());
+ create_dir(&socket_path)?;
+ }
+ debug!("Setting chmod 0700 of socket path: {}",
+ socket_path.display());
+ Self::chmod(&socket_path, 0o700)?;
+
+ // Finish the socket path
+ socket_path.push(&name);
+ socket_path.set_extension("sock");
+ if socket_path.exists() {
+ debug!("Removing existing socket: {}", socket_path.display());
+ remove_file(&socket_path)?;
+ }
+
+ Ok(socket_path)
+ }
+
+ #[cfg(unix)]
+ /// Sets the permissions to a given `Path`
+ fn chmod(path: &Path, perms: u32) -> Result<()> {
+ use std::os::unix::prelude::PermissionsExt;
+ use std::fs::{set_permissions, Permissions};
+ set_permissions(path, Permissions::from_mode(perms))?;
+ Ok(())
+ }
+
+ #[cfg(windows)]
+ /// Sets the permissions to a given `Path`
+ fn chmod(_path: &Path, _perms: u32) -> Result<()> {
+ Ok(())
+ }
+
+ /// Returns the path where the socket and pid file will be stored
+ pub fn get_run_path() -> PathBuf {
+ if Path::new("/run").exists() {
+ PathBuf::from("/run")
+ } else {
+ PathBuf::from("/var").join("run")
+ }
+ }
+}
+
+impl Drop for ConfigurationServiceManager {
+ fn drop(&mut self) {
+ let mut socket_path = Self::get_run_path().join("wireguard");
+ socket_path.push(&self.interface_name);
+ socket_path.set_extension("sock");
+ if socket_path.exists() {
+ debug!("Removing socket on drop: {}", socket_path.display());
+ let _ = remove_file(&socket_path);
+ }
+ }
+}
diff --git a/src/interface/mod.rs b/src/interface/mod.rs
new file mode 100644
index 0000000..8cbbfb3
--- /dev/null
+++ b/src/interface/mod.rs
@@ -0,0 +1,317 @@
+mod config;
+
+use self::config::{ConfigurationServiceManager, UpdateEvent, Command, ConfigurationCodec};
+use base64;
+use hex;
+use byteorder::{ByteOrder, BigEndian, LittleEndian};
+use snow::NoiseBuilder;
+use protocol::Peer;
+use std::io;
+use std::rc::Rc;
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::net::SocketAddr;
+use std::time::Duration;
+use types::{InterfaceInfo};
+
+use pnet::packet::ipv4::Ipv4Packet;
+
+use futures::{Future, Stream, Sink, future, unsync, sync, stream};
+use tokio_core::reactor::{Core, Handle};
+use tokio_core::net::{UdpSocket, UdpCodec};
+use tokio_utun::{UtunStream, UtunCodec};
+use tokio_io::{AsyncRead};
+use tokio_io::codec::{Framed, Encoder, Decoder};
+use tokio_uds::{UnixListener};
+use tokio_timer::{Interval, Timer};
+
+fn debug_packet(header: &str, packet: &[u8]) {
+ let packet = Ipv4Packet::new(packet);
+ debug!("{} {:?}", header, packet);
+}
+
+pub struct Interface {
+ name: String,
+ info: Rc<RefCell<InterfaceInfo>>,
+ peers: Rc<RefCell<HashMap<[u8; 32], Rc<RefCell<Peer>>>>>,
+ ids: Rc<RefCell<HashMap<u32, Rc<RefCell<Peer>>>>>,
+}
+
+struct VecUdpCodec;
+impl UdpCodec for VecUdpCodec {
+ type In = (SocketAddr, Vec<u8>);
+ type Out = (SocketAddr, Vec<u8>);
+
+ fn decode(&mut self, src: &SocketAddr, buf: &[u8]) -> io::Result<Self::In> {
+ Ok((*src, buf.to_vec()))
+ }
+
+ fn encode(&mut self, msg: Self::Out, buf: &mut Vec<u8>) -> SocketAddr {
+ let (addr, mut data) = msg;
+ buf.append(&mut data);
+ addr
+ }
+}
+
+struct VecUtunCodec;
+#[allow(dead_code)]
+enum UtunPacket {
+ Inet4(Vec<u8>),
+ Inet6(Vec<u8>),
+}
+impl UtunCodec for VecUtunCodec {
+ type In = Vec<u8>;
+ type Out = Vec<u8>;
+
+ fn decode(&mut self, buf: &[u8]) -> io::Result<Self::In> {
+ debug!("utun packet type {}", buf[3]);
+ Ok(buf[4..].to_vec())
+ }
+
+ fn encode(&mut self, mut msg: Self::Out, buf: &mut Vec<u8>) {
+ buf.extend_from_slice(&[0u8, 0, 0, 2]);
+ buf.append(&mut msg);
+ }
+}
+
+impl Interface {
+ pub fn new(name: &str) -> Self {
+ let info = Rc::new(RefCell::new(InterfaceInfo::default()));
+ let peers = Rc::new(RefCell::new(HashMap::new()));
+ let ids = Rc::new(RefCell::new(HashMap::new()));
+ let _config_service = ConfigurationServiceManager::new(name);
+ Interface {
+ name: name.to_owned(),
+ info,
+ peers,
+ ids,
+ }
+ }
+
+ pub fn start(&mut self) {
+ let mut core = Core::new().unwrap();
+
+ let (utun_tx, utun_rx) = unsync::mpsc::channel::<Vec<u8>>(1024);
+ let udp_socket = UdpSocket::bind(&([0,0,0,0], 0).into(), &core.handle()).unwrap();
+ let (tx, rx) = unsync::mpsc::channel::<(SocketAddr, Vec<u8>)>(1024);
+ let (udp_writer, udp_reader) = udp_socket.framed(VecUdpCodec{}).split();
+ let udp_read_fut = udp_reader.for_each({
+ let ids_ref = self.ids.clone();
+ let handle = core.handle();
+ let tx = tx.clone();
+ let interface_info = self.info.clone();
+ move |(_socket_addr, packet)| {
+ debug!("got a UDP packet of length {}, packet type {}", packet.len(), packet[0]);
+ match packet[0] {
+ 1 => {
+ info!("got handshake initialization.");
+ },
+ 2 => {
+ let their_index = LittleEndian::read_u32(&packet[4..]);
+ let our_index = LittleEndian::read_u32(&packet[8..]);
+ let mut ids = ids_ref.borrow_mut();
+ let peer_ref = ids.get(&our_index).unwrap().clone();
+ let mut peer = peer_ref.borrow_mut();
+ peer.sessions.next.as_mut().unwrap().their_index = their_index;
+ let payload_len = peer.next_noise().expect("pending noise session")
+ .read_message(&packet[12..60], &mut []).unwrap();
+ assert!(payload_len == 0);
+ peer.ratchet_session().unwrap();
+ info!("got handshake response, ratcheted session.");
+ let tx = tx.clone();
+
+ let interface_info = interface_info.borrow();
+ let noise = NoiseBuilder::new("Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s".parse().unwrap())
+ .local_private_key(&interface_info.private_key.expect("no private key!"))
+ .remote_public_key(&peer.info.pub_key)
+ .prologue("WireGuard v1 zx2c4 Jason@zx2c4.com".as_bytes())
+ .psk(2, &peer.info.psk.expect("no psk!"))
+ .build_initiator().unwrap();
+ peer.set_next_session(noise.into());
+
+ let _ = ids.insert(peer.our_next_index().unwrap(), peer_ref.clone());
+
+ let init_packet = peer.get_handshake_packet();
+ let endpoint = peer.info.endpoint.unwrap().clone();
+
+ let timer = Timer::default();
+ let sleep = timer.sleep(Duration::from_secs(120));
+ let boop = sleep.and_then({
+ let handle = handle.clone();
+ let peer_ref = peer_ref.clone();
+ let interface_info = interface_info.clone();
+ move |_| {
+ info!("sending rekey!");
+ handle.spawn(tx.clone().send((endpoint, init_packet))
+ .map(|_| ())
+ .map_err(|_| ()));
+ Ok(())
+ }
+ }).map_err(|_|());
+ handle.spawn(boop);
+ },
+ 4 => {
+ let our_index_received = LittleEndian::read_u32(&packet[4..]);
+ let nonce = LittleEndian::read_u64(&packet[8..]);
+
+ let mut raw_packet = [0u8; 1500];
+ let ids = ids_ref.borrow();
+ let lookup = ids.get(&our_index_received);
+ if let Some(ref peer) = lookup {
+ let mut peer = peer.borrow_mut();
+ // info!("retrieved peer with pubkey {}", base64::encode(&peer.pubkey));
+ // info!("ok going to try to decrypt");
+
+ peer.rx_bytes += packet.len();
+ let noise = peer.current_noise().expect("current noise session");
+ noise.set_receiving_nonce(nonce).unwrap();
+ let payload_len = noise.read_message(&packet[16..], &mut raw_packet).unwrap();
+ debug_packet("received TRANSPORT: ", &raw_packet[..payload_len]);
+ handle.spawn(utun_tx.clone().send(raw_packet[..payload_len].to_owned())
+ .map(|_| ())
+ .map_err(|_| ()));
+ }
+ },
+ _ => unimplemented!()
+ }
+ Ok(())
+ }
+ }).map_err(|_| ());
+
+ let udp_write_fut = udp_writer.sink_map_err(|_| ()).send_all(
+ rx.map(|(addr, packet)| {
+ debug!("sending encrypted UDP packet");
+ (addr, packet)
+ }).map_err(|_| ())).map_err(|_| ());
+
+ let utun_stream = UtunStream::connect(&self.name, &core.handle()).unwrap().framed(VecUtunCodec{});
+ let (utun_writer, utun_reader) = utun_stream.split();
+ let utun_fut = utun_reader.for_each({
+ let ids = self.ids.clone();
+ let utun_handle = core.handle();
+ let udp_tx = tx.clone();
+ move |packet| {
+ debug_packet("received UTUN packet: ", &packet);
+ let mut ping_packet = [0u8; 1500];
+ let ids = ids.borrow();
+ let (_key, peer) = ids.iter().next().unwrap(); // TODO destination IP peer lookup
+ let mut peer = peer.borrow_mut();
+ ping_packet[0] = 4;
+ let their_index = peer.their_current_index().expect("no current index for them");
+ let endpoint = peer.info.endpoint.unwrap();
+ peer.tx_bytes += packet.len();
+ let noise = peer.current_noise().expect("current noise session");
+ LittleEndian::write_u32(&mut ping_packet[4..], their_index);
+ LittleEndian::write_u64(&mut ping_packet[8..], noise.sending_nonce().unwrap());
+ let len = noise.write_message(&packet, &mut ping_packet[16..]).expect("failed to encrypt outgoing UDP packet");
+ utun_handle.spawn(udp_tx.clone().send((endpoint, ping_packet[..(16+len)].to_owned()))
+ .map(|_| ())
+ .map_err(|_| ()));
+ Ok(())
+ }
+ }).map_err(|_| ());
+
+ let utun_write_fut = utun_writer.sink_map_err(|_| ()).send_all(
+ utun_rx.map(|packet| {
+ debug_packet("sending UTUN: ", &packet);
+ packet
+ }).map_err(|_| ())).map_err(|_| ());
+
+ let handle = core.handle();
+ let listener = UnixListener::bind(ConfigurationServiceManager::get_path(&self.name).unwrap(), &handle).unwrap();
+ let (config_tx, config_rx) = sync::mpsc::channel::<UpdateEvent>(1024);
+ let h = handle.clone();
+ let config_server = listener.incoming().for_each({
+ let config_tx = config_tx.clone();
+ let info = self.info.clone();
+ let peers = self.peers.clone();
+ move |(stream, _)| {
+ let (sink, stream) = stream.framed(ConfigurationCodec {}).split();
+ debug!("UnixServer connection.");
+
+ let handle = h.clone();
+ let responses = stream.and_then({
+ let config_tx = config_tx.clone();
+ let info = info.clone();
+ let peers = peers.clone();
+ move |command| {
+ match command {
+ Command::Set(_version, items) => {
+ config_tx.clone().send_all(stream::iter_ok(items)).wait().unwrap();
+ future::ok("errno=0\nerrno=0\n\n".to_string())
+ },
+ Command::Get(_version) => {
+ let info = info.borrow();
+ let peers = peers.borrow();
+ let mut s = String::new();
+ if let Some(private_key) = info.private_key {
+ s.push_str(&format!("private_key={}\n", hex::encode(private_key)));
+ }
+
+ for (_, peer) in peers.iter() {
+ s.push_str(&peer.borrow().to_config_string());
+ }
+ future::ok(format!("{}errno=0\n\n", s))
+ }
+ }
+ }
+ });
+
+ let fut = sink.send_all(responses).map(|_| ()).map_err(|_| ());
+
+ handle.spawn(fut);
+
+ Ok(())
+ }
+ }).map_err(|_| ());
+
+ let config_fut = config_rx.for_each({
+ let tx = tx.clone();
+ let handle = handle.clone();
+ move |event| {
+ let interface_info = self.info.clone();
+ match event {
+ UpdateEvent::PrivateKey(private_key) => {
+ let mut interface_info = interface_info.borrow_mut();
+ interface_info.private_key = Some(private_key);
+ debug!("set new private key");
+ },
+ UpdateEvent::ListenPort(port) => {
+ let mut interface_info = interface_info.borrow_mut();
+ interface_info.listen_port = Some(port);
+ debug!("set new listen port");
+ },
+ UpdateEvent::UpdatePeer(info) => {
+ info!("added new peer: {}", info);
+ let interface_info = interface_info.borrow();
+ let mut noise = NoiseBuilder::new("Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s".parse().unwrap())
+ .local_private_key(&interface_info.private_key.expect("no private key!"))
+ .remote_public_key(&info.pub_key)
+ .prologue("WireGuard v1 zx2c4 Jason@zx2c4.com".as_bytes())
+ .psk(2, &info.psk.expect("no psk!"))
+ .build_initiator().unwrap();
+
+ let mut peer = Peer::new(info.clone());
+ peer.set_next_session(noise.into());
+
+ let init_packet = peer.get_handshake_packet();
+ let our_index = peer.our_next_index().unwrap();
+ let peer = Rc::new(RefCell::new(peer));
+
+ let _ = self.ids.borrow_mut().insert(our_index, peer.clone());
+ let _ = self.peers.borrow_mut().insert(info.pub_key, peer);
+
+ handle.spawn(tx.clone().send((info.endpoint.unwrap(), init_packet))
+ .map(|_| ())
+ .map_err(|_| ()));
+ },
+ _ => unimplemented!()
+ }
+
+ future::ok(())
+ }
+ }).map_err(|_| ());
+
+ core.run(utun_fut.join(utun_write_fut.join(udp_read_fut.join(udp_write_fut.join(config_fut.join(config_server)))))).unwrap();
+ }
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..0f3f9e4
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,100 @@
+#![allow(unused_imports)]
+
+#[macro_use] extern crate log;
+extern crate env_logger;
+
+#[macro_use] extern crate structopt_derive;
+#[macro_use] extern crate error_chain;
+
+
+extern crate daemonize;
+extern crate rand;
+extern crate nix;
+extern crate structopt;
+
+extern crate mio;
+
+extern crate bytes;
+extern crate futures;
+extern crate tokio_core;
+extern crate tokio_io;
+extern crate tokio_proto;
+extern crate tokio_service;
+extern crate tokio_uds;
+extern crate tokio_utun;
+extern crate tokio_timer;
+
+extern crate snow;
+extern crate base64;
+extern crate hex;
+extern crate time;
+extern crate byteorder;
+extern crate crypto;
+extern crate pnet;
+
+mod error;
+mod interface;
+mod protocol;
+mod types;
+
+use daemonize::Daemonize;
+use error::{ErrorKind, Error, Result};
+use std::path::PathBuf;
+use interface::Interface;
+use structopt::StructOpt;
+
+#[derive(StructOpt, Debug)]
+#[structopt(name = "wgrs", about = "WireGuard - a network tunnel")]
+struct Opt {
+ /// A flag, true if used in the command line.
+ #[structopt(short = "d", long = "debug", help = "Activate debug mode")]
+ debug: bool,
+
+ /// An argument of type float, with a default value.
+ #[structopt(short = "f", long = "foreground", help = "Run in the foreground")]
+ foreground: bool,
+
+ /// Needed parameter, the first on the command line.
+ #[structopt(help = "WireGuard interface name", default_value = "utun4")]
+ interface: String,
+
+ /// An optional parameter, will be `None` if not present on the
+ /// command line.
+ #[structopt(help = "Output file, stdout if not present")]
+ output: Option<String>,
+}
+
+fn main() {
+ env_logger::init().unwrap();
+ let opt = Opt::from_args();
+
+ if !opt.foreground {
+ daemonize().expect("failed to daemonize");
+ }
+
+ Interface::new(&opt.interface).start();
+// WireGuard::start(interface_name).expect("failed to start WireGuard interface");
+}
+
+fn daemonize() -> Result<()> {
+ if !nix::unistd::getuid().is_root() {
+ bail!("You are not the root user which can spawn the daemon.");
+ }
+
+ debug!("Starting daemon.");
+
+ let pid_path = PathBuf::new(); // TODO temporary
+
+// let pid_path = WireGuard::get_run_path();
+
+ let daemonize = Daemonize::new()
+ .pid_file(pid_path.join("wireguard.pid"))
+ .chown_pid_file(true)
+ .working_directory(pid_path)
+ .user("nobody")
+ .group("daemon")
+ .umask(0o077);
+
+ daemonize.start()?;
+ Ok(())
+}
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs
new file mode 100644
index 0000000..bae5340
--- /dev/null
+++ b/src/protocol/mod.rs
@@ -0,0 +1,3 @@
+mod peer;
+
+pub use self::peer::Peer;
diff --git a/src/protocol/peer.rs b/src/protocol/peer.rs
new file mode 100644
index 0000000..e26e1bf
--- /dev/null
+++ b/src/protocol/peer.rs
@@ -0,0 +1,189 @@
+use byteorder::{ByteOrder, BigEndian, LittleEndian};
+use crypto::blake2s::Blake2s;
+use snow::{self, NoiseBuilder};
+use pnet::packet::Packet;
+use pnet::packet::ip::IpNextHeaderProtocols;
+use pnet::packet::ipv4::{self, MutableIpv4Packet};
+use pnet::packet::icmp::{self, MutableIcmpPacket, IcmpTypes, echo_reply, echo_request};
+use std::{self, io};
+use std::fmt::{self, Debug, Display, Formatter};
+use std::net::{Ipv4Addr, IpAddr, SocketAddr, ToSocketAddrs};
+use std::str::FromStr;
+use std::thread::JoinHandle;
+use base64;
+use hex;
+use time;
+use rand::{self, Rng};
+use types::PeerInfo;
+
+use futures::{self, Future};
+use tokio_core::reactor::Handle;
+use tokio_core::net::{UdpSocket, UdpCodec};
+
+pub struct Peer {
+ pub info: PeerInfo,
+ pub sessions: Sessions,
+ pub tx_bytes: usize,
+ pub rx_bytes: usize,
+}
+
+pub struct Session {
+ pub noise: snow::Session,
+ pub our_index: u32,
+ pub their_index: u32,
+}
+
+impl Session {
+ #[allow(dead_code)]
+ pub fn with_their_index(session: snow::Session, their_index: u32) -> Session {
+ Session {
+ noise: session,
+ our_index: rand::thread_rng().gen::<u32>(),
+ their_index,
+ }
+ }
+
+ pub fn into_transport_mode(self) -> Session {
+ Session {
+ noise: self.noise.into_transport_mode().unwrap(),
+ our_index: self.our_index,
+ their_index: self.their_index,
+ }
+ }
+}
+
+impl From<snow::Session> for Session {
+ fn from(session: snow::Session) -> Self {
+ Session {
+ noise: session,
+ our_index: 0,
+ their_index: 0,
+ }
+ }
+}
+
+pub struct Sessions {
+ pub past: Option<Session>,
+ pub current: Option<Session>,
+ pub next: Option<Session>,
+}
+
+impl Display for Peer {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "Peer({})", self.info)
+ }
+}
+
+impl Debug for Peer {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "Peer( endpoint: {:?}, pubkey: [redacted], psk: [redacted] )", self.info.endpoint)
+ }
+}
+
+fn memcpy(out: &mut [u8], data: &[u8]) {
+ out[..data.len()].copy_from_slice(data);
+}
+
+impl Peer {
+ pub fn new(info: PeerInfo) -> Peer {
+ Peer {
+ info,
+ sessions: Sessions {
+ past: None,
+ current: None,
+ next: None
+ },
+ tx_bytes: 0,
+ rx_bytes: 0,
+ }
+ }
+
+ pub fn set_next_session(&mut self, session: Session) {
+ let _ = std::mem::replace(&mut self.sessions.next, Some(session));
+ }
+
+ pub fn ratchet_session(&mut self) -> Result<(), ()> {
+ let next = std::mem::replace(&mut self.sessions.next, None).ok_or(())?;
+ let next = next.into_transport_mode();
+
+ let current = std::mem::replace(&mut self.sessions.current, Some(next));
+ let _ = std::mem::replace(&mut self.sessions.past, current);
+ Ok(())
+ }
+
+ pub fn current_noise(&mut self) -> Option<&mut snow::Session> {
+ if let Some(ref mut session) = self.sessions.current {
+ Some(&mut session.noise)
+ } else {
+ None
+ }
+ }
+
+ pub fn next_noise(&mut self) -> Option<&mut snow::Session> {
+ if let Some(ref mut session) = self.sessions.next {
+ Some(&mut session.noise)
+ } else {
+ None
+ }
+ }
+
+ pub fn our_next_index(&self) -> Option<u32> {
+ if let Some(ref session) = self.sessions.next {
+ Some(session.our_index)
+ } else {
+ None
+ }
+ }
+
+ pub fn our_current_index(&self) -> Option<u32> {
+ if let Some(ref session) = self.sessions.current {
+ Some(session.our_index)
+ } else {
+ None
+ }
+ }
+
+ pub fn their_current_index(&self) -> Option<u32> {
+ if let Some(ref session) = self.sessions.current {
+ Some(session.their_index)
+ } else {
+ None
+ }
+ }
+
+ pub fn get_handshake_packet(&mut self) -> Vec<u8> {
+ let now = time::get_time();
+ let mut tai64n = [0; 12];
+ BigEndian::write_i64(&mut tai64n[0..], 4611686018427387914 + now.sec);
+ BigEndian::write_i32(&mut tai64n[8..], now.nsec);
+ let mut initiation_packet = vec![0; 148];
+ initiation_packet[0] = 1; /* Type: Initiation */
+ initiation_packet[1] = 0; /* Reserved */
+ initiation_packet[2] = 0; /* Reserved */
+ initiation_packet[3] = 0; /* Reserved */
+ LittleEndian::write_u32(&mut initiation_packet[4..], self.our_next_index().unwrap());
+ self.sessions.next.as_mut().unwrap().noise.write_message(&tai64n, &mut initiation_packet[8..]).unwrap();
+ let mut mac_key_input = [0; 40];
+ let mut mac_key = [0; 32];
+ memcpy(&mut mac_key_input, b"mac1----");
+ memcpy(&mut mac_key_input[8..], &self.info.pub_key);
+ Blake2s::blake2s(&mut mac_key, &mac_key_input, &[0; 0]);
+ let mut mac = [0; 16];
+ Blake2s::blake2s(&mut mac, &initiation_packet[0..116], &mac_key);
+ memcpy(&mut initiation_packet[116..], &mac);
+
+ initiation_packet
+ }
+
+ pub fn to_config_string(&self) -> String {
+ let mut s = format!("public_key={}\n", hex::encode(&self.info.pub_key));
+ if let Some(ref psk) = self.info.psk {
+ s.push_str(&format!("preshared_key={}\n", hex::encode(psk)));
+ }
+ if let Some(ref endpoint) = self.info.endpoint {
+ s.push_str(&format!("endpoint={}:{}\n", endpoint.ip().to_string(),endpoint.port()));
+ }
+ s.push_str(&format!("tx_bytes={}\nrx_bytes={}\n", self.tx_bytes, self.rx_bytes));
+ s
+ }
+}
diff --git a/src/types.rs b/src/types.rs
new file mode 100644
index 0000000..29b02bb
--- /dev/null
+++ b/src/types.rs
@@ -0,0 +1,107 @@
+use base64;
+use std::io::{self, Cursor, Read, Write};
+use byteorder::{BigEndian, LittleEndian, WriteBytesExt, ReadBytesExt};
+use std::fmt::{self, Display, Formatter};
+use std::net::{Ipv4Addr, IpAddr, SocketAddr};
+
+#[derive(Clone, Debug)]
+pub struct PeerInfo {
+ pub pub_key: [u8; 32],
+ pub psk: Option<[u8; 32]>,
+ pub endpoint: Option<SocketAddr>,
+ pub allowed_ips: Vec<(IpAddr, u32)>,
+ pub keep_alive_interval: Option<u16>,
+}
+
+impl Display for PeerInfo {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ let encoded = base64::encode(&self.pub_key);
+ write!(f, "{}...{}", &encoded[..4], &encoded[encoded.len()-4..])
+ }
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct InterfaceInfo {
+ pub private_key: Option<[u8; 32]>,
+ pub pub_key: Option<[u8; 32]>,
+ pub listen_port: Option<u16>,
+}
+
+pub enum Message {
+ HandshakeInitiation(HandshakeInitiationMessage),
+// HandshakeResponse(HandshakeResponseMessage),
+// Transport(TransportMessage),
+// CookieReply(CookieReplyMessage),
+ Other(Vec<u8>)
+}
+
+// TODO use TryFrom
+impl<'a> From<&'a [u8]> for Message {
+ fn from(bytes: &'a [u8]) -> Self {
+ use self::Message::*;
+ let mut cursor = Cursor::new(bytes);
+ match cursor.read_u8().unwrap() {
+ 1 => HandshakeInitiation(HandshakeInitiationMessage::from(&bytes[4..])),
+ _ => Other((&bytes[4..]).to_owned())
+ }
+ }
+}
+
+impl From<Message> for Vec<u8> {
+ fn from(message: Message) -> Self {
+ use self::Message::*;
+ match message {
+ HandshakeInitiation(message) => {
+ let mut bytes = vec![1u8, 0, 0, 0];
+ bytes.append(&mut message.into());
+ bytes
+ },
+ _ => unimplemented!()
+ }
+ }
+}
+
+pub struct HandshakeInitiationMessage {
+ pub sender_i: u32,
+ pub payload: [u8; 76],
+ pub mac1: [u8; 16],
+ pub mac2: [u8; 16]
+}
+
+impl HandshakeInitiationMessage {
+ pub fn new() -> Self {
+ HandshakeInitiationMessage {
+ sender_i: 0,
+ payload: [0u8; 76],
+ mac1: [0u8; 16],
+ mac2: [0u8; 16],
+ }
+ }
+}
+
+impl<'a> From<&'a [u8]> for HandshakeInitiationMessage {
+
+ fn from(bytes: &'a [u8]) -> Self {
+ let mut message = HandshakeInitiationMessage::new();
+ let mut cursor = Cursor::new(bytes);
+
+ message.sender_i = cursor.read_u32::<LittleEndian>().unwrap();
+ cursor.read_exact(&mut message.payload[..]).unwrap();
+ cursor.read_exact(&mut message.mac1[..]).unwrap();
+ cursor.read_exact(&mut message.mac2[..]).unwrap();
+ message
+ }
+}
+
+impl From<HandshakeInitiationMessage> for Vec<u8> {
+ fn from(message: HandshakeInitiationMessage) -> Self {
+ let mut cursor = vec![];
+ cursor.write_all(&[1u8, 0, 0, 0]).unwrap();
+ cursor.write_u32::<LittleEndian>(message.sender_i).unwrap();
+ cursor.write_all(&message.payload).unwrap();
+ cursor.write_all(&message.mac1).unwrap();
+ cursor.write_all(&message.mac2).unwrap();
+
+ cursor
+ }
+} \ No newline at end of file