From bf482e06ea88123d56bd6e8a7e72928d693c5eeb Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Thu, 14 Oct 2021 21:02:51 -0400 Subject: [PATCH] Update a bunch of service code in keeping with new Rust core, and remove osdep stuff in favor of the libc crate. --- zerotier-network-hypervisor/src/vl2/mod.rs | 3 + .../src/vl2/multicastgroup.rs | 53 ++ zerotier-system-service/Cargo.lock | 465 +++++++++++++++++- zerotier-system-service/Cargo.toml | 5 +- zerotier-system-service/build.rs | 15 - zerotier-system-service/src/getifaddrs.rs | 32 +- zerotier-system-service/src/main.rs | 2 +- zerotier-system-service/src/vnic/common.rs | 49 +- .../src/vnic/mac_feth_tap.rs | 445 ++++++++++++++--- zerotier-system-service/src/vnic/vnic.rs | 6 +- 10 files changed, 946 insertions(+), 129 deletions(-) create mode 100644 zerotier-network-hypervisor/src/vl2/multicastgroup.rs delete mode 100644 zerotier-system-service/build.rs diff --git a/zerotier-network-hypervisor/src/vl2/mod.rs b/zerotier-network-hypervisor/src/vl2/mod.rs index e69de29bb..5e1f289e4 100644 --- a/zerotier-network-hypervisor/src/vl2/mod.rs +++ b/zerotier-network-hypervisor/src/vl2/mod.rs @@ -0,0 +1,3 @@ +mod multicastgroup; + +pub use multicastgroup::MulticastGroup; diff --git a/zerotier-network-hypervisor/src/vl2/multicastgroup.rs b/zerotier-network-hypervisor/src/vl2/multicastgroup.rs new file mode 100644 index 000000000..01f20940b --- /dev/null +++ b/zerotier-network-hypervisor/src/vl2/multicastgroup.rs @@ -0,0 +1,53 @@ +use crate::vl1::MAC; +use std::cmp::Ordering; +use std::hash::{Hash, Hasher}; + +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct MulticastGroup { + pub mac: MAC, + pub adi: u32, +} + +impl From<&MAC> for MulticastGroup { + #[inline(always)] + fn from(mac: &MAC) -> Self { + Self { + mac: mac.clone(), + adi: 0, + } + } +} + +impl From for MulticastGroup { + #[inline(always)] + fn from(mac: MAC) -> Self { + Self { + mac, + adi: 0, + } + } +} + +impl Ord for MulticastGroup { + #[inline(always)] + fn cmp(&self, other: &Self) -> Ordering { + let o = self.mac.cmp(&other.mac); + match o { + Ordering::Equal => self.adi.cmp(&other.adi), + _ => o + } + } +} + +impl PartialOrd for MulticastGroup { + #[inline(always)] + fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } +} + +impl Hash for MulticastGroup { + #[inline(always)] + fn hash(&self, state: &mut H) { + state.write_u64(self.mac.to_u64()); + state.write_u32(self.adi); + } +} diff --git a/zerotier-system-service/Cargo.lock b/zerotier-system-service/Cargo.lock index 5215bbf87..2e070e568 100644 --- a/zerotier-system-service/Cargo.lock +++ b/zerotier-system-service/Cargo.lock @@ -2,6 +2,14 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aes-gmac-siv" +version = "0.1.0" +dependencies = [ + "gcrypt", + "openssl", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -28,6 +36,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "bitflags" version = "1.3.2" @@ -43,12 +57,30 @@ dependencies = [ "generic-array", ] +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "cc" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -95,6 +127,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "concat-arrays" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df715824eb382e34b7afb7463b0247bf41538aeba731fba05241ecdb5dc3747" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "console" version = "0.15.0" @@ -119,6 +162,39 @@ dependencies = [ "libc", ] +[[package]] +name = "cstr-argument" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bd9c8e659a473bce955ae5c35b116af38af11a7acb0b480e01f3ed348aeb40" +dependencies = [ + "cfg-if 1.0.0", + "memchr", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "dashmap" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c" +dependencies = [ + "cfg-if 1.0.0", + "num_cpus", +] + [[package]] name = "dialoguer" version = "0.9.0" @@ -149,10 +225,33 @@ dependencies = [ "digest", "hex", "md-5", - "rand", + "rand 0.8.4", "sha2", ] +[[package]] +name = "ed25519" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4620d40f6d2601794401d6dd95a5cf69b6c157852539470eeda433a99b3c0efc" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand 0.7.3", + "serde", + "sha2", + "zeroize", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -165,6 +264,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "futures" version = "0.3.17" @@ -259,6 +373,20 @@ dependencies = [ "slab", ] +[[package]] +name = "gcrypt" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2ee79dcb8915fc0e9d8364e87d2215555076aa159d0a5d84ba9dba109b0d59" +dependencies = [ + "bitflags", + "cstr-argument", + "gpg-error", + "libc", + "libgcrypt-sys", + "once_cell", +] + [[package]] name = "generic-array" version = "0.14.4" @@ -269,15 +397,35 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.10.2+wasi-snapshot-preview1", +] + +[[package]] +name = "gpg-error" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7073b9ac823434ae73608715086e944d694a7ce2677371b8c5253300d1f767f1" +dependencies = [ + "libgpg-error-sys", ] [[package]] @@ -352,6 +500,15 @@ dependencies = [ "want", ] +[[package]] +name = "instant" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "itoa" version = "0.4.8" @@ -370,13 +527,53 @@ version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +[[package]] +name = "libgcrypt-sys" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62eb5d6d9cd6d8c8adf9641c95b223eb14f07a7a81c082e2d08f0bf3880214e4" +dependencies = [ + "cc", + "cfg-if 0.1.10", + "libc", + "libgpg-error-sys", +] + +[[package]] +name = "libgpg-error-sys" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1aedf0efc5d25fdd08eb52b0759c71d02ac77fd1879b96e95211239528897" +dependencies = [ + "libc", + "winreg", +] + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", +] + +[[package]] +name = "lz4_flex" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177c079243f6867429aca5af5053747f57e329d44f0c58bebca078cd14873ec2" +dependencies = [ + "twox-hash", ] [[package]] @@ -479,6 +676,58 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "openssl" +version = "0.10.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell", + "openssl-sys", +] + +[[package]] +name = "openssl-sys" +version = "0.9.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + [[package]] name = "pin-project-lite" version = "0.2.7" @@ -491,6 +740,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" + [[package]] name = "ppv-lite86" version = "0.2.14" @@ -527,6 +782,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "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.4" @@ -534,9 +802,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" dependencies = [ "libc", - "rand_chacha", - "rand_core", - "rand_hc", + "rand_chacha 0.3.1", + "rand_core 0.6.3", + "rand_hc 0.3.1", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", ] [[package]] @@ -546,7 +824,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.3", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", ] [[package]] @@ -555,7 +842,16 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom", + "getrandom 0.2.3", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -564,7 +860,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" dependencies = [ - "rand_core", + "rand_core 0.6.3", ] [[package]] @@ -606,6 +902,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.130" @@ -644,7 +946,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer", - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", "opaque-debug", @@ -659,19 +961,31 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19772be3c4dd2ceaacf03cb41d5885f2a02c4d8804884918e3a258480803335" + [[package]] name = "slab" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + [[package]] name = "socket2" version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "winapi", ] @@ -686,12 +1000,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.80" @@ -703,15 +1029,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "tempfile" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "rand", + "rand 0.8.4", "redox_syscall", "remove_dir_all", "winapi", @@ -796,7 +1134,7 @@ version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "pin-project-lite", "tracing-core", ] @@ -816,6 +1154,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "twox-hash" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f559b464de2e2bdabcac6a210d12e9b5a5973c251e102c44c585c71d51bd78e" +dependencies = [ + "cfg-if 1.0.0", + "static_assertions", +] + [[package]] name = "typenum" version = "1.14.0" @@ -834,6 +1182,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "urlencoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b90931029ab9b034b300b797048cf23723400aa757e8a2bfb9d748102f9821" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" @@ -856,6 +1216,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +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" @@ -885,10 +1251,71 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "zeroize" -version = "1.4.2" +name = "winreg" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf68b08513768deaa790264a7fac27a58cbf2705cfcdc9448362229217d7e970" +checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +dependencies = [ + "winapi", +] + +[[package]] +name = "x25519-dalek" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2392b6b94a576b4e2bf3c5b2757d63f10ada8020a2e4d08ac849ebcf6ea8e077" +dependencies = [ + "curve25519-dalek", + "rand_core 0.5.1", + "zeroize", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotier-core-crypto" +version = "0.1.0" +dependencies = [ + "aes-gmac-siv", + "ed25519-dalek", + "gcrypt", + "rand_core 0.6.3", + "x25519-dalek", +] + +[[package]] +name = "zerotier-network-hypervisor" +version = "2.0.0" +dependencies = [ + "base64", + "concat-arrays", + "dashmap", + "libc", + "lz4_flex", + "parking_lot", + "urlencoding", + "winapi", + "zerotier-core-crypto", +] [[package]] name = "zerotier-system-service" @@ -902,6 +1329,7 @@ dependencies = [ "futures", "hyper", "lazy_static", + "libc", "num-derive", "num-traits", "num_cpus", @@ -910,4 +1338,5 @@ dependencies = [ "socket2 0.3.19", "tokio", "winapi", + "zerotier-network-hypervisor", ] diff --git a/zerotier-system-service/Cargo.toml b/zerotier-system-service/Cargo.toml index 9a95560f0..82ed0f8c4 100644 --- a/zerotier-system-service/Cargo.toml +++ b/zerotier-system-service/Cargo.toml @@ -3,7 +3,6 @@ name = "zerotier-system-service" version = "0.1.0" authors = ["Adam Ierymenko "] edition = "2018" -build = "build.rs" [profile.release] opt-level = 'z' @@ -12,6 +11,7 @@ codegen-units = 1 panic = 'abort' [dependencies] +zerotier-network-hypervisor = { path = "../zerotier-network-hypervisor" } num_cpus = "^1" tokio = { version = "1", features = ["rt", "net", "time", "signal", "macros"] } serde = { version = "1", features = ["derive"] } @@ -30,3 +30,6 @@ colored = "^2" [target."cfg(windows)".dependencies] winapi = { version = "^0", features = ["handleapi", "ws2ipdef", "ws2tcpip"] } + +[target."cfg(not(windows))".dependencies] +libc = "^0" diff --git a/zerotier-system-service/build.rs b/zerotier-system-service/build.rs deleted file mode 100644 index d71096be8..000000000 --- a/zerotier-system-service/build.rs +++ /dev/null @@ -1,15 +0,0 @@ -#[allow(unused_assignments)] -#[allow(unused_mut)] -fn main() { - let d = env!("CARGO_MANIFEST_DIR"); - println!("cargo:rustc-link-search=native={}/../build/core", d); - println!("cargo:rustc-link-search=native={}/../build/osdep", d); - println!("cargo:rustc-link-lib=static=zt_core"); - println!("cargo:rustc-link-lib=static=zt_osdep"); - - let mut cpplib = "c++"; - #[cfg(target_os = "linux")] { - cpplib = "stdc++"; - } - println!("cargo:rustc-link-lib={}", cpplib); -} diff --git a/zerotier-system-service/src/getifaddrs.rs b/zerotier-system-service/src/getifaddrs.rs index 6309a3d0b..f95c7c044 100644 --- a/zerotier-system-service/src/getifaddrs.rs +++ b/zerotier-system-service/src/getifaddrs.rs @@ -14,9 +14,7 @@ use std::mem::size_of; use std::ptr::{copy_nonoverlapping, null_mut}; -use zerotier_core::InetAddress; - -use crate::osdep as osdep; +use zerotier_network_hypervisor::vl1::InetAddress; fn s6_addr_as_ptr(a: &A) -> *const A { a as *const A @@ -26,19 +24,19 @@ fn s6_addr_as_ptr(a: &A) -> *const A { #[cfg(unix)] pub(crate) fn for_each_address(mut f: F) { unsafe { - let mut ifa_name = [0_u8; osdep::IFNAMSIZ as usize]; - let mut ifap: *mut osdep::ifaddrs = null_mut(); - if osdep::getifaddrs((&mut ifap as *mut *mut osdep::ifaddrs).cast()) == 0 { + let mut ifa_name = [0_u8; libc::IFNAMSIZ as usize]; + let mut ifap: *mut libc::ifaddrs = null_mut(); + if libc::getifaddrs((&mut ifap as *mut *mut libc::ifaddrs).cast()) == 0 { let mut i = ifap; while !i.is_null() { if !(*i).ifa_addr.is_null() { let mut a = InetAddress::new(); let sa_family = (*(*i).ifa_addr).sa_family as u8; - if sa_family == osdep::AF_INET as u8 { - copy_nonoverlapping((*i).ifa_addr.cast::(), (&mut a as *mut InetAddress).cast::(), size_of::()); - } else if sa_family == osdep::AF_INET6 as u8 { - copy_nonoverlapping((*i).ifa_addr.cast::(), (&mut a as *mut InetAddress).cast::(), size_of::()); + if sa_family == libc::AF_INET as u8 { + copy_nonoverlapping((*i).ifa_addr.cast::(), (&mut a as *mut InetAddress).cast::(), size_of::()); + } else if sa_family == libc::AF_INET6 as u8 { + copy_nonoverlapping((*i).ifa_addr.cast::(), (&mut a as *mut InetAddress).cast::(), size_of::()); } else { i = (*i).ifa_next; continue; @@ -46,11 +44,11 @@ pub(crate) fn for_each_address(mut f: F) { let mut netmask_bits: u16 = 0; if !(*i).ifa_netmask.is_null() { - if sa_family == osdep::AF_INET as u8 { - let a = (*(*i).ifa_netmask.cast::()).sin_addr.s_addr as u32; + if sa_family == libc::AF_INET as u8 { + let a = (*(*i).ifa_netmask.cast::()).sin_addr.s_addr as u32; netmask_bits = a.leading_ones() as u16; - } else if sa_family == osdep::AF_INET6 as u8 { - let a = s6_addr_as_ptr(&((*(*i).ifa_netmask.cast::()).sin6_addr)).cast::(); + } else if sa_family == libc::AF_INET6 as u8 { + let a = s6_addr_as_ptr(&((*(*i).ifa_netmask.cast::()).sin6_addr)).cast::(); for i in 0..16 as isize { let b = *a.offset(i); if b == 0xff { @@ -65,7 +63,7 @@ pub(crate) fn for_each_address(mut f: F) { a.set_port(netmask_bits); let mut namlen: usize = 0; - while namlen < (osdep::IFNAMSIZ as usize) { + while namlen < (libc::IFNAMSIZ as usize) { let c = *(*i).ifa_name.offset(namlen as isize); if c != 0 { ifa_name[namlen] = c as u8; @@ -83,14 +81,14 @@ pub(crate) fn for_each_address(mut f: F) { } i = (*i).ifa_next; } - osdep::freeifaddrs(ifap.cast()); + libc::freeifaddrs(ifap.cast()); } } } #[cfg(test)] mod tests { - use zerotier_core::InetAddress; + use zerotier_network_hypervisor::vl1::InetAddress; #[test] fn test_getifaddrs() { diff --git a/zerotier-system-service/src/main.rs b/zerotier-system-service/src/main.rs index c064312c6..60939ebb3 100644 --- a/zerotier-system-service/src/main.rs +++ b/zerotier-system-service/src/main.rs @@ -92,7 +92,7 @@ Common Operations: Advanced Operations: service Start node - (usually not invoked directly) + (usually run by service manager) controller [option] ยท list List networks on controller diff --git a/zerotier-system-service/src/vnic/common.rs b/zerotier-system-service/src/vnic/common.rs index 4eb52ae83..c13115ae3 100644 --- a/zerotier-system-service/src/vnic/common.rs +++ b/zerotier-system-service/src/vnic/common.rs @@ -13,36 +13,51 @@ use std::collections::HashSet; -#[allow(unused_imports)] -use zerotier_core::{MAC, MulticastGroup}; - #[allow(unused_imports)] use num_traits::AsPrimitive; -/// BSD based OSes support getifmaddrs(). +#[allow(unused_imports)] +use std::os::raw::c_int; + +#[allow(unused_imports)] +use zerotier_network_hypervisor::vl1::MAC; + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly", target_os = "freebsd", target_os = "darwin"))] -pub(crate) fn get_l2_multicast_subscriptions(dev: &str) -> HashSet { +#[allow(non_camel_case_types)] +#[repr(C)] +struct ifmaddrs { + ifma_next: *mut ifmaddrs, + ifma_name: *mut libc::sockaddr, + ifma_addr: *mut libc::sockaddr, + ifma_lladdr: *mut libc::sockaddr, +} + +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly", target_os = "freebsd", target_os = "darwin"))] +extern "C" { + fn getifmaddrs(ifmap: *mut *mut ifmaddrs) -> c_int; + fn freeifmaddrs(ifmp: *mut ifmaddrs); +} + +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly", target_os = "freebsd", target_os = "darwin"))] +pub fn get_l2_multicast_subscriptions(dev: &str) -> HashSet { let mut groups: HashSet = HashSet::new(); let dev = dev.as_bytes(); unsafe { - let mut maddrs: *mut osdep::ifmaddrs = std::ptr::null_mut(); - if osdep::getifmaddrs(&mut maddrs as *mut *mut osdep::ifmaddrs) == 0 { + let mut maddrs: *mut ifmaddrs = std::ptr::null_mut(); + if getifmaddrs(&mut maddrs as *mut *mut ifmaddrs) == 0 { let mut i = maddrs; while !i.is_null() { - if !(*i).ifma_name.is_null() && !(*i).ifma_addr.is_null() && (*(*i).ifma_addr).sa_family as i32 == osdep::AF_LINK as i32 { - let in_: &osdep::sockaddr_dl = &*((*i).ifma_name.cast()); - let la: &osdep::sockaddr_dl = &*((*i).ifma_addr.cast()); - if la.sdl_alen == 6 && in_.sdl_nlen <= dev.len().as_() && crate::osdep::memcmp(dev.as_ptr().cast(), in_.sdl_data.as_ptr().cast(), in_.sdl_nlen.as_()) == 0 { + if !(*i).ifma_name.is_null() && !(*i).ifma_addr.is_null() && (*(*i).ifma_addr).sa_family as i32 == libc::AF_LINK as i32 { + let in_: &libc::sockaddr_dl = &*((*i).ifma_name.cast()); + let la: &libc::sockaddr_dl = &*((*i).ifma_addr.cast()); + if la.sdl_alen == 6 && in_.sdl_nlen <= dev.len().as_() && crate::libc::memcmp(dev.as_ptr().cast(), in_.sdl_data.as_ptr().cast(), in_.sdl_nlen.as_()) == 0 { let mi = la.sdl_nlen as usize; - groups.insert(MulticastGroup{ - mac: MAC((la.sdl_data[mi] as u64) << 40 | (la.sdl_data[mi+1] as u64) << 32 | (la.sdl_data[mi+2] as u64) << 24 | (la.sdl_data[mi+3] as u64) << 16 | (la.sdl_data[mi+4] as u64) << 8 | la.sdl_data[mi+5] as u64), - adi: 0, - }); + groups.insert(MAC::from_u64((la.sdl_data[mi] as u64) << 40 | (la.sdl_data[mi+1] as u64) << 32 | (la.sdl_data[mi+2] as u64) << 24 | (la.sdl_data[mi+3] as u64) << 16 | (la.sdl_data[mi+4] as u64) << 8 | la.sdl_data[mi+5] as u64)); } } i = (*i).ifma_next; } - osdep::freeifmaddrs(maddrs); + freeifmaddrs(maddrs); } } groups @@ -50,7 +65,7 @@ pub(crate) fn get_l2_multicast_subscriptions(dev: &str) -> HashSet HashSet { +pub fn get_l2_multicast_subscriptions(dev: &str) -> HashSet { let mut groups: HashSet = HashSet::new(); groups } diff --git a/zerotier-system-service/src/vnic/mac_feth_tap.rs b/zerotier-system-service/src/vnic/mac_feth_tap.rs index 3a54ffe3c..8cd7926e4 100644 --- a/zerotier-system-service/src/vnic/mac_feth_tap.rs +++ b/zerotier-system-service/src/vnic/mac_feth_tap.rs @@ -39,22 +39,21 @@ use std::cell::Cell; use std::collections::HashSet; use std::error::Error; use std::ffi::CString; -use std::ptr::{null_mut, copy_nonoverlapping}; use std::mem::{transmute, zeroed}; -use std::os::raw::{c_int, c_uchar, c_void}; +use std::os::raw::{c_char, c_int, c_short, c_uchar, c_uint, c_void}; use std::process::Command; +use std::ptr::{copy_nonoverlapping, null_mut}; use std::sync::Mutex; use std::thread::JoinHandle; use lazy_static::lazy_static; use num_traits::cast::AsPrimitive; -use zerotier_core::{InetAddress, MAC, MulticastGroup, NetworkId}; +use zerotier_network_hypervisor::vl1::{InetAddress, MAC}; -use crate::osdep as osdep; use crate::getifaddrs; use crate::vnic::vnic::VNIC; -use crate::osdep::getifmaddrs; +use zerotier_network_hypervisor::vl2::MulticastGroup; const BPF_BUFFER_SIZE: usize = 131072; const IFCONFIG: &'static str = "/sbin/ifconfig"; @@ -81,7 +80,7 @@ impl Drop for MacFethDevice { } } -pub(crate) struct MacFethTap { +pub struct MacFethTap { network_id: u64, device: MacFethDevice, ndrv_fd: c_int, @@ -104,26 +103,227 @@ lazy_static! { static ref MAC_FETH_BPF_DEVICES_USED: Mutex> = Mutex::new(BTreeSet::new()); } +/* +struct nd_ifinfo { + u_int32_t linkmtu; /* LinkMTU */ + u_int32_t maxmtu; /* Upper bound of LinkMTU */ + u_int32_t basereachable; /* BaseReachableTime */ + u_int32_t reachable; /* Reachable Time */ + u_int32_t retrans; /* Retrans Timer */ + u_int32_t flags; /* Flags */ + int recalctm; /* BaseReacable re-calculation timer */ + u_int8_t chlim; /* CurHopLimit */ + u_int8_t receivedra; +}; +struct in6_ndireq { + char ifname[IFNAMSIZ]; + struct nd_ifinfo ndi; +}; +struct in6_addrlifetime { + time_t ia6t_expire; /* valid lifetime expiration time */ + time_t ia6t_preferred; /* preferred lifetime expiration time */ + u_int32_t ia6t_vltime; /* valid lifetime */ + u_int32_t ia6t_pltime; /* prefix lifetime */ +}; +struct in6_ifstat { + ifs6_in_receive; /* # of total input datagram */ + ifs6_in_hdrerr; /* # of datagrams with invalid hdr */ + ifs6_in_toobig; /* # of datagrams exceeded MTU */ + ifs6_in_noroute; /* # of datagrams with no route */ + ifs6_in_addrerr; /* # of datagrams with invalid dst */ + ifs6_in_protounknown; /* # of datagrams with unknown proto */ + /* NOTE: increment on final dst if */ + ifs6_in_truncated; /* # of truncated datagrams */ + ifs6_in_discard; /* # of discarded datagrams */ + /* NOTE: fragment timeout is not here */ + ifs6_in_deliver; /* # of datagrams delivered to ULP */ + /* NOTE: increment on final dst if */ + ifs6_out_forward; /* # of datagrams forwarded */ + /* NOTE: increment on outgoing if */ + ifs6_out_request; /* # of outgoing datagrams from ULP */ + /* NOTE: does not include forwrads */ + ifs6_out_discard; /* # of discarded datagrams */ + ifs6_out_fragok; /* # of datagrams fragmented */ + ifs6_out_fragfail; /* # of datagrams failed on fragment */ + ifs6_out_fragcreat; /* # of fragment datagrams */ + /* NOTE: this is # after fragment */ + ifs6_reass_reqd; /* # of incoming fragmented packets */ + /* NOTE: increment on final dst if */ + ifs6_reass_ok; /* # of reassembled packets */ + /* NOTE: this is # after reass */ + /* NOTE: increment on final dst if */ + ifs6_atmfrag_rcvd; /* # of atomic fragments received */ + ifs6_reass_fail; /* # of reass failures */ + /* NOTE: may not be packet count */ + /* NOTE: increment on final dst if */ + ifs6_in_mcast; /* # of inbound multicast datagrams */ + ifs6_out_mcast; /* # of outbound multicast datagrams */ + + ifs6_cantfoward_icmp6; /* # of ICMPv6 packets received for unreachable dest */ + ifs6_addr_expiry_cnt; /* # of address expiry events (excluding privacy addresses) */ + ifs6_pfx_expiry_cnt; /* # of prefix expiry events */ + ifs6_defrtr_expiry_cnt; /* # of default router expiry events */ +}; +struct in6_ifreq { + char ifr_name[IFNAMSIZ]; + union { + struct sockaddr_in6 ifru_addr; + struct sockaddr_in6 ifru_dstaddr; + int ifru_flags; + int ifru_flags6; + int ifru_metric; + int ifru_intval; + caddr_t ifru_data; + struct in6_addrlifetime ifru_lifetime; + struct in6_ifstat ifru_stat; + struct icmp6_ifstat ifru_icmp6stat; + u_int32_t ifru_scope_id[SCOPE6_ID_MAX]; + } ifr_ifru; +}; +*/ + +#[allow(non_camel_case_types)] +#[repr(C)] +struct icmp6_ifstat { + ifs6_in_msg: u64, + ifs6_in_error: u64, + ifs6_in_dstunreach: u64, + ifs6_in_adminprohib: u64, + ifs6_in_timeexceed: u64, + ifs6_in_paramprob: u64, + ifs6_in_pkttoobig: u64, + ifs6_in_echo: u64, + ifs6_in_echoreply: u64, + ifs6_in_routersolicit: u64, + ifs6_in_routeradvert: u64, + ifs6_in_neighborsolicit: u64, + ifs6_in_neighboradvert: u64, + ifs6_in_redirect: u64, + ifs6_in_mldquery: u64, + ifs6_in_mldreport: u64, + ifs6_in_mlddone: u64, + ifs6_out_msg: u64, + ifs6_out_error: u64, + ifs6_out_dstunreach: u64, + ifs6_out_adminprohib: u64, + ifs6_out_timeexceed: u64, + ifs6_out_paramprob: u64, + ifs6_out_pkttoobig: u64, + ifs6_out_echo: u64, + ifs6_out_echoreply: u64, + ifs6_out_routersolicit: u64, + ifs6_out_routeradvert: u64, + ifs6_out_neighborsolicit: u64, + ifs6_out_neighboradvert: u64, + ifs6_out_redirect: u64, + ifs6_out_mldquery: u64, + ifs6_out_mldreport: u64, + ifs6_out_mlddone: u64, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct in6_ifstat { + ifs6_in_receive: u64, + ifs6_in_hdrerr: u64, + ifs6_in_toobig: u64, + ifs6_in_noroute: u64, + ifs6_in_addrerr: u64, + ifs6_in_protounknown: u64, + ifs6_in_truncated: u64, + ifs6_in_discard: u64, + ifs6_in_deliver: u64, + ifs6_out_forward: u64, + ifs6_out_request: u64, + ifs6_out_discard: u64, + ifs6_out_fragok: u64, + ifs6_out_fragfail: u64, + ifs6_out_fragcreat: u64, + ifs6_reass_reqd: u64, + ifs6_reass_ok: u64, + ifs6_atmfrag_rcvd: u64, + ifs6_reass_fail: u64, + ifs6_in_mcast: u64, + ifs6_out_mcast: u64, + ifs6_cantfoward_icmp6: u64, + ifs6_addr_expiry_cnt: u64, + ifs6_pfx_expiry_cnt: u64, + ifs6_defrtr_expiry_cnt: u64, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct in6_addrlifetime { + ia6t_expire: libc::time_t, + ia6t_preferred: libc::time_t, + ia6t_vltime: u32, + ia6t_pltime: u32, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +union u_ifr_ifru { + ifru_addr: libc::sockaddr_in6, + ifru_dstaddr: libc::sockaddr_in6, + ifru_flags: c_int, + ifru_flags6: c_int, + ifru_metric: c_int, + ifru_intval: c_int, + ifru_data: *mut c_void, + ifru_lifetime: in6_addrlifetime, + ifru_stat: in6_ifstat, + ifru_icmp6stat: icmp6_ifstat, + ifru_scope_id: [u32; 16 /* SCOPE6_ID_MAX */], +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct in6_ifreq { + ifr_name: [c_char; libc::IFNAMSIZ], + ifr_ifru: u_ifr_ifru, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct nd_ifinfo { + linkmtu: u32, + maxmtu: u32, + basereachable: u32, + reachable: u32, + retrans: u32, + flags: u32, + recalctm: c_int, + chlim: u8, + receivedra: u8, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct in6_ndireq { + ifname: [c_char; libc::IFNAMSIZ], + ndi: nd_ifinfo, +} + fn device_ipv6_set_params(device: &String, perform_nud: bool, accept_ra: bool) -> bool { let dev = device.as_bytes(); let mut ok = true; unsafe { - let s = osdep::socket(osdep::AF_INET6 as c_int, osdep::SOCK_DGRAM as c_int, 0); + let s = libc::socket(libc::AF_INET6 as c_int, libc::SOCK_DGRAM as c_int, 0); if s < 0 { return false; } - let mut nd: osdep::in6_ndireq = zeroed(); + let mut nd: in6_ndireq = zeroed(); copy_nonoverlapping(dev.as_ptr(), nd.ifname.as_mut_ptr().cast::(), if dev.len() > (nd.ifname.len() - 1) { nd.ifname.len() - 1 } else { dev.len() }); - if osdep::ioctl(s, osdep::c_SIOCGIFINFO_IN6, (&mut nd as *mut osdep::in6_ndireq).cast::()) == 0 { + if libc::ioctl(s, 76 /* SIOCGIFINFO_IN6 */, (&mut nd as *mut in6_ndireq).cast::()) == 0 { let oldflags = nd.ndi.flags; if perform_nud { - nd.ndi.flags |= osdep::ND6_IFF_PERFORMNUD as osdep::u_int32_t; + nd.ndi.flags |= 0x1 /* ND6_IFF_PERFORMNUD */; } else { - nd.ndi.flags &= !(osdep::ND6_IFF_PERFORMNUD as osdep::u_int32_t); + nd.ndi.flags &= !0x1 /* !ND6_IFF_PERFORMNUD */; } if nd.ndi.flags != oldflags { - if osdep::ioctl(s, osdep::c_SIOCSIFINFO_FLAGS, (&mut nd as *mut osdep::in6_ndireq).cast::()) != 0 { + if libc::ioctl(s, 87 /* SIOCSIFINFO_FLAGS */, (&mut nd as *mut in6_ndireq).cast::()) != 0 { ok = false; } } @@ -131,17 +331,144 @@ fn device_ipv6_set_params(device: &String, perform_nud: bool, accept_ra: bool) - ok = false; } - let mut ifr: osdep::in6_ifreq = zeroed(); + let mut ifr: in6_ifreq = zeroed(); copy_nonoverlapping(dev.as_ptr(), ifr.ifr_name.as_mut_ptr().cast::(), if dev.len() > (ifr.ifr_name.len() - 1) { ifr.ifr_name.len() - 1 } else { dev.len() }); - if osdep::ioctl(s, if accept_ra { osdep::c_SIOCAUTOCONF_START } else { osdep::c_SIOCAUTOCONF_STOP }, (&mut ifr as *mut osdep::in6_ifreq).cast::()) != 0 { + if libc::ioctl(s, if accept_ra { 132 /* SIOCAUTOCONF_START */ } else { 133 /* SIOCAUTOCONF_STOP */ }, (&mut ifr as *mut in6_ifreq).cast::()) != 0 { ok = false; } - osdep::close(s); + libc::close(s); } ok } +/* +struct ifkpi { + unsigned int ifk_module_id; + unsigned int ifk_type; + union { + void *ifk_ptr; + int ifk_value; + } ifk_data; +}; +struct ifdevmtu { + int ifdm_current; + int ifdm_min; + int ifdm_max; +}; +struct ifreq { +#ifndef IFNAMSIZ +#define IFNAMSIZ IF_NAMESIZE +#endif + char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + short ifru_flags; + int ifru_metric; + int ifru_mtu; + int ifru_phys; + int ifru_media; + int ifru_intval; + caddr_t ifru_data; + struct ifdevmtu ifru_devmtu; + struct ifkpi ifru_kpi; + u_int32_t ifru_wake_flags; + u_int32_t ifru_route_refcnt; + int ifru_cap[2]; + u_int32_t ifru_functional_type; +#define IFRTYPE_FUNCTIONAL_UNKNOWN 0 +#define IFRTYPE_FUNCTIONAL_LOOPBACK 1 +#define IFRTYPE_FUNCTIONAL_WIRED 2 +#define IFRTYPE_FUNCTIONAL_WIFI_INFRA 3 +#define IFRTYPE_FUNCTIONAL_WIFI_AWDL 4 +#define IFRTYPE_FUNCTIONAL_CELLULAR 5 +#define IFRTYPE_FUNCTIONAL_INTCOPROC 6 +#define IFRTYPE_FUNCTIONAL_COMPANIONLINK 7 +#define IFRTYPE_FUNCTIONAL_LAST 7 + } ifr_ifru; +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#ifdef __APPLE__ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#else +#define ifr_flags ifr_ifru.ifru_flags[0] /* flags */ +#define ifr_prevflags ifr_ifru.ifru_flags[1] /* flags */ +#endif /* __APPLE__ */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +#define ifr_phys ifr_ifru.ifru_phys /* physical wire */ +#define ifr_media ifr_ifru.ifru_media /* physical media */ +#define ifr_data ifr_ifru.ifru_data /* for use by interface */ +#define ifr_devmtu ifr_ifru.ifru_devmtu +#define ifr_intval ifr_ifru.ifru_intval /* integer value */ +#define ifr_kpi ifr_ifru.ifru_kpi +#define ifr_wake_flags ifr_ifru.ifru_wake_flags /* wake capabilities */ +#define ifr_route_refcnt ifr_ifru.ifru_route_refcnt /* route references count */ +#define ifr_reqcap ifr_ifru.ifru_cap[0] /* requested capabilities */ +#define ifr_curcap ifr_ifru.ifru_cap[1] /* current capabilities */ +}; +struct sockaddr_ndrv { + unsigned char snd_len; + unsigned char snd_family; + unsigned char snd_name[IFNAMSIZ]; /* from if.h */ +}; +*/ + +#[allow(non_camel_case_types)] +#[repr(C)] +struct ifkpi { + ifk_module_id: c_uint, + ifk_type: c_uint, + ifk_data: *mut c_void, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct ifdevmtu { + ifdm_current: c_int, + ifdm_min: c_int, + ifdm_max: c_int, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +union ifr_ifru { + ifru_addr: libc::sockaddr, + ifru_dstaddr: libc::sockaddr, + ifru_broadaddr: libc::sockaddr, + ifru_flags: c_short, + ifru_metric: c_int, + ifru_mtu: c_int, + ifru_phys: c_int, + ifru_media: c_int, + ifru_intval: c_int, + ifru_data: u64, + ifru_devmtu: ifdevmtu, + ifru_kpi: ifkpi, + ifru_wake_flags: u32, + ifru_route_refcnt: u32, + ifru_cap: [c_int; 2], + ifru_functional_type: u32, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct ifreq { + ifr_name: [c_char; libc::IFNAMSIZ], + ifr_ifru: ifr_ifru, +} + +#[allow(non_camel_case_types)] +#[repr(C)] +struct sockaddr_ndrv { + snd_len: c_uchar, + snd_family: c_uchar, + snd_name: [c_uchar; libc::IFNAMSIZ], +} + impl MacFethTap { /// Create a new MacFethTap with a function to call for Ethernet frames. /// The function F should return as quickly as possible. It should pass copies @@ -149,13 +476,13 @@ impl MacFethTap { /// given will not remain valid after it returns. Also note that F will be called /// from another thread that is spawned here, so all its bound references must /// be "Send" and "Sync" e.g. Arc<>. - pub(crate) fn new(nwid: &NetworkId, mac: &MAC, mtu: i32, metric: i32, eth_frame_func: F) -> Result { + pub fn new(nwid: &NetworkId, mac: &MAC, mtu: i32, metric: i32, eth_frame_func: F) -> Result { // This tracks BPF devices we are using so we don't try to reopen them, and also // doubles as a global lock to ensure that only one feth tap is created at once per // ZeroTier process per system. let mut bpf_devices_used = MAC_FETH_BPF_DEVICES_USED.lock().unwrap(); - if unsafe { osdep::getuid() } != 0 { + if unsafe { libc::getuid() } != 0 { return Err(String::from("ZeroTier MacFethTap must run as root")); } @@ -245,7 +572,7 @@ impl MacFethTap { } else { let bpf_dev = CString::new(format!("/dev/bpf{}", bpf_no)).unwrap(); let bpf_dev = bpf_dev.as_bytes_with_nul(); - bpf_fd = unsafe { osdep::open(bpf_dev.as_ptr().cast(), osdep::O_RDWR as c_int) }; + bpf_fd = unsafe { libc::open(bpf_dev.as_ptr().cast(), libc::O_RDWR as c_int) }; if bpf_fd >= 0 { break; } @@ -262,60 +589,60 @@ impl MacFethTap { // Set/get buffer length to use with reads from BPF device, trying to // use up to BPF_BUFFER_SIZE bytes. let mut fl: c_int = BPF_BUFFER_SIZE as c_int; - if unsafe { osdep::ioctl(bpf_fd as c_int, osdep::c_BIOCSBLEN, (&mut fl as *mut c_int).cast::()) } != 0 { - unsafe { osdep::close(bpf_fd); } + if unsafe { libc::ioctl(bpf_fd as c_int, 102 /* BIOCSBLEN */, (&mut fl as *mut c_int).cast::()) } != 0 { + unsafe { libc::close(bpf_fd); } return Err(String::from("unable to configure BPF device")); } - let bpf_read_size = fl as osdep::size_t; + let bpf_read_size = fl as libc::size_t; // Set immediate mode for "live" capture. fl = 1; - if unsafe { osdep::ioctl(bpf_fd as c_int, osdep::c_BIOCIMMEDIATE, (&mut fl as *mut c_int).cast::()) } != 0 { - unsafe { osdep::close(bpf_fd); } + if unsafe { libc::ioctl(bpf_fd as c_int, 112 /* BIOCIMMEDIATE */, (&mut fl as *mut c_int).cast::()) } != 0 { + unsafe { libc::close(bpf_fd); } return Err(String::from("unable to configure BPF device")); } // Do not send us back packets we inject or send. fl = 0; - if unsafe { osdep::ioctl(bpf_fd as c_int, osdep::c_BIOCSSEESENT, (&mut fl as *mut c_int).cast::()) } != 0 { - unsafe { osdep::close(bpf_fd); } + if unsafe { libc::ioctl(bpf_fd as c_int, 119 /* BIOCSSEESENT */, (&mut fl as *mut c_int).cast::()) } != 0 { + unsafe { libc::close(bpf_fd); } return Err(String::from("unable to configure BPF device")); } // Bind BPF to secondary feth device. - let mut bpf_ifr: osdep::ifreq = unsafe { std::mem::zeroed() }; + let mut bpf_ifr: ifreq = unsafe { std::mem::zeroed() }; let peer_dev_name_bytes = device.peer_name.as_bytes(); unsafe { copy_nonoverlapping(peer_dev_name_bytes.as_ptr(), bpf_ifr.ifr_name.as_mut_ptr().cast::(), if peer_dev_name_bytes.len() > (bpf_ifr.ifr_name.len() - 1) { bpf_ifr.ifr_name.len() - 1 } else { peer_dev_name_bytes.len() }); } - if unsafe { osdep::ioctl(bpf_fd as c_int, osdep::c_BIOCSETIF, (&mut bpf_ifr as *mut osdep::ifreq).cast::()) } != 0 { - unsafe { osdep::close(bpf_fd); } + if unsafe { libc::ioctl(bpf_fd as c_int, 108 /* BIOCSETIF */, (&mut bpf_ifr as *mut ifreq).cast::()) } != 0 { + unsafe { libc::close(bpf_fd); } return Err(String::from("unable to configure BPF device")); } // Include Ethernet header in BPF captures. fl = 1; - if unsafe { osdep::ioctl(bpf_fd as c_int, osdep::c_BIOCSHDRCMPLT, (&mut fl as *mut c_int).cast::()) } != 0 { - unsafe { osdep::close(bpf_fd); } + if unsafe { libc::ioctl(bpf_fd as c_int, 117 /* BIOCSHDRCMPLT */, (&mut fl as *mut c_int).cast::()) } != 0 { + unsafe { libc::close(bpf_fd); } return Err(String::from("unable to configure BPF device")); } // Set promiscuous mode so bridging can work. fl = 1; - if unsafe { osdep::ioctl(bpf_fd as c_int, osdep::c_BIOCPROMISC, (&mut fl as *mut c_int).cast::()) } != 0 { - unsafe { osdep::close(bpf_fd); } + if unsafe { libc::ioctl(bpf_fd as c_int, 105 /* BIOCPROMISC */, (&mut fl as *mut c_int).cast::()) } != 0 { + unsafe { libc::close(bpf_fd); } return Err(String::from("unable to configure BPF device")); } // Create BPF listener thread, which calls the supplied function on each incoming packet. let t = std::thread::Builder::new().stack_size(zerotier_core::RECOMMENDED_THREAD_STACK_SIZE).spawn(move || { let mut buf: [u8; BPF_BUFFER_SIZE] = [0_u8; BPF_BUFFER_SIZE]; - let hdr_struct_size = std::mem::size_of::() as isize; + let hdr_struct_size = std::mem::size_of::() as isize; loop { - let n = unsafe { osdep::read(bpf_fd, buf.as_mut_ptr().cast(), bpf_read_size) } as isize; + let n = unsafe { libc::read(bpf_fd, buf.as_mut_ptr().cast(), bpf_read_size) } as isize; if n >= 0 { let mut p: isize = 0; while (p + hdr_struct_size) < n { unsafe { - let h = buf.as_ptr().offset(p).cast::(); + let h = buf.as_ptr().offset(p).cast::(); let hdrlen = (*h).bh_hdrlen as isize; let caplen = (*h).bh_caplen as isize; let pktlen = hdrlen + caplen; @@ -331,30 +658,30 @@ impl MacFethTap { } }); if t.is_err() { - unsafe { osdep::close(bpf_fd); } + unsafe { libc::close(bpf_fd); } return Err(String::from("unable to start thread")); } // Create AF_NDRV socket used to inject packets. We could inject with BPF but that has // a hard MTU limit of 2048 so we have to use AF_NDRV instead. Performance is probably // the same, but it means another socket. - let ndrv_fd = unsafe { osdep::socket(osdep::AF_NDRV as c_int, osdep::SOCK_RAW as c_int, 0) }; + let ndrv_fd = unsafe { libc::socket(27 /* AF_NDRV */, libc::SOCK_RAW, 0) }; if ndrv_fd < 0 { - unsafe { osdep::close(bpf_fd); } + unsafe { libc::close(bpf_fd); } return Err(String::from("unable to create AF_NDRV socket")); } - let mut ndrv_sa: osdep::sockaddr_ndrv = unsafe { std::mem::zeroed() }; - ndrv_sa.snd_len = std::mem::size_of::() as c_uchar; - ndrv_sa.snd_family = osdep::AF_NDRV as c_uchar; + let mut ndrv_sa: sockaddr_ndrv = unsafe { std::mem::zeroed() }; + ndrv_sa.snd_len = std::mem::size_of::() as c_uchar; + ndrv_sa.snd_family = 27 /* AF_NDRV */; unsafe { copy_nonoverlapping(peer_dev_name_bytes.as_ptr(), ndrv_sa.snd_name.as_mut_ptr().cast::(), if peer_dev_name_bytes.len() > (bpf_ifr.ifr_name.len() - 1) { bpf_ifr.ifr_name.len() - 1 } else { peer_dev_name_bytes.len() }); } - if unsafe { osdep::bind(ndrv_fd, (&ndrv_sa as *const osdep::sockaddr_ndrv).cast(), std::mem::size_of::() as osdep::socklen_t) } != 0 { - unsafe { osdep::close(bpf_fd); } - unsafe { osdep::close(ndrv_fd); } + if unsafe { libc::bind(ndrv_fd, (&ndrv_sa as *const sockaddr_ndrv).cast(), std::mem::size_of::() as libc::socklen_t) } != 0 { + unsafe { libc::close(bpf_fd); } + unsafe { libc::close(ndrv_fd); } return Err(String::from("unable to bind AF_NDRV socket")); } - if unsafe { osdep::connect(ndrv_fd, (&ndrv_sa as *const osdep::sockaddr_ndrv).cast(), std::mem::size_of::() as osdep::socklen_t) } != 0 { - unsafe { osdep::close(bpf_fd); } - unsafe { osdep::close(ndrv_fd); } + if unsafe { libc::connect(ndrv_fd, (&ndrv_sa as *const sockaddr_ndrv).cast(), std::mem::size_of::() as libc::socklen_t) } != 0 { + unsafe { libc::close(bpf_fd); } + unsafe { libc::close(ndrv_fd); } return Err(String::from("unable to connect AF_NDRV socket")); } @@ -417,14 +744,16 @@ impl VNIC for MacFethTap { ipv } - #[inline(always)] fn device_name(&self) -> String { self.device.name.clone() } - #[inline(always)] fn get_multicast_groups(&self) -> HashSet { - crate::vnic::common::get_l2_multicast_subscriptions(self.device.name.as_str()) + let mut all_groups: HashSet = HashSet::new(); + crate::vnic::common::get_l2_multicast_subscriptions(self.device.name.as_str()).into_iter().for_each(|mac| { + all_groups.insert(MulticastGroup::from(&mac)); + }); + all_groups } #[inline(always)] @@ -433,17 +762,17 @@ impl VNIC for MacFethTap { let sm = source_mac.0; let mut hdr: [u8; 14] = [(dm >> 40) as u8, (dm >> 32) as u8, (dm >> 24) as u8, (dm >> 16) as u8, (dm >> 8) as u8, dm as u8, (sm >> 40) as u8, (sm >> 32) as u8, (sm >> 24) as u8, (sm >> 16) as u8, (sm >> 8) as u8, sm as u8, (ethertype >> 8) as u8, ethertype as u8]; unsafe { - let iov: [osdep::iovec; 2] = [ - osdep::iovec { + let iov: [libc::iovec; 2] = [ + libc::iovec { iov_base: hdr.as_mut_ptr().cast(), iov_len: 14, }, - osdep::iovec { + libc::iovec { iov_base: transmute(data), // have to "cast away const" even though data is not modified by writev() - iov_len: len as osdep::size_t, + iov_len: len as libc::size_t, }, ]; - osdep::writev(self.ndrv_fd, iov.as_ptr(), 2) == (len + 14) as osdep::ssize_t + libc::writev(self.ndrv_fd, iov.as_ptr(), 2) == (len + 14) as libc::ssize_t } } } @@ -452,14 +781,14 @@ impl Drop for MacFethTap { fn drop(&mut self) { if self.bpf_fd >= 0 { unsafe { - osdep::shutdown(self.bpf_fd, osdep::SHUT_RDWR as c_int); - osdep::close(self.bpf_fd); + libc::shutdown(self.bpf_fd, libc::SHUT_RDWR); + libc::close(self.bpf_fd); MAC_FETH_BPF_DEVICES_USED.lock().unwrap().remove(&self.bpf_no); } } if self.ndrv_fd >= 0 { unsafe { - osdep::close(self.ndrv_fd); + libc::close(self.ndrv_fd); } } let t = self.bpf_read_thread.replace(None); diff --git a/zerotier-system-service/src/vnic/vnic.rs b/zerotier-system-service/src/vnic/vnic.rs index 35054910b..c81c33dcb 100644 --- a/zerotier-system-service/src/vnic/vnic.rs +++ b/zerotier-system-service/src/vnic/vnic.rs @@ -11,8 +11,10 @@ */ /****/ +use zerotier_network_hypervisor::vl2::MulticastGroup; + /// Virtual network interface -pub(crate) trait VNIC { +pub trait VNIC { /// Add a new IPv4 or IPv6 address to this interface, returning true on success. fn add_ip(&self, ip: &zerotier_core::InetAddress) -> bool; @@ -30,7 +32,7 @@ pub(crate) trait VNIC { /// This doesn't do any IGMP snooping. It just reports the groups the port /// knows about. On some OSes this may not be supported in which case it /// will return an empty set. - fn get_multicast_groups(&self) -> std::collections::BTreeSet; + fn get_multicast_groups(&self) -> std::collections::BTreeSet; /// Inject an Ethernet frame into this port. fn put(&self, source_mac: &zerotier_core::MAC, dest_mac: &zerotier_core::MAC, ethertype: u16, vlan_id: u16, data: *const u8, len: usize) -> bool;