example: netlink crate

This commit is contained in:
Alexander Polakov 2020-06-03 15:14:34 +03:00
parent 23d9f94264
commit 9f3fc1958b
2 changed files with 90 additions and 0 deletions

View File

@ -12,6 +12,9 @@ uds_windows = "0.1.4"
inotify = { version = "0.8.2", default-features = false }
nix = "0.17.0"
timerfd = "1.1.1"
netlink-sys = "0.2"
netlink-packet-core = "0.1"
netlink-packet-route = "0.2"
[dev-dependencies]
anyhow = "1.0.28"
@ -38,6 +41,10 @@ tokio = { version = "0.2.18", default-features = false }
tungstenite = "0.10.1"
url = "2.1.1"
[[example]]
name = "netlink-route"
path = "netlink-route.rs"
[[example]]
name = "async-h1-client"
path = "async-h1-client.rs"

83
examples/netlink-route.rs Normal file
View File

@ -0,0 +1,83 @@
use std::io;
#[cfg(not(target_os = "linux"))]
fn main() {
println!("This example works only on Linux!");
}
#[cfg(target_os = "linux")]
fn main() -> io::Result<()> {
use netlink_packet_core::{NetlinkHeader, NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST};
use netlink_packet_route::{rtnl::link::nlas::Nla, LinkMessage, NetlinkPayload, RtnlMessage};
use netlink_sys::{Protocol, Socket, SocketAddr};
use smol::Async;
use std::process;
fn align(len: usize) -> usize {
const RTA_ALIGNTO: usize = 4;
((len)+RTA_ALIGNTO-1) & !(RTA_ALIGNTO-1)
}
smol::run(async {
let mut socket = Socket::new(Protocol::Route)?;
socket.bind(&SocketAddr::new(process::id(), 1))?;
let mut socket = Async::new(socket)?;
let mut packet = NetlinkMessage {
header: NetlinkHeader {
sequence_number: 1,
flags: NLM_F_DUMP | NLM_F_REQUEST,
..Default::default()
},
payload: RtnlMessage::GetLink(LinkMessage::default()).into(),
};
packet.finalize();
let mut buf = vec![0; packet.header.length as usize];
packet.serialize(&mut buf[..]);
socket.write_with_mut(|sock| sock.send(&buf, 0)).await?;
'out: loop {
let mut buf = [0; 4096];
let mut cursor = 0;
let (count, _) = socket
.read_with_mut(|sock| sock.recv_from(&mut buf, 0))
.await?;
loop {
if cursor >= count {
break;
}
let msg_len = {
let mut len_buf = [0; 4];
len_buf.copy_from_slice(&buf[cursor..cursor + 4]);
u32::from_ne_bytes(len_buf) as usize
};
let msg_len = align(msg_len);
let reply = NetlinkMessage::<RtnlMessage>::deserialize(&buf[cursor..cursor + msg_len])
.expect("Failed to deserialize message");
match reply.payload {
NetlinkPayload::InnerMessage(RtnlMessage::NewLink(link)) => {
let name = link
.nlas
.iter()
.filter_map(|nla| match nla {
Nla::IfName(name) => Some(name.clone()),
_ => None,
})
.next()
.unwrap();
println!("{}: {}", link.header.index, name);
}
_ => {
break 'out;
}
}
cursor += msg_len;
}
}
Ok(())
})
}