Skip to content

Commit 9f3fc19

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

2 files changed

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

0 commit comments

Comments
 (0)