From fe5a91a500028b96cf9a65e0eabc8f31dad9391d Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 2 Dec 2021 13:09:02 +0100 Subject: [PATCH] feat(ext/net): add op_network_interfaces Add an op to list the network interfaces on the system. Prep work for #8137 and `os.networkInterfaces()` Node compat in std. Refs denoland/deno_std#1436. --- Cargo.lock | 9 +++++++ ext/net/Cargo.toml | 1 + ext/net/README.md | 1 + ext/net/lib.rs | 1 + ext/net/ops.rs | 54 ++++++++++++++++++++++++++++++++++++++++++ runtime/build.rs | 6 +++++ runtime/permissions.rs | 4 ++++ 7 files changed, 76 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 92b491b5e1f5ac..e1b40426ada255 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -885,6 +885,7 @@ dependencies = [ "deno_core", "deno_tls", "log", + "netif", "serde", "tokio", "trust-dns-proto", @@ -2268,6 +2269,14 @@ dependencies = [ "thiserror", ] +[[package]] +name = "netif" +version = "0.1.0" +source = "git+https://github.com/bnoordhuis/netif#ff2b73735a9ad16288a5ad3013a69b8367ace41d" +dependencies = [ + "libc", +] + [[package]] name = "new_debug_unreachable" version = "1.0.4" diff --git a/ext/net/Cargo.toml b/ext/net/Cargo.toml index 912dac88436de3..13ee6d6cb62977 100644 --- a/ext/net/Cargo.toml +++ b/ext/net/Cargo.toml @@ -17,6 +17,7 @@ path = "lib.rs" deno_core = { version = "0.109.0", path = "../../core" } deno_tls = { version = "0.14.0", path = "../tls" } log = "0.4.14" +netif = { git = "https://github.com/bnoordhuis/netif" } serde = { version = "1.0.129", features = ["derive"] } tokio = { version = "1.10.1", features = ["full"] } trust-dns-proto = "0.20.3" diff --git a/ext/net/README.md b/ext/net/README.md index 1928fc375b1632..998c572f392f60 100644 --- a/ext/net/README.md +++ b/ext/net/README.md @@ -20,3 +20,4 @@ Following ops are provided: - "op_tls_listen" - "op_tls_accept" - "op_tls_handshake" +- "op_network_interfaces" diff --git a/ext/net/lib.rs b/ext/net/lib.rs index bbbfb3331a8661..82f20d952b7975 100644 --- a/ext/net/lib.rs +++ b/ext/net/lib.rs @@ -24,6 +24,7 @@ pub trait NetPermissions { ) -> Result<(), AnyError>; fn check_read(&mut self, _p: &Path) -> Result<(), AnyError>; fn check_write(&mut self, _p: &Path) -> Result<(), AnyError>; + fn check_network_interfaces(&mut self) -> Result<(), AnyError>; } /// `UnstableChecker` is a struct so it can be placed inside `GothamState`; diff --git a/ext/net/ops.rs b/ext/net/ops.rs index 739807123e6492..04cadcdd2e4566 100644 --- a/ext/net/ops.rs +++ b/ext/net/ops.rs @@ -55,6 +55,7 @@ pub fn init() -> Vec { ("op_dgram_recv", op_async(op_dgram_recv)), ("op_dgram_send", op_async(op_dgram_send::

)), ("op_dns_resolve", op_async(op_dns_resolve::

)), + ("op_network_interfaces", op_sync(op_network_interfaces::

)), ] } @@ -709,6 +710,59 @@ fn rdata_to_return_record( } } +fn op_network_interfaces( + state: &mut OpState, + _: (), + _: (), +) -> Result, AnyError> +where + NP: NetPermissions + 'static, +{ + state.borrow_mut::().check_network_interfaces()?; + Ok(netif::all()?.map(NetworkInterface::from).collect()) +} + +#[derive(serde::Serialize)] +struct NetworkInterface { + family: &'static str, + address: String, + netmask: String, + scopeid: Option, + cidr: String, + mac: String, +} + +impl From for NetworkInterface { + fn from(ifa: netif::Interface) -> Self { + let family = match ifa.address() { + std::net::IpAddr::V4(_) => "IPv4", + std::net::IpAddr::V6(_) => "IPv6", + }; + + let (address, range) = ifa.cidr(); + let cidr = format!("{:?}/{}", address, range); + + let address = format!("{:?}", ifa.address()); + let netmask = format!("{:?}", ifa.netmask()); + let scopeid = ifa.scope_id(); + + let [b0, b1, b2, b3, b4, b5] = ifa.mac(); + let mac = format!( + "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", + b0, b1, b2, b3, b4, b5 + ); + + Self { + family, + address, + netmask, + scopeid, + cidr, + mac, + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/runtime/build.rs b/runtime/build.rs index 14e2e0362c6543..008268359a82ff 100644 --- a/runtime/build.rs +++ b/runtime/build.rs @@ -112,6 +112,12 @@ mod not_docs { ) -> Result<(), deno_core::error::AnyError> { unreachable!("snapshotting!") } + + fn check_network_interfaces( + &mut self, + ) -> Result<(), deno_core::error::AnyError> { + unreachable!("snapshotting!") + } } fn create_runtime_snapshot(snapshot_path: &Path, files: Vec) { diff --git a/runtime/permissions.rs b/runtime/permissions.rs index 9a85e5e5833235..aa6cf4ffda33db 100644 --- a/runtime/permissions.rs +++ b/runtime/permissions.rs @@ -1285,6 +1285,10 @@ impl deno_net::NetPermissions for Permissions { fn check_write(&mut self, path: &Path) -> Result<(), AnyError> { self.write.check(path) } + + fn check_network_interfaces(&mut self) -> Result<(), AnyError> { + Ok(()) // TODO(bnoordhuis) + } } impl deno_fetch::FetchPermissions for Permissions {