use nlink::netlink::{Connection, NetworkEvent, Route};
use tokio_stream::StreamExt;
#[tokio::main]
async fn main() -> nlink::netlink::Result<()> {
println!("Monitoring network events (Ctrl+C to stop)...\n");
let conn = Connection::<Route>::new()?;
conn.subscribe_all()?;
let mut events = conn.events().await;
while let Some(result) = events.next().await {
let event = result?;
match event {
NetworkEvent::NewLink(link) => {
println!(
"[LINK+] {} (index={}, mtu={:?}, up={})",
link.name_or("?"),
link.ifindex(),
link.mtu(),
link.is_up()
);
}
NetworkEvent::DelLink(link) => {
println!("[LINK-] {} (index={})", link.name_or("?"), link.ifindex());
}
NetworkEvent::NewAddress(addr) => {
let ip = addr
.address()
.or(addr.local())
.map(|a| a.to_string())
.unwrap_or_else(|| "?".into());
println!(
"[ADDR+] {}/{} on ifindex={}",
ip,
addr.prefix_len(),
addr.ifindex()
);
}
NetworkEvent::DelAddress(addr) => {
let ip = addr
.address()
.or(addr.local())
.map(|a| a.to_string())
.unwrap_or_else(|| "?".into());
println!(
"[ADDR-] {}/{} on ifindex={}",
ip,
addr.prefix_len(),
addr.ifindex()
);
}
NetworkEvent::NewRoute(route) => {
let dst = route
.destination()
.map(|a| format!("{}/{}", a, route.dst_len()))
.unwrap_or_else(|| "default".into());
let via = route
.gateway()
.map(|a| format!(" via {}", a))
.unwrap_or_default();
println!("[ROUTE+] {}{}", dst, via);
}
NetworkEvent::DelRoute(route) => {
let dst = route
.destination()
.map(|a| format!("{}/{}", a, route.dst_len()))
.unwrap_or_else(|| "default".into());
println!("[ROUTE-] {}", dst);
}
NetworkEvent::NewNeighbor(neigh) => {
let ip = neigh
.destination()
.map(|a| a.to_string())
.unwrap_or_else(|| "?".into());
let mac = neigh
.lladdr()
.map(|m| {
format!(
" lladdr {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
m[0], m[1], m[2], m[3], m[4], m[5]
)
})
.unwrap_or_default();
println!("[NEIGH+] {}{} on ifindex={}", ip, mac, neigh.ifindex());
}
NetworkEvent::DelNeighbor(neigh) => {
let ip = neigh
.destination()
.map(|a| a.to_string())
.unwrap_or_else(|| "?".into());
println!("[NEIGH-] {} on ifindex={}", ip, neigh.ifindex());
}
NetworkEvent::NewQdisc(tc) => {
println!(
"[QDISC+] {} on ifindex={}",
tc.kind().unwrap_or("?"),
tc.ifindex()
);
}
NetworkEvent::DelQdisc(tc) => {
println!(
"[QDISC-] {} on ifindex={}",
tc.kind().unwrap_or("?"),
tc.ifindex()
);
}
NetworkEvent::NewClass(tc) => {
println!(
"[CLASS+] {} on ifindex={}",
tc.kind().unwrap_or("?"),
tc.ifindex()
);
}
NetworkEvent::DelClass(tc) => {
println!(
"[CLASS-] {} on ifindex={}",
tc.kind().unwrap_or("?"),
tc.ifindex()
);
}
NetworkEvent::NewFilter(tc) => {
println!(
"[FILTER+] {} on ifindex={}",
tc.kind().unwrap_or("?"),
tc.ifindex()
);
}
NetworkEvent::DelFilter(tc) => {
println!(
"[FILTER-] {} on ifindex={}",
tc.kind().unwrap_or("?"),
tc.ifindex()
);
}
NetworkEvent::NewAction(tc) => {
println!(
"[ACTION+] {} on ifindex={}",
tc.kind().unwrap_or("?"),
tc.ifindex()
);
}
NetworkEvent::DelAction(tc) => {
println!(
"[ACTION-] {} on ifindex={}",
tc.kind().unwrap_or("?"),
tc.ifindex()
);
}
NetworkEvent::NewFdb(fdb) => {
println!(
"[FDB+] {} on ifindex={} vlan={:?}",
fdb.mac_str(),
fdb.ifindex(),
fdb.vlan()
);
}
NetworkEvent::DelFdb(fdb) => {
println!(
"[FDB-] {} on ifindex={} vlan={:?}",
fdb.mac_str(),
fdb.ifindex(),
fdb.vlan()
);
}
NetworkEvent::NewRule(rule) => {
println!(
"[RULE+] prio={} table={} src={:?}",
rule.priority(),
rule.table_id(),
rule.source()
);
}
NetworkEvent::DelRule(rule) => {
println!("[RULE-] prio={} table={}", rule.priority(), rule.table_id());
}
NetworkEvent::NewNexthop(nh) => {
println!(
"[NEXTHOP+] id={} gateway={:?} oif={:?}",
nh.id(),
nh.gateway(),
nh.ifindex()
);
}
NetworkEvent::DelNexthop(nh) => {
println!("[NEXTHOP-] id={}", nh.id());
}
NetworkEvent::NewNsId(ns) => {
println!("[NSID+] nsid={:?} pid={:?}", ns.nsid(), ns.pid());
}
NetworkEvent::DelNsId(ns) => {
println!("[NSID-] nsid={:?}", ns.nsid());
}
NetworkEvent::NewMdb(mdb) => {
println!(
"[MDB+] group={} port_ifindex={} vid={}",
mdb.group, mdb.port_ifindex, mdb.vid
);
}
NetworkEvent::DelMdb(mdb) => {
println!(
"[MDB-] group={} port_ifindex={} vid={}",
mdb.group, mdb.port_ifindex, mdb.vid
);
}
_ => {}
}
}
Ok(())
}