diff --git a/Cargo.lock b/Cargo.lock index 2941071d..21b27143 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,18 +2,18 @@ # It is not intended for manual editing. [[package]] name = "addr2line" -version = "0.13.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" dependencies = [ "gimli", ] [[package]] name = "adler" -version = "0.2.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aead" @@ -26,9 +26,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] @@ -58,12 +58,12 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.50" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46254cf2fdcdf1badb5934448c1bcbe046a56537b3987d96c51a7afc5d03f293" +checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" dependencies = [ "addr2line", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -81,9 +81,9 @@ dependencies = [ [[package]] name = "bit-vec" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0dc55f2d8a1a85650ac47858bb001b4c0dd73d79e3c455a842925e68d29cd3" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] name = "bitflags" @@ -110,21 +110,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.4.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" +checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cc" -version = "1.0.60" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" [[package]] name = "cfg-if" @@ -198,9 +198,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg", "cfg-if 1.0.0", @@ -239,22 +239,22 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8492de420e9e60bc9a1d66e2dbb91825390b738a388606600663fc529b4b307" +checksum = "639891fde0dbea823fc3d798a0fdf9d2f9440a42d64a78ab3488b0ca025117b3" dependencies = [ "byteorder", "digest", - "rand_core", + "rand_core 0.5.1", "subtle", "zeroize", ] [[package]] name = "dashmap" -version = "4.0.1" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b937cd1fbd1f194ac842196bd2529f21618088ee6d8bff6a46ece611451c96b" +checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" dependencies = [ "cfg-if 1.0.0", "num_cpus", @@ -271,13 +271,13 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e" +checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" dependencies = [ "atty", "humantime", - "log 0.4.11", + "log 0.4.14", "regex", "termcolor", ] @@ -326,20 +326,31 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" [[package]] name = "glob" @@ -349,18 +360,18 @@ checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" [[package]] name = "hermit-abi" -version = "0.1.15" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] [[package]] name = "hex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hjul" @@ -385,9 +396,9 @@ dependencies = [ [[package]] name = "humantime" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "instant" @@ -398,6 +409,12 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "ioctl-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c429fffa658f288669529fc26565f728489a2e39bc7b24a428aaaf51355182e" + [[package]] name = "iovec" version = "0.1.4" @@ -424,9 +441,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.45" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" +checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c" dependencies = [ "wasm-bindgen", ] @@ -455,15 +472,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.77" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" [[package]] name = "lock_api" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176" dependencies = [ "scopeguard", ] @@ -474,29 +491,29 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" dependencies = [ - "log 0.4.11", + "log 0.4.14", ] [[package]] name = "log" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] name = "memchr" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "miniz_oxide" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c60c0dfe32c10b43a144bad8fc83538c52f58302c92300ea7ec7bf7b38d5a7b9" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", "autocfg", @@ -504,9 +521,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.22" +version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" dependencies = [ "cfg-if 0.1.10", "fuchsia-zircon", @@ -514,7 +531,7 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log 0.4.11", + "log 0.4.14", "miow", "net2", "slab", @@ -528,16 +545,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ "lazycell", - "log 0.4.11", + "log 0.4.14", "mio", "slab", ] [[package]] name = "miow" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" dependencies = [ "kernel32-sys", "net2", @@ -547,20 +564,32 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" dependencies = [ "cfg-if 0.1.10", "libc", "winapi 0.3.9", ] +[[package]] +name = "nix" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a" +dependencies = [ + "bitflags 1.2.1", + "cc", + "cfg-if 1.0.0", + "libc", +] + [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg", ] @@ -577,15 +606,15 @@ dependencies = [ [[package]] name = "object" -version = "0.20.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" [[package]] name = "once_cell" -version = "1.4.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" [[package]] name = "opaque-debug" @@ -593,6 +622,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "page_size" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "parking_lot" version = "0.11.1" @@ -606,9 +645,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ "cfg-if 1.0.0", "instant", @@ -620,9 +659,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "pnet" @@ -724,15 +763,15 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "proc-macro2" -version = "1.0.21" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" dependencies = [ "unicode-xid 0.2.1", ] @@ -749,8 +788,8 @@ dependencies = [ "lazy_static", "num-traits", "quick-error", - "rand", - "rand_chacha", + "rand 0.7.3", + "rand_chacha 0.2.2", "rand_xorshift", "regex-syntax", "rusty-fork", @@ -765,9 +804,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2", ] @@ -778,11 +817,23 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc 0.2.0", +] + +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ "libc", - "rand_chacha", - "rand_core", - "rand_hc", + "rand_chacha 0.3.0", + "rand_core 0.6.2", + "rand_hc 0.3.0", ] [[package]] @@ -792,7 +843,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.2", ] [[package]] @@ -801,7 +862,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom 0.2.2", ] [[package]] @@ -810,7 +880,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core 0.6.2", ] [[package]] @@ -819,32 +898,34 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" dependencies = [ - "rand_core", + "rand_core 0.5.1", ] [[package]] name = "redox_syscall" -version = "0.1.57" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041" +dependencies = [ + "bitflags 1.2.1", +] [[package]] name = "regex" -version = "1.3.9" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] name = "regex-syntax" -version = "0.6.18" +version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" +checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" [[package]] name = "remove_dir_all" @@ -857,9 +938,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.15" +version = "0.16.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" dependencies = [ "cc", "libc", @@ -872,9 +953,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" [[package]] name = "rustc-serialize" @@ -902,9 +983,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.116" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" +checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" [[package]] name = "slab" @@ -914,9 +995,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "1.4.2" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" [[package]] name = "spin" @@ -926,9 +1007,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spin" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "652ac3743312871a5fb703f0337e68ffa3cdc28c863efad0b8dc858fa10c991b" +checksum = "13287b4da9d1207a4f4929ac390916d64eacfe236a487e9a9f5b3be392be5162" [[package]] name = "subtle" @@ -938,9 +1019,9 @@ checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" [[package]] name = "syn" -version = "1.0.41" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b" +checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" dependencies = [ "proc-macro2", "quote", @@ -1010,13 +1091,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "rand", + "rand 0.8.3", "redox_syscall", "remove_dir_all", "winapi 0.3.9", @@ -1034,27 +1115,18 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" dependencies = [ "winapi-util", ] -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - [[package]] name = "typenum" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" [[package]] name = "unicode-xid" @@ -1086,9 +1158,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" [[package]] name = "wait-timeout" @@ -1105,25 +1177,31 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + [[package]] name = "wasm-bindgen" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" +checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" +checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae" dependencies = [ "bumpalo", "lazy_static", - "log 0.4.11", + "log 0.4.14", "proc-macro2", "quote", "syn", @@ -1132,9 +1210,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" +checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1142,9 +1220,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" +checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c" dependencies = [ "proc-macro2", "quote", @@ -1155,15 +1233,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.68" +version = "0.2.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" +checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489" [[package]] name = "web-sys" -version = "0.3.45" +version = "0.3.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" +checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" dependencies = [ "js-sys", "wasm-bindgen", @@ -1231,18 +1309,21 @@ dependencies = [ "hex", "hjul", "hmac", + "ioctl-sys", "ip_network_table-deps-treebitmap", "libc", - "log 0.4.11", + "log 0.4.14", + "nix", "num_cpus", + "page_size", "parking_lot", "pnet", "proptest", - "rand", - "rand_chacha", - "rand_core", + "rand 0.7.3", + "rand_chacha 0.2.2", + "rand_core 0.5.1", "ring", - "spin 0.7.0", + "spin 0.7.1", "subtle", "x25519-dalek", "zerocopy", @@ -1260,12 +1341,12 @@ dependencies = [ [[package]] name = "x25519-dalek" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc614d95359fd7afc321b66d2107ede58b246b844cf5d8a0adcca413e439f088" +checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" dependencies = [ "curve25519-dalek", - "rand_core", + "rand_core 0.5.1", "zeroize", ] @@ -1292,9 +1373,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f33972566adbd2d3588b0491eb94b98b43695c4ef897903470ede4f3f5a28a" +checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" dependencies = [ "zeroize_derive", ] diff --git a/Cargo.toml b/Cargo.toml index 640d8cb9..e4d387db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,11 @@ version = "0.5.0" [target.'cfg(unix)'.dependencies] libc = "^0.2" +[target.'cfg(target_os = "macos")'.dependencies] +ioctl-sys = "0.6" +page_size = "0.4" +nix = "0.20" + [dependencies.x25519-dalek] version = "^1.1" diff --git a/src/main.rs b/src/main.rs index 7e752bd4..1a6967b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,11 @@ extern crate alloc; +#[cfg(target_os = "macos")] +extern crate ioctl_sys; +#[cfg(target_os = "macos")] +extern crate page_size; + #[cfg(feature = "profiler")] extern crate cpuprofiler; diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index d28391ea..4962f04c 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -1,7 +1,6 @@ mod tun; -mod uapi; mod udp; +pub use crate::platform::unix::uapi::UnixUAPI as UAPI; pub use tun::LinuxTun as Tun; -pub use uapi::LinuxUAPI as UAPI; pub use udp::LinuxUDP as UDP; diff --git a/src/platform/linux/uapi.rs b/src/platform/linux/uapi.rs index 107745ad..99dd4577 100644 --- a/src/platform/linux/uapi.rs +++ b/src/platform/linux/uapi.rs @@ -1,4 +1,4 @@ -use super::super::uapi::*; +use crate::platform::unix::UnixAPI; use std::fs; use std::io; diff --git a/src/platform/macos/fd.rs b/src/platform/macos/fd.rs new file mode 100644 index 00000000..94cef988 --- /dev/null +++ b/src/platform/macos/fd.rs @@ -0,0 +1,44 @@ +use std::{io, os::unix::io::RawFd, sync::Arc}; + +struct FdInner { + fd: RawFd, +} + +impl Drop for FdInner { + fn drop(&mut self) { + unsafe { libc::close(self.fd) }; + } +} + +#[derive(Clone)] +pub(super) struct Fd { + fd: Arc, +} + +impl Fd { + pub fn new(fd: RawFd) -> Self { + Self { + fd: Arc::new(FdInner { fd }), + } + } + + pub unsafe fn raw_fd(&self) -> RawFd { + self.fd.fd + } + + pub fn write(&self, buf: &[u8]) -> io::Result { + let bytes_read = unsafe { libc::write(self.raw_fd(), buf.as_ptr() as _, buf.len()) }; + if bytes_read < 0 { + return Err(io::Error::from_raw_os_error(-bytes_read as i32)); + } + Ok(bytes_read as usize) + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + let bytes_written = unsafe { libc::read(self.raw_fd(), buf.as_mut_ptr() as _, buf.len()) }; + if bytes_written < 0 { + return Err(io::Error::last_os_error()); + } + Ok(bytes_written as usize) + } +} diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs new file mode 100644 index 00000000..32e67f9b --- /dev/null +++ b/src/platform/macos/mod.rs @@ -0,0 +1,8 @@ +mod fd; +mod sys; +mod tun; +mod udp; + +pub use crate::platform::unix::uapi::UnixUAPI as UAPI; +pub use tun::MacosTun as Tun; +pub use udp::MacosUDP as UDP; diff --git a/src/platform/macos/sys.rs b/src/platform/macos/sys.rs new file mode 100644 index 00000000..de4d10dd --- /dev/null +++ b/src/platform/macos/sys.rs @@ -0,0 +1,38 @@ +#![allow(non_camel_case_types)] +#[repr(C)] +pub struct ctl_info { + pub ctl_id: u32, + pub ctl_name: [u8; 96], +} +ioctl_sys::ioctl!(readwrite ctliocginfo with 'N', 3; ctl_info); + +#[repr(C)] +pub struct rt_msghdr { + pub rtm_msglen: u16, + pub rtm_version: u8, + pub rtm_type: u8, + pub rtm_index: u16, + pub rtm_flags: i32, + pub rtm_addrs: i32, + pub rtm_pid: libc::pid_t, + pub rtm_seq: i32, + pub rtm_errno: i32, + pub rtm_use: i32, + pub rtm_inits: u32, + pub rtm_rmx: rt_metrics, +} + +#[repr(C)] +pub struct rt_metrics { + pub rmx_locks: u32, /* Kernel must leave these values alone */ + pub rmx_mtu: u32, /* MTU for this path */ + pub rmx_hopcount: u32, /* max hops expected */ + pub rmx_expire: i32, /* lifetime for route, e.g. redirect */ + pub rmx_recvpipe: u32, /* inbound delay-bandwidth product */ + pub rmx_sendpipe: u32, /* outbound delay-bandwidth product */ + pub rmx_ssthresh: u32, /* outbound gateway buffer limit */ + pub rmx_rtt: u32, /* estimated round trip time */ + pub rmx_rttvar: u32, /* estimated rtt variance */ + pub rmx_pksent: u32, /* packets sent using this route */ + pub rmx_filler: [u32; 4], /* will be used for T/TCP later */ +} diff --git a/src/platform/macos/tun.rs b/src/platform/macos/tun.rs new file mode 100644 index 00000000..243e1e9b --- /dev/null +++ b/src/platform/macos/tun.rs @@ -0,0 +1,288 @@ +use crate::{ + plt::{fd::Fd, sys::*}, + tun::*, +}; +use std::{ + fmt, + fs::File, + io::{self, Read, Write}, + mem, + os::unix::io::FromRawFd, +}; + +pub const UTUN_CONTROL_NAME: &[u8] = b"com.apple.net.utun_control"; + +use libc::{socklen_t, IFNAMSIZ}; + +#[derive(Debug)] +pub enum MacosTunError { + InvalidName, + Open(io::Error), + CtliocginfoError(io::Error), + Connect(io::Error), + GetName(io::Error), + TunStatusError(StatusError), +} + +impl MacosTunError { + fn last_os_error(kind: impl Fn(io::Error) -> Self) -> Self { + kind(io::Error::last_os_error()) + } +} + +impl fmt::Display for MacosTunError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use MacosTunError::*; + match self { + InvalidName => write!(f, "Interface name must be utun[0-9]*"), + Open(err) => write!(f, "failed to open tunnel socket: {}", err), + CtliocginfoError(err) => write!(f, "failed configure socket for utun: {}", err), + Connect(err) => write!(f, "failed to connect tunnel socket: {}", err), + GetName(err) => write!(f, "failed to get tunnel name: {}", err), + TunStatusError(err) => write!(f, "failed to create tunnel status reader: {}", err), + } + } +} + +impl std::error::Error for MacosTunError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use MacosTunError::*; + match self { + Open(err) | CtliocginfoError(err) | Connect(err) | GetName(err) => Some(err), + TunStatusError(err) => Some(err), + InvalidName => None, + } + } +} + +impl From for MacosTunError { + fn from(err: StatusError) -> Self { + Self::TunStatusError(err) + } +} + +#[derive(Debug)] +pub enum StatusError { + GetInterfaceIndex(io::Error), + Open(io::Error), + Read(io::Error), +} + +impl StatusError { + fn last_os_error(kind: impl Fn(io::Error) -> Self) -> Self { + kind(io::Error::last_os_error()) + } +} + +impl fmt::Display for StatusError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use StatusError::*; + match self { + GetInterfaceIndex(err) => { + write!(f, "failed to get interface index: {}", err) + } + Open(err) => { + write!(f, "failed to open route socket: {}", err) + } + Read(err) => { + write!(f, "failed to read from route socket: {}", err) + } + } + } +} + +impl std::error::Error for StatusError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use StatusError::*; + match self { + GetInterfaceIndex(err) | Open(err) | Read(err) => Some(err), + } + } +} + +pub struct MacosTun {} + +pub struct MacosTunStatus { + interface_index: u32, + route_socket: File, +} + +impl MacosTunStatus { + fn new(interface_name: [u8; libc::IFNAMSIZ]) -> Result { + let interface_index = unsafe { libc::if_nametoindex(interface_name.as_ptr() as _) }; + if interface_index == 0 { + return Err(StatusError::last_os_error(StatusError::GetInterfaceIndex)); + } + let route_socket_fd = + unsafe { libc::socket(libc::AF_ROUTE, libc::SOCK_RAW, libc::AF_UNSPEC) }; + if route_socket_fd < 0 { + return Err(StatusError::last_os_error(StatusError::Open)); + } + let route_socket = unsafe { File::from_raw_fd(route_socket_fd) }; + + Ok(Self { + interface_index, + route_socket, + }) + } +} +impl Status for MacosTunStatus { + type Error = StatusError; + + fn event(&mut self) -> Result { + let mut buffer = vec![0u8; page_size::get()]; + loop { + let route_read = self.route_socket.read(buffer.as_mut_slice()); + let bytes_read = match route_read { + Ok(bytes_read) => bytes_read, + Err(err) => { + if err.kind() == io::ErrorKind::Interrupted { + continue; + } + return Err(StatusError::Read(err)); + } + }; + + if bytes_read < mem::size_of::() + || bytes_read < mem::size_of::() + { + continue; + } + let msg_header: &rt_msghdr = unsafe { &*(buffer.as_ptr() as *const rt_msghdr) }; + if msg_header.rtm_type != libc::RTM_IFINFO as u8 { + continue; + } + + let if_msg: &libc::if_msghdr = unsafe { &*(buffer.as_ptr() as *const libc::if_msghdr) }; + if if_msg.ifm_index as u32 != self.interface_index { + continue; + } + if if_msg.ifm_flags & libc::IFF_UP == 0 { + return Ok(TunEvent::Down); + } + let mtu = if_msg.ifm_data.ifi_mtu; + return Ok(TunEvent::Up(mtu as usize)); + } + } +} +pub struct MacosTunWriter { + tun: Fd, +} + +impl Writer for MacosTunWriter { + type Error = io::Error; + fn write(&self, src: &[u8]) -> Result<(), Self::Error> { + let mut buf = vec![0u8; src.len() + 4]; + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x00; + + if src[0] >> 4 == 6 { + buf[3] = libc::AF_INET6 as u8; + } else { + buf[3] = libc::AF_INET as u8; + } + buf[4..].copy_from_slice(src); + + let _ = self.tun.write(&buf)?; + Ok(()) + } +} +pub struct MacosTunReader { + tun: Fd, +} + +impl Reader for MacosTunReader { + type Error = io::Error; + + fn read(&self, buf: &mut [u8], offset: usize) -> Result { + let bytes_read = self.tun.read(&mut buf[(offset.saturating_sub(4))..])?; + if bytes_read < 4 { + return Ok(0); + } + Ok(bytes_read - 4) + } +} + +impl Tun for MacosTun { + type Writer = MacosTunWriter; + type Reader = MacosTunReader; + type Error = MacosTunError; +} + +impl PlatformTun for MacosTun { + type Status = MacosTunStatus; + + fn create(name: &str) -> Result<(Vec, Self::Writer, Self::Status), Self::Error> { + if name.as_bytes().len() > IFNAMSIZ { + return Err(MacosTunError::InvalidName); + } + let name_index: u32 = name + .strip_prefix("utun") + .and_then(|index| index.parse().ok()) + .ok_or(MacosTunError::InvalidName)?; + + let tun_fd = + unsafe { libc::socket(libc::PF_SYSTEM, libc::SOCK_DGRAM, libc::SYSPROTO_CONTROL) }; + if tun_fd < 0 { + return Err(MacosTunError::last_os_error(MacosTunError::Open)); + } + let tun = Fd::new(tun_fd); + + let mut info = ctl_info { + ctl_id: 0, + ctl_name: [0; 96], + }; + (&mut info.ctl_name[..]) + .write(UTUN_CONTROL_NAME) + .expect("failed to control name into ctl_info buffer"); + + if unsafe { ctliocginfo(tun.raw_fd(), &mut info as *mut _ as *mut _) } < 0 { + return Err(MacosTunError::last_os_error( + MacosTunError::CtliocginfoError, + )); + } + + let addr = libc::sockaddr_ctl { + sc_id: info.ctl_id, + sc_len: mem::size_of::() as _, + sc_family: libc::AF_SYSTEM as u8, + ss_sysaddr: libc::AF_SYS_CONTROL as u16, + sc_unit: name_index + 1, + sc_reserved: [0; 5], + }; + + if unsafe { + libc::connect( + tun.raw_fd(), + &addr as *const libc::sockaddr_ctl as *const libc::sockaddr, + mem::size_of::() as socklen_t, + ) + } < 0 + { + return Err(MacosTunError::last_os_error(MacosTunError::Connect)); + } + + let mut interface_name = [0u8; libc::IFNAMSIZ]; + let mut name_len: socklen_t = libc::IFNAMSIZ as u32; + + if unsafe { + libc::getsockopt( + tun.raw_fd(), + libc::SYSPROTO_CONTROL, + libc::UTUN_OPT_IFNAME, + interface_name.as_mut_ptr() as *mut libc::c_void, + &mut name_len as *mut socklen_t, + ) + } < 0 + { + return Err(MacosTunError::last_os_error(MacosTunError::GetName)); + } + + Ok(( + vec![MacosTunReader { tun: tun.clone() }], + MacosTunWriter { tun }, + MacosTunStatus::new(interface_name)?, + )) + } +} diff --git a/src/platform/macos/udp.rs b/src/platform/macos/udp.rs new file mode 100644 index 00000000..5ceafc40 --- /dev/null +++ b/src/platform/macos/udp.rs @@ -0,0 +1,494 @@ +use super::super::udp::*; +use super::super::Endpoint; + +use std::fmt; +use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; +use std::os::unix::io::RawFd; + +use nix::sys::{ + socket::{ + bind, getsockname, recvmsg, sendmsg, setsockopt, socket, + sockopt::{Ipv4RecvDstAddr, Ipv4RecvIf, Ipv6RecvPacketInfo, ReuseAddr, ReusePort}, + AddressFamily, ControlMessage, ControlMessageOwned, InetAddr, IpAddr, MsgFlags, SockAddr, + SockFlag, SockProtocol, SockType, + }, + uio::IoVec, +}; +use std::sync::Arc; + +#[derive(Debug)] +pub struct UdpSocket { + socket: RawFd, + is_ipv4: bool, +} + +#[derive(Debug)] +pub enum UdpError { + OpenSocket(nix::Error), + SetSocketOpt(nix::Error), + GetSockName(nix::Error), + BindSocket(nix::Error), + SendMsg(nix::Error), + RecvMsg(nix::Error), + UnexpectedControlMessage(ControlMessageOwned), + NoControlMessage, + InvalidAddress(Option), + UnsupportedProtocol(&'static str), + InsufficientSourceInfo(Option, Option), +} + +impl std::fmt::Display for UdpError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use UdpError::*; + match self { + OpenSocket(err) => { + write!(f, "failed to open socket: {}", err) + } + SetSocketOpt(err) => { + write!(f, "failed to set socket option: {}", err) + } + GetSockName(err) => { + write!(f, "failed to get socket name: {}", err) + } + BindSocket(err) => { + write!(f, "failed to bind socket: {}", err) + } + SendMsg(err) => { + write!(f, "failed to send message: {}", err) + } + RecvMsg(err) => { + write!(f, "failed to receive message: {}", err) + } + InvalidAddress(Some(invalid_addr)) => { + write!(f, "expected socket address, got {}", invalid_addr) + } + InvalidAddress(None) => { + write!(f, "expected socket address") + } + UnexpectedControlMessage(unexpected_message) => { + write!( + f, + "received unexpected control message: {:?}", + unexpected_message + ) + } + NoControlMessage => { + write!(f, "received no control message") + } + UnsupportedProtocol(protocol) => { + write!(f, "unsupported protocol {}", protocol) + } + InsufficientSourceInfo(in_addr, if_index) => { + let mut faults = Vec::with_capacity(2); + if in_addr.is_none() { + faults.push("no address") + } + if if_index.is_none() { + faults.push("no reciving interface index") + } + write!(f, "received packet with {}", faults.join(" and ")) + } + } + } +} + +impl std::error::Error for UdpError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use UdpError::*; + match self { + OpenSocket(err) | SetSocketOpt(err) | GetSockName(err) | BindSocket(err) + | SendMsg(err) | RecvMsg(err) => Some(err), + UnexpectedControlMessage(_) + | NoControlMessage + | InvalidAddress(_) + | UnsupportedProtocol(_) + | InsufficientSourceInfo(_, _) => None, + } + } +} + +type Result = std::result::Result; + +impl UdpSocket { + fn bind(addr: impl Into, port: u16) -> Result<(u16, Self)> { + let ip_addr = addr.into(); + let addr_family = if ip_addr.is_ipv4() { + AddressFamily::Inet + } else { + AddressFamily::Inet6 + }; + let inet_addr = InetAddr::new(IpAddr::from_std(&ip_addr), port); + let socket_addr = SockAddr::new_inet(inet_addr); + + let socket: RawFd = socket( + addr_family, + SockType::Datagram, + SockFlag::empty(), + SockProtocol::Udp, + ) + .map_err(UdpError::OpenSocket)?; + + if ip_addr.is_ipv4() { + setsockopt(socket, Ipv4RecvDstAddr, &true).map_err(UdpError::SetSocketOpt)?; + setsockopt(socket, Ipv4RecvIf, &true).map_err(UdpError::SetSocketOpt)?; + } else { + setsockopt(socket, Ipv6RecvPacketInfo, &true).map_err(UdpError::SetSocketOpt)?; + } + + setsockopt(socket, ReuseAddr, &true).map_err(UdpError::SetSocketOpt)?; + setsockopt(socket, ReusePort, &true).map_err(UdpError::SetSocketOpt)?; + + bind(socket, &socket_addr).map_err(UdpError::BindSocket)?; + let bound_port = if port == 0 { + let sockaddr = getsockname(socket).map_err(UdpError::GetSockName)?; + Self::validate_sockaddr(Some(sockaddr))?.port() + } else { + port + }; + + Ok(( + bound_port, + Self { + socket, + is_ipv4: ip_addr.is_ipv4(), + }, + )) + } + + fn validate_sockaddr(addr: Option) -> Result { + match addr { + Some(SockAddr::Inet(inet)) => Ok(inet), + anything_else => Err(UdpError::InvalidAddress(anything_else)), + } + } + + fn send_to(&self, buf: &[u8], endpoint: &MacosEndpoint) -> Result { + let iov = [IoVec::from_slice(buf)]; + let packet_info = PacketInfo::new(endpoint); + let control_messages = [packet_info.control_message()]; + sendmsg( + self.socket, + &iov, + &control_messages, + MsgFlags::empty(), + Some(&SockAddr::new_inet(endpoint.destination())), + ) + .map_err(UdpError::SendMsg) + } + + fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, MacosEndpoint)> { + let iov = [IoVec::from_mut_slice(buf)]; + let mut control_messages_buffer = self.control_message_buffer(); + let msg = recvmsg( + self.socket, + &iov, + Some(&mut control_messages_buffer), + MsgFlags::empty(), + ) + .map_err(UdpError::RecvMsg)?; + + let endpoint = if self.is_ipv4 { + let mut destination_addr = None; + let mut if_index = None; + let src_addr_info = match msg.address { + Some(SockAddr::Inet(InetAddr::V4(sockaddr_in))) => sockaddr_in, + anything_else => { + return Err(UdpError::InvalidAddress(anything_else)); + } + }; + let control_messages = msg.cmsgs(); + for message in control_messages { + match message { + ControlMessageOwned::Ipv4RecvIf(if_sockaddr) => { + if_index = Some(if_sockaddr.sdl_index as u32); + } + ControlMessageOwned::Ipv4RecvDstAddr(in_addr) => { + destination_addr = Some(in_addr); + } + other => { + log::error!("received unexpected control message: {:?}", other); + continue; + } + } + } + match (destination_addr, if_index) { + (Some(incoming_destination), Some(src_if_index)) => MacosEndpoint::V4 { + destination: src_addr_info, + src_if_index: src_if_index, + src_addr: incoming_destination, + }, + (dest, if_index) => { + return Err(UdpError::InsufficientSourceInfo(dest, if_index)); + } + } + } else { + let src_addr_info = match msg.address { + Some(SockAddr::Inet(InetAddr::V6(inet_addr))) => inet_addr, + anything_else => { + return Err(UdpError::InvalidAddress(anything_else)); + } + }; + + let src_if_index = match msg.cmsgs().next() { + Some(ControlMessageOwned::Ipv6PacketInfo(packet_info)) => packet_info.ipi6_ifindex, + Some(any_other_cmsg) => { + return Err(UdpError::UnexpectedControlMessage(any_other_cmsg)); + } + None => { + return Err(UdpError::NoControlMessage); + } + }; + MacosEndpoint::V6 { + destination: src_addr_info, + src_if_index, + } + }; + Ok((msg.bytes, endpoint)) + } + + fn control_message_buffer(&self) -> Vec { + if self.is_ipv4 { + nix::cmsg_space![libc::in_addr, libc::sockaddr_dl] + } else { + nix::cmsg_space![libc::in6_pktinfo] + } + } +} + +impl Drop for UdpSocket { + fn drop(&mut self) { + log::debug!("macos udp, release fd (fd = {})", self.socket); + if let Err(err) = nix::unistd::close(self.socket) { + log::error!("failed to close UdpSocket {}", err); + } + } +} +enum PacketInfo { + V4(libc::in_pktinfo), + V6(libc::in6_pktinfo), +} + +impl PacketInfo { + fn new(endpoint: &MacosEndpoint) -> Self { + match endpoint { + MacosEndpoint::V4 { + destination, + src_if_index, + src_addr, + } => Self::V4(libc::in_pktinfo { + ipi_addr: destination.sin_addr, + ipi_ifindex: *src_if_index, + ipi_spec_dst: *src_addr, + }), + MacosEndpoint::V6 { + destination, + src_if_index, + } => Self::V6(libc::in6_pktinfo { + ipi6_addr: destination.sin6_addr, + ipi6_ifindex: *src_if_index, + }), + } + } + + fn control_message<'a>(&'a self) -> ControlMessage<'a> { + match self { + Self::V4(v4) => ControlMessage::Ipv4PacketInfo(v4), + Self::V6(v6) => ControlMessage::Ipv6PacketInfo(v6), + } + } +} + +pub struct MacosUDP(); + +pub struct MacosOwner { + port: u16, + _sock4: Option>, + _sock6: Option>, +} + +impl Owner for MacosOwner { + type Error = UdpError; + + fn get_port(&self) -> u16 { + self.port + } + + fn set_fwmark(&mut self, _value: Option) -> Result<()> { + Ok(()) + } +} + +pub enum MacosUDPReader { + V4(Arc), + V6(Arc), +} + +impl AsRef for MacosUDPReader { + fn as_ref(&self) -> &UdpSocket { + match self { + Self::V4(socket) | Self::V6(socket) => &*socket, + } + } +} + +#[derive(Clone)] +pub struct MacosUDPWriter { + sock4: Option>, + sock6: Option>, +} + +#[derive(Debug)] +pub enum MacosEndpoint { + V4 { + destination: libc::sockaddr_in, + src_if_index: u32, + src_addr: libc::in_addr, + }, + V6 { + destination: libc::sockaddr_in6, + src_if_index: u32, + }, +} + +impl MacosEndpoint { + fn destination(&self) -> InetAddr { + match self { + Self::V4 { destination, .. } => InetAddr::V4(*destination), + Self::V6 { destination, .. } => InetAddr::V6(*destination), + } + } + fn is_ipv4(&self) -> bool { + match self { + Self::V4 { .. } => true, + Self::V6 { .. } => false, + } + } +} + +impl Endpoint for MacosEndpoint { + fn from_address(addr: SocketAddr) -> Self { + let sock_addr = InetAddr::from_std(&addr); + match sock_addr { + InetAddr::V4(destination) => Self::V4 { + destination, + src_if_index: 0, + src_addr: libc::in_addr { s_addr: 0u32 }, + }, + InetAddr::V6(destination) => Self::V6 { + destination, + src_if_index: 0, + }, + } + } + + fn clear_src(&mut self) { + match self { + Self::V4 { + ref mut src_if_index, + ref mut src_addr, + .. + } => { + *src_if_index = 0; + *src_addr = libc::in_addr { s_addr: 0u32 }; + } + Self::V6 { + ref mut src_if_index, + .. + } => { + *src_if_index = 0; + } + } + } + + fn into_address(&self) -> SocketAddr { + self.destination().to_std() + } +} + +impl Reader for MacosUDPReader { + type Error = UdpError; + + fn read(&self, buf: &mut [u8]) -> Result<(usize, MacosEndpoint)> { + self.as_ref().recv_from(buf) + } +} + +impl Writer for MacosUDPWriter { + type Error = UdpError; + + fn write(&self, buf: &[u8], dst: &mut MacosEndpoint) -> Result<()> { + let maybe_socket = if dst.is_ipv4() { + &self.sock4 + } else { + &self.sock6 + }; + + let socket = + maybe_socket + .as_ref() + .ok_or(UdpError::UnsupportedProtocol(if dst.is_ipv4() { + "ipv4" + } else { + "ipv6" + }))?; + + let _ = socket.send_to(buf, dst)?; + Ok(()) + } +} + +impl UDP for MacosUDP { + type Error = UdpError; + type Endpoint = MacosEndpoint; + type Writer = MacosUDPWriter; + type Reader = MacosUDPReader; +} + +impl MacosUDP {} + +impl PlatformUDP for MacosUDP { + type Owner = MacosOwner; + + #[allow(clippy::type_complexity)] + #[allow(clippy::unnecessary_unwrap)] + fn bind(mut port: u16) -> Result<(Vec, Self::Writer, Self::Owner)> { + log::trace!("binding to port {}", port); + + let bind6 = UdpSocket::bind(Ipv6Addr::UNSPECIFIED, port); + if let Ok((new_port, _)) = bind6 { + port = new_port; + } + + let bind4 = UdpSocket::bind(Ipv4Addr::UNSPECIFIED, port); + if let Ok((new_port, _)) = bind4 { + port = new_port; + } + + if bind4.is_err() && bind6.is_err() { + log::trace!("failed to bind for either IP version"); + return Err(bind6.unwrap_err()); + } + + let sock6 = bind6.ok().map(|(_, socket)| Arc::new(socket)); + let sock4 = bind4.ok().map(|(_, socket)| Arc::new(socket)); + + let owner = MacosOwner { + port, + _sock6: sock6.clone(), + _sock4: sock4.clone(), + }; + + let mut readers: Vec = Vec::with_capacity(2); + if let Some(sock) = sock6.clone() { + readers.push(MacosUDPReader::V6(sock)) + } + if let Some(sock) = sock4.clone() { + readers.push(MacosUDPReader::V4(sock)) + } + debug_assert!(!readers.is_empty()); + + let writer = MacosUDPWriter { sock4, sock6 }; + + Ok((readers, writer, owner)) + } +} diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 6b8fa0e5..d77e85fc 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -7,10 +7,14 @@ pub mod udp; pub use endpoint::Endpoint; #[cfg(target_os = "linux")] -pub mod linux; +#[path = "linux/mod.rs"] +pub use linux as plt; + +#[cfg(target_os = "macos")] +#[path = "macos/mod.rs"] +pub mod plt; + +pub(crate) mod unix; #[cfg(test)] pub mod dummy; - -#[cfg(target_os = "linux")] -pub use linux as plt; diff --git a/src/platform/unix/mod.rs b/src/platform/unix/mod.rs new file mode 100644 index 00000000..9c870737 --- /dev/null +++ b/src/platform/unix/mod.rs @@ -0,0 +1 @@ +pub mod uapi; diff --git a/src/platform/unix/uapi.rs b/src/platform/unix/uapi.rs new file mode 100644 index 00000000..1210f7b8 --- /dev/null +++ b/src/platform/unix/uapi.rs @@ -0,0 +1,31 @@ +use crate::platform::uapi::*; + +use std::fs; +use std::io; +use std::os::unix::net::{UnixListener, UnixStream}; + +const SOCK_DIR: &str = "/var/run/wireguard/"; + +pub struct UnixUAPI {} + +impl PlatformUAPI for UnixUAPI { + type Error = io::Error; + type Bind = UnixListener; + + fn bind(name: &str) -> Result { + let socket_path = format!("{}{}.sock", SOCK_DIR, name); + let _ = fs::create_dir_all(SOCK_DIR); + let _ = fs::remove_file(&socket_path); + UnixListener::bind(socket_path) + } +} + +impl BindUAPI for UnixListener { + type Stream = UnixStream; + type Error = io::Error; + + fn connect(&self) -> Result { + let (stream, _) = self.accept()?; + Ok(stream) + } +} diff --git a/src/wireguard/handshake/macs.rs b/src/wireguard/handshake/macs.rs index f4f55864..2eaffb3a 100644 --- a/src/wireguard/handshake/macs.rs +++ b/src/wireguard/handshake/macs.rs @@ -181,7 +181,16 @@ impl Generator { struct Secret { value: [u8; 32], - birth: Instant, + birth: Option, +} + +impl Secret { + fn is_still_valid(&self) -> bool { + match self.birth { + Some(birth) => birth.elapsed() < COOKIE_UPDATE_INTERVAL, + None => false, + } + } } pub struct Validator { @@ -197,14 +206,15 @@ impl Validator { cookie_key: HASH!(LABEL_COOKIE, pk.as_bytes()).into(), secret: RwLock::new(Secret { value: [0u8; SIZE_SECRET], - birth: Instant::now() - Duration::new(86400, 0), + birth: None, }), } } fn get_tau(&self, src: &[u8]) -> Option<[u8; SIZE_COOKIE]> { let secret = self.secret.read(); - if secret.birth.elapsed() < COOKIE_UPDATE_INTERVAL { + if secret.is_still_valid() + { Some(MAC!(&secret.value, src)) } else { None @@ -215,7 +225,7 @@ impl Validator { // check if current value is still valid { let secret = self.secret.read(); - if secret.birth.elapsed() < COOKIE_UPDATE_INTERVAL { + if secret.is_still_valid() { return MAC!(&secret.value, src); }; } @@ -223,13 +233,13 @@ impl Validator { // take write lock, check again { let mut secret = self.secret.write(); - if secret.birth.elapsed() < COOKIE_UPDATE_INTERVAL { + if secret.is_still_valid() { return MAC!(&secret.value, src); }; // set new random cookie secret rng.fill_bytes(&mut secret.value); - secret.birth = Instant::now(); + secret.birth = Some(Instant::now()); MAC!(&secret.value, src) } }