sweep 2!
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
use anyhow::{Context, Result};
|
||||
use lda_ipjs::subcommands::address;
|
||||
use std::collections::HashSet;
|
||||
use wakey_core::{InterfaceAddr, InterfaceSummary};
|
||||
|
||||
pub async fn list_devs() -> HashSet<String> {
|
||||
fn get_dev() -> HashSet<String> {
|
||||
let mut devs: HashSet<String> = HashSet::new();
|
||||
if let Ok(rd) = std::fs::read_dir("/sys/class/net") {
|
||||
for e in rd.flatten() {
|
||||
if e.file_type()
|
||||
.map(|ft| {
|
||||
if ft.is_symlink() {
|
||||
std::fs::metadata(e.path())
|
||||
.map(|m| m.is_dir())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
ft.is_dir()
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
&& let Ok(name) = e.file_name().into_string()
|
||||
&& name != "lo"
|
||||
&& !name.is_empty()
|
||||
{
|
||||
devs.insert(name);
|
||||
}
|
||||
}
|
||||
} else if let Ok(txt) = std::fs::read_to_string("/proc/net/dev") {
|
||||
for line in txt.lines().skip(2) {
|
||||
if let Some((name, _rest)) = line.split_once(':') {
|
||||
let n = name.trim().to_string();
|
||||
if n != "lo" && !n.is_empty() {
|
||||
devs.insert(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
devs
|
||||
}
|
||||
|
||||
tokio::task::spawn_blocking(get_dev)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub async fn devs_sorted() -> Vec<String> {
|
||||
let mut v: Vec<String> = list_devs().await.into_iter().collect();
|
||||
v.sort();
|
||||
v
|
||||
}
|
||||
|
||||
pub async fn list_interface_summaries() -> Result<Vec<InterfaceSummary>> {
|
||||
#[cfg(unix)]
|
||||
let rows = address::nl::get(None)
|
||||
.await
|
||||
.context("rtnetlink address query failed")?;
|
||||
|
||||
#[cfg(not(unix))]
|
||||
let rows = address::get_with_backend(address::Backend::Json, None)
|
||||
.await
|
||||
.context("ip -j address show failed")?;
|
||||
|
||||
let mut out: Vec<InterfaceSummary> = rows
|
||||
.into_iter()
|
||||
.filter(|row| row.ifname != "lo")
|
||||
.map(|row| InterfaceSummary {
|
||||
ifindex: row.ifindex,
|
||||
ifname: row.ifname,
|
||||
operstate: row.operstate.as_str().to_ascii_lowercase(),
|
||||
mac: row.address,
|
||||
addrs: row
|
||||
.addr_info
|
||||
.into_iter()
|
||||
.map(|info| InterfaceAddr {
|
||||
family: info.family.map(|family| family.as_str().to_string()),
|
||||
cidr: info
|
||||
.cidr
|
||||
.local
|
||||
.zip(info.cidr.prefixlen)
|
||||
.map(|(addr, prefixlen)| format!("{addr}/{prefixlen}")),
|
||||
broadcast: info.broadcast,
|
||||
scope: info.scope,
|
||||
label: info.label,
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
out.sort_by(|a, b| a.ifname.cmp(&b.ifname));
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub async fn has_dev(name: &str) -> bool {
|
||||
list_devs().await.contains(name)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mod interfaces;
|
||||
mod neighbors;
|
||||
mod query;
|
||||
|
||||
pub use interfaces::{devs_sorted, has_dev, list_devs, list_interface_summaries};
|
||||
pub use neighbors::{get_ips, get_neighbors, query_status};
|
||||
pub use query::classify_query;
|
||||
@@ -1,12 +1,9 @@
|
||||
use anyhow::{Context, Result};
|
||||
use futures::future::try_join_all;
|
||||
use lda_ipjs::subcommands::neighbor;
|
||||
use std::collections::HashSet;
|
||||
use std::net::IpAddr;
|
||||
use wakey_core::{
|
||||
DeviceQuery, InterfaceAddr, InterfaceSummary, NeighborEntry, NeighborState, QueryInput, parse,
|
||||
};
|
||||
|
||||
use lda_ipjs::subcommands::{address, neighbor};
|
||||
use wakey_core::{DeviceQuery, NeighborEntry, NeighborState};
|
||||
|
||||
pub async fn get_ips(machine_name: &str) -> Result<impl Iterator<Item = IpAddr>> {
|
||||
Ok(tokio::net::lookup_host((machine_name, 0))
|
||||
@@ -114,115 +111,6 @@ pub async fn query_status(query: &DeviceQuery) -> Result<Vec<NeighborEntry>> {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_devs() -> HashSet<String> {
|
||||
fn get_dev() -> HashSet<String> {
|
||||
let mut devs: HashSet<String> = HashSet::new();
|
||||
if let Ok(rd) = std::fs::read_dir("/sys/class/net") {
|
||||
for e in rd.flatten() {
|
||||
if e.file_type()
|
||||
.map(|ft| {
|
||||
if ft.is_symlink() {
|
||||
std::fs::metadata(e.path())
|
||||
.map(|m| m.is_dir())
|
||||
.unwrap_or(false)
|
||||
} else {
|
||||
ft.is_dir()
|
||||
}
|
||||
})
|
||||
.unwrap_or(false)
|
||||
&& let Ok(name) = e.file_name().into_string()
|
||||
&& name != "lo"
|
||||
&& !name.is_empty()
|
||||
{
|
||||
devs.insert(name);
|
||||
}
|
||||
}
|
||||
} else if let Ok(txt) = std::fs::read_to_string("/proc/net/dev") {
|
||||
for line in txt.lines().skip(2) {
|
||||
if let Some((name, _rest)) = line.split_once(':') {
|
||||
let n = name.trim().to_string();
|
||||
if n != "lo" && !n.is_empty() {
|
||||
devs.insert(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
devs
|
||||
}
|
||||
|
||||
tokio::task::spawn_blocking(get_dev)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub async fn devs_sorted() -> Vec<String> {
|
||||
let mut v: Vec<String> = list_devs().await.into_iter().collect();
|
||||
v.sort();
|
||||
v
|
||||
}
|
||||
|
||||
pub async fn list_interface_summaries() -> Result<Vec<InterfaceSummary>> {
|
||||
#[cfg(unix)]
|
||||
let rows = address::nl::get(None)
|
||||
.await
|
||||
.context("rtnetlink address query failed")?;
|
||||
|
||||
#[cfg(not(unix))]
|
||||
let rows = address::get_with_backend(address::Backend::Json, None)
|
||||
.await
|
||||
.context("ip -j address show failed")?;
|
||||
|
||||
let mut out: Vec<InterfaceSummary> = rows
|
||||
.into_iter()
|
||||
.filter(|row| row.ifname != "lo")
|
||||
.map(|row| InterfaceSummary {
|
||||
ifindex: row.ifindex,
|
||||
ifname: row.ifname,
|
||||
operstate: row.operstate.as_str().to_ascii_lowercase(),
|
||||
mac: row.address,
|
||||
addrs: row
|
||||
.addr_info
|
||||
.into_iter()
|
||||
.map(|info| InterfaceAddr {
|
||||
family: info.family.map(|family| family.as_str().to_string()),
|
||||
cidr: info
|
||||
.cidr
|
||||
.local
|
||||
.zip(info.cidr.prefixlen)
|
||||
.map(|(addr, prefixlen)| format!("{addr}/{prefixlen}")),
|
||||
broadcast: info.broadcast,
|
||||
scope: info.scope,
|
||||
label: info.label,
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
out.sort_by(|a, b| a.ifname.cmp(&b.ifname));
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub async fn has_dev(name: &str) -> bool {
|
||||
list_devs().await.contains(name)
|
||||
}
|
||||
|
||||
pub async fn classify_query(q: String) -> QueryInput {
|
||||
let s = parse::extract_host(&q);
|
||||
if let Some(ip) = parse::parse_numeric_ipv4(s).or_else(|| s.parse::<IpAddr>().ok()) {
|
||||
return QueryInput::Ip(ip);
|
||||
}
|
||||
if let Ok(mac) = s.parse::<macaddr::MacAddr>() {
|
||||
return QueryInput::Mac(mac);
|
||||
}
|
||||
if let Ok(state) = s.parse::<NeighborState>() {
|
||||
return QueryInput::Nud(state);
|
||||
}
|
||||
if has_dev(s).await {
|
||||
return QueryInput::Dev(s.to_string());
|
||||
}
|
||||
QueryInput::Name(s.to_string())
|
||||
}
|
||||
|
||||
fn to_ipjs_state(value: NeighborState) -> lda_ipjs::subcommands::neighbor::NUDState {
|
||||
match value {
|
||||
NeighborState::Permanent => lda_ipjs::subcommands::neighbor::NUDState::Permanent,
|
||||
@@ -0,0 +1,22 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use wakey_core::{NeighborState, QueryInput, parse};
|
||||
|
||||
use crate::devices::interfaces::has_dev;
|
||||
|
||||
pub async fn classify_query(q: String) -> QueryInput {
|
||||
let s = parse::extract_host(&q);
|
||||
if let Some(ip) = parse::parse_numeric_ipv4(s).or_else(|| s.parse::<IpAddr>().ok()) {
|
||||
return QueryInput::Ip(ip);
|
||||
}
|
||||
if let Ok(mac) = s.parse::<macaddr::MacAddr>() {
|
||||
return QueryInput::Mac(mac);
|
||||
}
|
||||
if let Ok(state) = s.parse::<NeighborState>() {
|
||||
return QueryInput::Nud(state);
|
||||
}
|
||||
if has_dev(s).await {
|
||||
return QueryInput::Dev(s.to_string());
|
||||
}
|
||||
QueryInput::Name(s.to_string())
|
||||
}
|
||||
Reference in New Issue
Block a user