2 Commits
12 changed files with 84 additions and 69 deletions

No files matched your search

+1 -1
View File
@@ -32,7 +32,7 @@ pub async fn get(dev: Option<&str>) -> anyhow::Result<Vec<AddrOutput>> {
anyhow::bail!(String::from_utf8_lossy(&output.stderr).into_owned()); anyhow::bail!(String::from_utf8_lossy(&output.stderr).into_owned());
} }
Ok(serde_json::from_slice(&output.stdout)?) serde_json::from_slice(&output.stdout).context("Deserialize failed")
} }
pub async fn _get(dev: Option<&str>) -> io::Result<Output> { pub async fn _get(dev: Option<&str>) -> io::Result<Output> {
let mut cmd = tokio::process::Command::new("ip"); let mut cmd = tokio::process::Command::new("ip");
+13 -1
View File
@@ -24,7 +24,18 @@ pub async fn get(
if !output.status.success() { if !output.status.success() {
bail!(String::from_utf8_lossy(&output.stderr).into_owned()) bail!(String::from_utf8_lossy(&output.stderr).into_owned())
} else { } else {
Ok(serde_json::from_slice(&output.stdout)?) let mut fuckass: Vec<NeighborItem> =
serde_json::from_slice(&output.stdout).context("Deserialize failed")?;
// i hate ts.
if let Some(dev) = dev {
for item in &mut fuckass {
if item.dev.is_none() {
item.dev = Some(dev.to_owned());
}
}
};
Ok(fuckass)
} }
} }
@@ -33,6 +44,7 @@ pub async fn _get(ip: Option<IpAddr>, dev: Option<&str>, nud: &[NUDState]) -> io
cmd.args(["-j", "neigh", "show"]); cmd.args(["-j", "neigh", "show"]);
if let Some(ip) = ip { if let Some(ip) = ip {
// cmd.arg("to");
cmd.arg(ip.to_canonical().to_string()); cmd.arg(ip.to_canonical().to_string());
}; };
+2 -1
View File
@@ -73,7 +73,8 @@ pub enum NUDState {
pub struct NeighborItem { pub struct NeighborItem {
#[serde(rename(deserialize = "dst"))] #[serde(rename(deserialize = "dst"))]
pub ip: IpAddr, pub ip: IpAddr,
pub dev: String, #[serde(default)]
pub dev: Option<String>,
#[serde(with = "option_mac", default, rename(deserialize = "lladdr"))] #[serde(with = "option_mac", default, rename(deserialize = "lladdr"))]
pub mac: Option<MacAddr>, pub mac: Option<MacAddr>,
#[serde(default)] #[serde(default)]
+2 -2
View File
@@ -93,7 +93,7 @@ pub async fn get(
name name
}; };
let Some((ip, dev)) = ip.zip(dev) else { let (Some(ip), Some(dev)) = (ip, dev) else {
continue 'big; continue 'big;
}; };
@@ -116,7 +116,7 @@ pub async fn get(
result.push(NeighborItem { result.push(NeighborItem {
ip, ip,
dev, dev: Some(dev),
mac, mac,
state, state,
}); });
+1 -1
View File
@@ -1,2 +1,2 @@
pub mod iter; // pub mod iter;
pub mod serialize; pub mod serialize;
+10 -6
View File
@@ -1,6 +1,6 @@
use macaddr::MacAddr; use macaddr::MacAddr;
use serde::{self, Deserialize, Deserializer, de::Error as DeError}; use serde::{self, Deserialize, Deserializer, de::Error as DeError};
use serde::{Serialize, Serializer, de}; use serde::{Serialize, Serializer};
pub fn serialize_macs<S>(macs: &[MacAddr], serializer: S) -> Result<S::Ok, S::Error> pub fn serialize_macs<S>(macs: &[MacAddr], serializer: S) -> Result<S::Ok, S::Error>
where where
@@ -33,14 +33,18 @@ pub mod option_mac {
pub fn serialize<S: Serializer>(bro: &Option<MacAddr>, ser: S) -> Result<S::Ok, S::Error> { pub fn serialize<S: Serializer>(bro: &Option<MacAddr>, ser: S) -> Result<S::Ok, S::Error> {
Option::<String>::serialize(&bro.as_ref().map(ToString::to_string), ser) Option::<String>::serialize(&bro.as_ref().map(ToString::to_string), ser)
} }
/// deserialize an [`Option<MacAddr>`] /// deserialize an [`Option<MacAddr>`], returns None for invalid input (::, 0.0.0.0)
pub fn deserialize<'de, D>(des: D) -> Result<Option<MacAddr>, D::Error> pub fn deserialize<'de, D>(des: D) -> Result<Option<MacAddr>, D::Error>
where where
D: serde::Deserializer<'de>, D: serde::Deserializer<'de>,
{ {
Option::<&str>::deserialize(des)? let s: Option<&str> = Option::<&str>::deserialize(des)?;
.map(str::parse) match s {
.transpose() Some(val) => match val.parse::<MacAddr>() {
.map_err(de::Error::custom) Ok(mac) => Ok(Some(mac)),
Err(_) => Ok(None),
},
None => Ok(None),
}
} }
} }
+17 -3
View File
@@ -1,6 +1,6 @@
use std::collections::HashSet; use std::collections::HashSet;
use lda_ipjs::subcommands::neighbor; use lda_ipjs::subcommands::{address, neighbor};
#[tokio::test] // ← Use tokio::test instead of manual #[tokio::main] #[tokio::test] // ← Use tokio::test instead of manual #[tokio::main]
async fn ball1() -> anyhow::Result<()> { async fn ball1() -> anyhow::Result<()> {
@@ -119,7 +119,21 @@ async fn ball_compare_backends() -> anyhow::Result<()> {
Ok(()) Ok(())
} }
// #[tokio::test]
// async fn cidr_filter() {
// unimplemented!("never. i aint add what i dont need")
// }
#[tokio::test] #[tokio::test]
async fn cidr_filter() { async fn ipjas() -> anyhow::Result<()> {
unimplemented!("never. i aint add what i dont need") let cuh = address::json::get(None).await?;
println!("{cuh:#?}");
Ok(())
}
#[tokio::test]
async fn ipjas_raw() -> anyhow::Result<()> {
let cuh = address::json::_get(None).await?;
println!("{cuh:#?}");
Ok(())
} }
+2 -1
View File
@@ -1,4 +1,5 @@
[System.Diagnostics.CodeAnalysis.SuppressMessage('PSAvoidDefaultValueSwitchParameter', 'Default true is intentional for fast dev loop')] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidDefaultValueSwitchParameter', "",
Justification = 'Default true is intentional for fast dev loop')]
param( param(
[string]$Pass, [string]$Pass,
[string]$HostName = "192.168.100.1", [string]$HostName = "192.168.100.1",
+3 -3
View File
@@ -34,9 +34,9 @@ ForEach-Object { $_.Matches.Groups[1].Value } |
Get-Item Get-Item
if ($testBinaries.Count -eq 0) { if ($testBinaries.Count -eq 0) {
Write-Error "No test binaries found!" Write-Error "No test binaries found! Exiting..."
Write-Host "Cargo output:" -ForegroundColor Yellow # Write-Host "Cargo output:" -ForegroundColor Yellow
$cargoOutput | ForEach-Object { Write-Host $_ } # $cargoOutput | ForEach-Object { Write-Host $_ }
exit 1 exit 1
} }
+12 -6
View File
@@ -53,13 +53,19 @@ impl From<NUDState> for ipjs_neigh::NUDState {
} }
impl From<NeighborItem> for IpNeighLine { impl From<NeighborItem> for IpNeighLine {
fn from(item: NeighborItem) -> Self { fn from(
NeighborItem {
ip,
dev,
mac,
state,
}: NeighborItem,
) -> Self {
IpNeighLine { IpNeighLine {
ip: item.ip, ip,
dev: Some(item.dev), dev,
mac: item.mac, mac,
state: item state: state
.state
.first() .first()
.copied() .copied()
.map(Into::into) .map(Into::into)
+20 -30
View File
@@ -50,45 +50,35 @@ pub struct Filters {
pub async fn get_status_json( pub async fn get_status_json(
Query(DeviceQuery { Query(DeviceQuery {
name, name,
filter: filter: filters,
Filters {
ips,
devs,
nuds,
macs,
},
.. ..
}): Query<DeviceQuery>, }): Query<DeviceQuery>,
) -> impl IntoResponse { ) -> impl IntoResponse {
match get_macs( match get_macs(
&name.iter().collect::<Vec<_>>(), name.as_slice(),
&ips, &filters.ips,
&devs.iter().collect::<Vec<_>>(), &filters.devs,
&nuds, &filters.nuds,
&macs, &filters.macs,
) )
.await .await
{ {
Ok(table) => { Ok(table) => (
let filters = Filters { StatusCode::OK,
ips, Json(Status {
devs, name,
nuds, table,
macs, filters,
}; }),
( )
StatusCode::OK, .into_response(),
Json(Status {
name,
table,
filters,
}),
)
.into_response()
}
Err(error) => ApiError { Err(error) => ApiError {
code: StatusCode::BAD_GATEWAY, code: StatusCode::BAD_GATEWAY,
error: error.to_string(), error: error
.chain()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(": "),
} }
.into_response(), .into_response(),
} }
+1 -14
View File
@@ -107,20 +107,7 @@ pub async fn get_mac(
.await .await
.context("Calling ip -j neigh failed")?; .context("Calling ip -j neigh failed")?;
let lines = items let lines = items.into_iter().map(Into::into).collect();
.into_iter()
.map(|item| IpNeighLine {
ip: item.ip,
dev: Some(item.dev),
mac: item.mac,
state: item
.state
.first()
.copied()
.map(Into::into)
.unwrap_or(NUDState::None),
})
.collect();
Ok(lines) Ok(lines)
} }