Skip to content

Commit c0a3390

Browse files
committed
example: netlink crate
1 parent 23d9f94 commit c0a3390

2 files changed

Lines changed: 83 additions & 0 deletions

File tree

examples/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ uds_windows = "0.1.4"
1212
inotify = { version = "0.8.2", default-features = false }
1313
nix = "0.17.0"
1414
timerfd = "1.1.1"
15+
netlink-sys = "0.2"
16+
netlink-packet-core = "0.1"
17+
netlink-packet-route = "0.2"
1518

1619
[dev-dependencies]
1720
anyhow = "1.0.28"
@@ -38,6 +41,10 @@ tokio = { version = "0.2.18", default-features = false }
3841
tungstenite = "0.10.1"
3942
url = "2.1.1"
4043

44+
[[example]]
45+
name = "netlink-route"
46+
path = "netlink-route.rs"
47+
4148
[[example]]
4249
name = "async-h1-client"
4350
path = "async-h1-client.rs"

examples/netlink-route.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use netlink_packet_core::{NetlinkHeader, NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST};
2+
use netlink_packet_route::{rtnl::link::nlas::Nla, LinkMessage, NetlinkPayload, RtnlMessage};
3+
use netlink_sys::{Protocol, Socket, SocketAddr};
4+
use smol::Async;
5+
use std::io;
6+
use std::process;
7+
8+
pub fn align(len: usize) -> usize {
9+
const RTA_ALIGNTO: usize = 4;
10+
11+
((len)+RTA_ALIGNTO-1) & !(RTA_ALIGNTO-1)
12+
}
13+
14+
fn main() -> io::Result<()> {
15+
smol::run(async {
16+
let mut socket = Socket::new(Protocol::Route)?;
17+
socket.bind(&SocketAddr::new(process::id(), 1))?;
18+
let mut socket = Async::new(socket)?;
19+
20+
let mut packet = NetlinkMessage {
21+
header: NetlinkHeader {
22+
sequence_number: 1,
23+
flags: NLM_F_DUMP | NLM_F_REQUEST,
24+
..Default::default()
25+
},
26+
payload: RtnlMessage::GetLink(LinkMessage::default()).into(),
27+
};
28+
packet.finalize();
29+
30+
let mut buf = vec![0; packet.header.length as usize];
31+
packet.serialize(&mut buf[..]);
32+
socket.write_with_mut(|sock| sock.send(&buf, 0)).await?;
33+
34+
'out: loop {
35+
let mut buf = [0; 4096];
36+
let mut cursor = 0;
37+
38+
let (count, _) = socket
39+
.read_with_mut(|sock| sock.recv_from(&mut buf, 0))
40+
.await?;
41+
loop {
42+
if cursor >= count {
43+
break;
44+
}
45+
let msg_len = {
46+
let mut len_buf = [0; 4];
47+
len_buf.copy_from_slice(&buf[cursor..cursor + 4]);
48+
u32::from_ne_bytes(len_buf) as usize
49+
};
50+
let msg_len = align(msg_len);
51+
let reply = NetlinkMessage::<RtnlMessage>::deserialize(&buf[cursor..cursor + msg_len])
52+
.expect("Failed to deserialize message");
53+
match reply.payload {
54+
NetlinkPayload::InnerMessage(RtnlMessage::NewLink(link)) => {
55+
let name = link
56+
.nlas
57+
.iter()
58+
.filter_map(|nla| match nla {
59+
Nla::IfName(name) => Some(name.clone()),
60+
_ => None,
61+
})
62+
.next()
63+
.unwrap();
64+
println!("{}: {}", link.header.index, name);
65+
}
66+
_ => {
67+
break 'out;
68+
}
69+
}
70+
cursor += msg_len;
71+
}
72+
}
73+
74+
Ok(())
75+
})
76+
}

0 commit comments

Comments
 (0)