ball knowledge
(claude handholding)
This commit is contained in:
@@ -69,9 +69,16 @@ pub enum NUDState {
|
||||
/// everything i see
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)]
|
||||
pub struct NeighborItem {
|
||||
dst: IpAddr,
|
||||
#[serde(rename(deserialize = "dst"))]
|
||||
ip: IpAddr,
|
||||
dev: String,
|
||||
#[serde(deserialize_with = "des_opm", serialize_with = "ser_opm")]
|
||||
lladdr: Option<MacAddr>,
|
||||
#[serde(
|
||||
deserialize_with = "des_opm",
|
||||
serialize_with = "ser_opm",
|
||||
default,
|
||||
rename(deserialize = "lladdr")
|
||||
)]
|
||||
mac: Option<MacAddr>,
|
||||
#[serde(default)]
|
||||
state: Vec<NUDState>,
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
// hallo
|
||||
use std::net::IpAddr;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
net::IpAddr,
|
||||
};
|
||||
|
||||
use futures::TryStreamExt;
|
||||
use macaddr::MacAddr;
|
||||
use rtnetlink::packet_route::{
|
||||
AddressFamily,
|
||||
link::LinkAttribute,
|
||||
neighbour::{NeighbourAddress, NeighbourAttribute, NeighbourState},
|
||||
};
|
||||
@@ -16,47 +20,42 @@ pub async fn get(
|
||||
dev: Option<&str>,
|
||||
nud: &[NUDState],
|
||||
) -> anyhow::Result<Vec<NeighborItem>> {
|
||||
let (gip, gdev, gnud) = (ip, dev, nud);
|
||||
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 neighbor_data = handle.neighbours().get().execute();
|
||||
let nudset: HashSet<&NUDState> = HashSet::from_iter(gnud);
|
||||
let mut ball: HashMap<u32, String> = HashMap::new();
|
||||
let mut result = vec![];
|
||||
'big: while let Some(neighbour_message_item) = neighbor_data.try_next().await? {
|
||||
// Filter by address family
|
||||
if !matches!(
|
||||
neighbour_message_item.header.family,
|
||||
AddressFamily::Inet | AddressFamily::Inet6
|
||||
) || matches!(neighbour_message_item.header.state, NeighbourState::Noarp)
|
||||
{
|
||||
continue 'big;
|
||||
}
|
||||
|
||||
let state = vec![
|
||||
neighbour_message_item
|
||||
.header
|
||||
.state
|
||||
.try_into()
|
||||
.unwrap_or_default(),
|
||||
];
|
||||
let mut dst = None;
|
||||
let mut lladdr = None;
|
||||
]; // ONE ITEM. why tf ts design json.
|
||||
let mut ip = None;
|
||||
let mut mac = 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()),
|
||||
NeighbourAddress::Inet(ipv4_addr) => ip = Some(ipv4_addr.into()),
|
||||
NeighbourAddress::Inet6(ipv6_addr) => ip = Some(ipv6_addr.into()),
|
||||
_ => continue 'big,
|
||||
},
|
||||
NeighbourAttribute::LinkLocalAddress(items) => {
|
||||
lladdr = match items.len() {
|
||||
mac = 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,
|
||||
@@ -65,13 +64,57 @@ pub async fn get(
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
let Some((dst, dev)) = dst.zip(dev) else {
|
||||
continue;
|
||||
|
||||
// exquisite
|
||||
let dev = if let Some(cached) = ball.get(&neighbour_message_item.header.ifindex) {
|
||||
Some(cached.clone())
|
||||
} else {
|
||||
// Query and cache
|
||||
let name = handle
|
||||
.link()
|
||||
.get()
|
||||
.match_index(neighbour_message_item.header.ifindex)
|
||||
.execute()
|
||||
.try_next()
|
||||
.await?
|
||||
.and_then(|a| {
|
||||
a.attributes.into_iter().find_map(|attr| match attr {
|
||||
LinkAttribute::IfName(name) => Some(name),
|
||||
_ => None,
|
||||
})
|
||||
});
|
||||
|
||||
if let Some(ref n) = name {
|
||||
ball.insert(neighbour_message_item.header.ifindex, n.clone());
|
||||
}
|
||||
name
|
||||
};
|
||||
|
||||
let Some((ip, dev)) = ip.zip(dev) else {
|
||||
continue 'big;
|
||||
};
|
||||
|
||||
{
|
||||
// low block
|
||||
if let Some(fip) = gip
|
||||
&& fip != ip
|
||||
{
|
||||
continue 'big;
|
||||
}
|
||||
if let Some(fdev) = gdev
|
||||
&& dev != fdev
|
||||
{
|
||||
continue 'big;
|
||||
}
|
||||
if !nudset.is_empty() && !nudset.contains(&state[0]) {
|
||||
continue 'big;
|
||||
};
|
||||
}
|
||||
|
||||
result.push(NeighborItem {
|
||||
dst,
|
||||
ip,
|
||||
dev,
|
||||
lladdr,
|
||||
mac,
|
||||
state,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user