netlink-proto
is an asynchronous implementation of the Netlink
protocol.
Example: listening for audit events
This example shows how to use netlink-proto
with the tokio
runtime to print audit events. It requires extra external
dependencies:
futures = "^0.3"
tokio = "^0.2"
netlink-packet-audit = "^0.1"
use futures::stream::StreamExt;
use netlink_packet_audit::{
NLM_F_ACK, NLM_F_REQUEST, NetlinkMessage, NetlinkPayload,
AuditMessage, StatusMessage,
};
use std::process;
use netlink_proto::{
new_connection,
sys::{Protocol, SocketAddr},
};
const AUDIT_STATUS_ENABLED: u32 = 1;
const AUDIT_STATUS_PID: u32 = 4;
#[tokio::main]
async fn main() -> Result<(), String> {
let (conn, mut handle, mut messages) = new_connection(Protocol::Audit)
.map_err(|e| format!("Failed to create a new netlink connection: {}", e))?;
tokio::spawn(conn);
tokio::spawn(async move {
let mut status = StatusMessage::new();
status.enabled = 1;
status.pid = process::id();
status.mask = AUDIT_STATUS_ENABLED | AUDIT_STATUS_PID;
let payload = AuditMessage::SetStatus(status);
let mut nl_msg = NetlinkMessage::from(payload);
nl_msg.header.flags = NLM_F_REQUEST | NLM_F_ACK;
let kernel_unicast: SocketAddr = SocketAddr::new(0, 0);
let mut response = match handle.request(nl_msg, kernel_unicast) {
Ok(response) => response,
Err(e) => {
eprintln!("{}", e);
return;
}
};
while let Some(message) = response.next().await {
if let NetlinkPayload::Error(err_message) = message.payload {
eprintln!("Received an error message: {:?}", err_message);
return;
}
}
});
println!("Starting to print audit events... press ^C to interrupt");
while let Some((message, _addr)) = messages.next().await {
if let NetlinkPayload::Error(err_message) = message.payload {
eprintln!("received an error message: {:?}", err_message);
} else {
println!("{:?}", message);
}
}
Ok(())
}
Example: dumping all the machine's links
This example shows how to use netlink-proto
with the ROUTE
protocol.
Here we do not use netlink_proto::new_connection()
, and instead
create the socket manually and use call send()
and receive()
directly. In the previous example, the NetlinkFramed
was wrapped
in a Connection
which was polled automatically by the runtime.
use futures::StreamExt;
use netlink_packet_route::{
NLM_F_DUMP, NLM_F_REQUEST, NetlinkMessage, NetlinkHeader, LinkMessage, RtnlMessage
};
use netlink_proto::{
new_connection,
sys::{Protocol, SocketAddr},
};
#[tokio::main]
async fn main() -> Result<(), String> {
let (conn, mut handle, _) = new_connection(Protocol::Route)
.map_err(|e| format!("Failed to create a new netlink connection: {}", e))?;
tokio::spawn(conn);
let msg = NetlinkMessage {
header: NetlinkHeader {
sequence_number: 1,
flags: NLM_F_DUMP | NLM_F_REQUEST,
..Default::default()
},
payload: RtnlMessage::GetLink(LinkMessage::default()).into(),
};
let mut response = handle
.request(msg, SocketAddr::new(0, 0))
.map_err(|e| format!("Failed to send request: {}", e))?;
loop {
if let Some(packet) = response.next().await {
println!("<<< {:?}", packet);
} else {
break;
}
}
Ok(())
}