diff --git a/Cargo.lock b/Cargo.lock index 771d551071..d2f28125c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -935,6 +935,7 @@ dependencies = [ "hyper", "libc", "log", + "netif", "nix", "notify", "once_cell", @@ -2258,6 +2259,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "netif" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9e642845c332c335e3125759b10145a972c1f413cb48cd6d7b96e81821f281" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "new_debug_unreachable" version = "1.0.4" diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8733e1727d..fa6ed4e255 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -70,6 +70,7 @@ http = "0.2.4" hyper = { version = "0.14.12", features = ["server", "stream", "http1", "http2", "runtime"] } libc = "0.2.106" log = "0.4.14" +netif = "0.1.0" notify = "=5.0.0-pre.12" once_cell = "=1.9.0" regex = "1.5.4" diff --git a/runtime/ops/os.rs b/runtime/ops/os.rs index 81f8a529ee..bbc571cc6f 100644 --- a/runtime/ops/os.rs +++ b/runtime/ops/os.rs @@ -25,6 +25,7 @@ pub fn init(maybe_exit_code: Option>) -> Extension { ("op_delete_env", op_sync(op_delete_env)), ("op_hostname", op_sync(op_hostname)), ("op_loadavg", op_sync(op_loadavg)), + ("op_network_interfaces", op_sync(op_network_interfaces)), ("op_os_release", op_sync(op_os_release)), ("op_set_exit_code", op_sync(op_set_exit_code)), ("op_system_memory_info", op_sync(op_system_memory_info)), @@ -149,6 +150,60 @@ fn op_os_release( Ok(release) } +fn op_network_interfaces( + state: &mut OpState, + _: (), + _: (), +) -> Result, AnyError> { + super::check_unstable(state, "Deno.networkInterfaces"); + state.borrow_mut::().env.check_all()?; + Ok(netif::up()?.map(NetworkInterface::from).collect()) +} + +#[derive(serde::Serialize)] +struct NetworkInterface { + family: &'static str, + name: String, + 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 name = ifa.name().to_owned(); + 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, + name, + address, + netmask, + scopeid, + cidr, + mac, + } + } +} + // Copied from sys-info/lib.rs (then tweaked) #[derive(Serialize)] #[serde(rename_all = "camelCase")]