like idk this compiles or not
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
//!
|
||||
//! lowk why its free but its indirection and its ass
|
||||
|
||||
use macaddr::{MacAddr, MacAddr6};
|
||||
use macaddr::MacAddr6;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// i dont include what i dont know about (almost all ts)
|
||||
|
||||
@@ -1,25 +1,41 @@
|
||||
//! idk what to put here
|
||||
|
||||
use std::{iter, net::IpAddr};
|
||||
use std::net::IpAddr;
|
||||
|
||||
use anyhow::bail;
|
||||
|
||||
use super::{NUDState, NeighborItem};
|
||||
|
||||
// loose translation of [wakey::utils::query::macs::get_mac]
|
||||
// i think ill write tokio::process every time tho (for this if let thing) because iterate through all ts youll have to as str and all the hooplas.
|
||||
// it all turns to live osstr tho so ts just for my own sanity
|
||||
// thiserror? anyhow
|
||||
pub async fn get(
|
||||
ip: Option<IpAddr>,
|
||||
dev: Option<&str>,
|
||||
nud: &[NUDState],
|
||||
) -> anyhow::Result<Vec<NeighborItem>> {
|
||||
let output = tokio::process::Command::new("ip")
|
||||
.args(
|
||||
(["-j", "neigh", "show"].iter().map(ToString::to_string))
|
||||
.chain(ip.map(|ip| ip.to_canonical().to_string()))
|
||||
.chain(dev.map(ToString::to_string))
|
||||
.chain(nud.iter().map(|f| f.to_string())),
|
||||
)
|
||||
.output()
|
||||
.await?;
|
||||
let mut cmd = tokio::process::Command::new("ip");
|
||||
cmd.args(["-j", "neigh", "show"]);
|
||||
|
||||
bail!("no")
|
||||
if let Some(ip) = ip {
|
||||
cmd.arg(ip.to_canonical().to_string());
|
||||
};
|
||||
|
||||
if let Some(dev) = dev {
|
||||
cmd.arg("dev");
|
||||
cmd.arg(dev);
|
||||
}
|
||||
for nud in nud {
|
||||
cmd.arg("nud");
|
||||
cmd.arg(nud.to_string());
|
||||
}
|
||||
|
||||
let output = cmd.output().await?;
|
||||
|
||||
if !output.status.success() {
|
||||
bail!(String::from_utf8_lossy(&output.stderr).into_owned())
|
||||
} else {
|
||||
Ok(serde_json::from_slice(&output.stdout)?)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//! yes. this is a real call.
|
||||
|
||||
pub mod json;
|
||||
pub mod nl;
|
||||
|
||||
use crate::utils::serialize::mac::{des_opm, ser_opm};
|
||||
use std::net::IpAddr;
|
||||
@@ -25,7 +26,9 @@ pub struct NeighborInput {
|
||||
|
||||
// as input this must be lowercase. as output it is uppercase
|
||||
/// docs for items come from a random ahh man website idk
|
||||
#[derive(Debug, PartialEq, Eq, EnumString, Display, Clone, Copy, Hash, Serialize, Deserialize)]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, EnumString, Display, Clone, Copy, Hash, Serialize, Deserialize, Default,
|
||||
)]
|
||||
#[strum(serialize_all = "lowercase", ascii_case_insensitive)]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
pub enum NUDState {
|
||||
@@ -47,6 +50,7 @@ pub enum NUDState {
|
||||
/// this is a pseudo state used when initially
|
||||
/// creating a neighbour entry or after trying to
|
||||
/// remove it before it becomes free to do so.
|
||||
#[default]
|
||||
None,
|
||||
/// the neighbour entry has not (yet) been
|
||||
/// validated/resolved.
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// hallo
|
||||
use std::net::IpAddr;
|
||||
|
||||
use futures::TryStreamExt;
|
||||
use macaddr::MacAddr;
|
||||
use rtnetlink::packet_route::{
|
||||
link::LinkAttribute,
|
||||
neighbour::{NeighbourAddress, NeighbourAttribute, NeighbourState},
|
||||
};
|
||||
|
||||
use super::{NUDState, NeighborItem};
|
||||
|
||||
// dont you love https://github.com/rust-netlink/rtnetlink/blob/main/examples/get_neighbours.rs
|
||||
pub async fn get(
|
||||
ip: Option<IpAddr>,
|
||||
dev: Option<&str>,
|
||||
nud: &[NUDState],
|
||||
) -> anyhow::Result<Vec<NeighborItem>> {
|
||||
let (conn, handle, _) = rtnetlink::new_connection()?;
|
||||
tokio::spawn(conn); // every time?
|
||||
let mut neighbor_data = handle.neighbours().get().execute(); // can i change header with message_mut? what even is header.
|
||||
let mut result = vec![];
|
||||
'big: while let Some(neighbour_message_item) = neighbor_data.try_next().await? {
|
||||
let state = vec![
|
||||
neighbour_message_item
|
||||
.header
|
||||
.state
|
||||
.try_into()
|
||||
.unwrap_or_default(),
|
||||
];
|
||||
let mut dst = None;
|
||||
let mut lladdr = None;
|
||||
|
||||
// a hassle and a half to get the name
|
||||
let dev = handle
|
||||
.link()
|
||||
.get()
|
||||
.match_index(neighbour_message_item.header.ifindex)
|
||||
.execute()
|
||||
.try_next()
|
||||
.await?
|
||||
.and_then(|a| {
|
||||
for link_attr in a.attributes {
|
||||
match link_attr {
|
||||
LinkAttribute::IfName(name) => return Some(name),
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
for neigh_attr in neighbour_message_item.attributes {
|
||||
match neigh_attr {
|
||||
NeighbourAttribute::Destination(neighbour_address) => match neighbour_address {
|
||||
NeighbourAddress::Inet(ipv4_addr) => dst = Some(ipv4_addr.into()),
|
||||
NeighbourAddress::Inet6(ipv6_addr) => dst = Some(ipv6_addr.into()),
|
||||
_ => continue 'big,
|
||||
},
|
||||
NeighbourAttribute::LinkLocalAddress(items) => {
|
||||
lladdr = match items.len() {
|
||||
6 => items.first_chunk::<6>().map(|&e| MacAddr::from(e)),
|
||||
8 => items.first_chunk::<8>().map(|&e| MacAddr::from(e)),
|
||||
_ => continue 'big,
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
let Some((dst, dev)) = dst.zip(dev) else {
|
||||
continue;
|
||||
};
|
||||
result.push(NeighborItem {
|
||||
dst,
|
||||
dev,
|
||||
lladdr,
|
||||
state,
|
||||
});
|
||||
}
|
||||
Ok(result) // now i need another pass to filter out the uh.
|
||||
}
|
||||
|
||||
impl TryFrom<NeighbourState> for NUDState {
|
||||
fn try_from(value: NeighbourState) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
NeighbourState::Incomplete => Ok(Self::Incomplete),
|
||||
NeighbourState::Reachable => Ok(Self::Reachable),
|
||||
NeighbourState::Stale => Ok(Self::Stale),
|
||||
NeighbourState::Delay => Ok(Self::Delay),
|
||||
NeighbourState::Probe => Ok(Self::Probe),
|
||||
NeighbourState::Failed => Ok(Self::Failed),
|
||||
NeighbourState::Noarp => Ok(Self::Noarp),
|
||||
NeighbourState::Permanent => Ok(Self::Permanent),
|
||||
NeighbourState::None => Ok(Self::None),
|
||||
NeighbourState::Other(e) => Err(e),
|
||||
_ => Err(u16::MAX), // idk
|
||||
}
|
||||
}
|
||||
|
||||
type Error = u16;
|
||||
}
|
||||
Reference in New Issue
Block a user