Update a bunch of service code in keeping with new Rust core, and remove osdep stuff in favor of the libc crate.

This commit is contained in:
Adam Ierymenko 2021-10-14 21:02:51 -04:00
parent 0c0e78da1b
commit bf482e06ea
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
10 changed files with 946 additions and 129 deletions

View file

@ -0,0 +1,3 @@
mod multicastgroup;
pub use multicastgroup::MulticastGroup;

View file

@ -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<MAC> 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<Ordering> { Some(self.cmp(other)) }
}
impl Hash for MulticastGroup {
#[inline(always)]
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u64(self.mac.to_u64());
state.write_u32(self.adi);
}
}

View file

@ -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",
]

View file

@ -3,7 +3,6 @@ name = "zerotier-system-service"
version = "0.1.0"
authors = ["Adam Ierymenko <adam.ierymenko@zerotier.com>"]
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"

View file

@ -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);
}

View file

@ -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: &A) -> *const A {
a as *const A
@ -26,19 +24,19 @@ fn s6_addr_as_ptr<A>(a: &A) -> *const A {
#[cfg(unix)]
pub(crate) fn for_each_address<F: FnMut(&InetAddress, &str)>(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::<u8>(), (&mut a as *mut InetAddress).cast::<u8>(), size_of::<osdep::sockaddr_in>());
} else if sa_family == osdep::AF_INET6 as u8 {
copy_nonoverlapping((*i).ifa_addr.cast::<u8>(), (&mut a as *mut InetAddress).cast::<u8>(), size_of::<osdep::sockaddr_in6>());
if sa_family == libc::AF_INET as u8 {
copy_nonoverlapping((*i).ifa_addr.cast::<u8>(), (&mut a as *mut InetAddress).cast::<u8>(), size_of::<libc::sockaddr_in>());
} else if sa_family == libc::AF_INET6 as u8 {
copy_nonoverlapping((*i).ifa_addr.cast::<u8>(), (&mut a as *mut InetAddress).cast::<u8>(), size_of::<libc::sockaddr_in6>());
} else {
i = (*i).ifa_next;
continue;
@ -46,11 +44,11 @@ pub(crate) fn for_each_address<F: FnMut(&InetAddress, &str)>(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::<osdep::sockaddr_in>()).sin_addr.s_addr as u32;
if sa_family == libc::AF_INET as u8 {
let a = (*(*i).ifa_netmask.cast::<libc::sockaddr_in>()).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::<osdep::sockaddr_in6>()).sin6_addr)).cast::<u8>();
} else if sa_family == libc::AF_INET6 as u8 {
let a = s6_addr_as_ptr(&((*(*i).ifa_netmask.cast::<libc::sockaddr_in6>()).sin6_addr)).cast::<u8>();
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<F: FnMut(&InetAddress, &str)>(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<F: FnMut(&InetAddress, &str)>(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() {

View file

@ -92,7 +92,7 @@ Common Operations:
Advanced Operations:
service Start node
(usually not invoked directly)
(usually run by service manager)
controller <command> [option]
· list List networks on controller

View file

@ -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<MulticastGroup> {
#[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<MAC> {
let mut groups: HashSet<MulticastGroup> = 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<MulticastGrou
/// Linux stores this stuff in /proc and it needs to be fetched from there.
#[cfg(target_os = "linux")]
pub(crate) fn get_l2_multicast_subscriptions(dev: &str) -> HashSet<MulticastGroup> {
pub fn get_l2_multicast_subscriptions(dev: &str) -> HashSet<MAC> {
let mut groups: HashSet<MulticastGroup> = HashSet::new();
groups
}

View file

@ -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<BTreeSet<u32>> = 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::<u8>(), 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::<c_void>()) == 0 {
if libc::ioctl(s, 76 /* SIOCGIFINFO_IN6 */, (&mut nd as *mut in6_ndireq).cast::<c_void>()) == 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::<c_void>()) != 0 {
if libc::ioctl(s, 87 /* SIOCSIFINFO_FLAGS */, (&mut nd as *mut in6_ndireq).cast::<c_void>()) != 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::<u8>(), 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::<c_void>()) != 0 {
if libc::ioctl(s, if accept_ra { 132 /* SIOCAUTOCONF_START */ } else { 133 /* SIOCAUTOCONF_STOP */ }, (&mut ifr as *mut in6_ifreq).cast::<c_void>()) != 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<F: Fn(&[u8]) + Send + Sync + 'static>(nwid: &NetworkId, mac: &MAC, mtu: i32, metric: i32, eth_frame_func: F) -> Result<MacFethTap, String> {
pub fn new<F: Fn(&[u8]) + Send + Sync + 'static>(nwid: &NetworkId, mac: &MAC, mtu: i32, metric: i32, eth_frame_func: F) -> Result<MacFethTap, String> {
// 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::<c_void>()) } != 0 {
unsafe { osdep::close(bpf_fd); }
if unsafe { libc::ioctl(bpf_fd as c_int, 102 /* BIOCSBLEN */, (&mut fl as *mut c_int).cast::<c_void>()) } != 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::<c_void>()) } != 0 {
unsafe { osdep::close(bpf_fd); }
if unsafe { libc::ioctl(bpf_fd as c_int, 112 /* BIOCIMMEDIATE */, (&mut fl as *mut c_int).cast::<c_void>()) } != 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::<c_void>()) } != 0 {
unsafe { osdep::close(bpf_fd); }
if unsafe { libc::ioctl(bpf_fd as c_int, 119 /* BIOCSSEESENT */, (&mut fl as *mut c_int).cast::<c_void>()) } != 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::<u8>(), 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::<c_void>()) } != 0 {
unsafe { osdep::close(bpf_fd); }
if unsafe { libc::ioctl(bpf_fd as c_int, 108 /* BIOCSETIF */, (&mut bpf_ifr as *mut ifreq).cast::<c_void>()) } != 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::<c_void>()) } != 0 {
unsafe { osdep::close(bpf_fd); }
if unsafe { libc::ioctl(bpf_fd as c_int, 117 /* BIOCSHDRCMPLT */, (&mut fl as *mut c_int).cast::<c_void>()) } != 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::<c_void>()) } != 0 {
unsafe { osdep::close(bpf_fd); }
if unsafe { libc::ioctl(bpf_fd as c_int, 105 /* BIOCPROMISC */, (&mut fl as *mut c_int).cast::<c_void>()) } != 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::<osdep::bpf_hdr>() as isize;
let hdr_struct_size = std::mem::size_of::<libc::bpf_hdr>() 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::<osdep::bpf_hdr>();
let h = buf.as_ptr().offset(p).cast::<libc::bpf_hdr>();
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::<osdep::sockaddr_ndrv>() 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::<sockaddr_ndrv>() 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::<u8>(), 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::<osdep::sockaddr_ndrv>() 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::<sockaddr_ndrv>() 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::<osdep::sockaddr_ndrv>() 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::<sockaddr_ndrv>() 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<MulticastGroup> {
crate::vnic::common::get_l2_multicast_subscriptions(self.device.name.as_str())
let mut all_groups: HashSet<MulticastGroup> = 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);

View file

@ -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<zerotier_core::MulticastGroup>;
fn get_multicast_groups(&self) -> std::collections::BTreeSet<MulticastGroup>;
/// 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;