Thanks to visit codestin.com
Credit goes to lib.rs

23 unstable releases

0.12.0 Aug 27, 2025
0.11.5 Jan 26, 2025
0.11.3 Jan 29, 2024
0.11.2 Jul 9, 2023
0.1.1 Jan 2, 2019

#655 in Network programming

Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App

695,689 downloads per month
Used in 737 crates (19 directly)

MIT license

49KB
924 lines

Rust async netlink protocol

The netlink-proto crate is an asynchronous implementation of the netlink protocol. It only depends on netlink-packet-core for the NetlinkMessage type and netlink-sys for the socket.


lib.rs:

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 = "^1.0"
  • netlink-packet-audit = "^0.1"
use futures::stream::StreamExt;
use netlink_packet_core::{NetlinkMessage, NetlinkPayload, NLM_F_ACK,
    NLM_F_REQUEST};
use netlink_packet_audit::{
    AuditMessage,
    StatusMessage,
};
use std::process;

use netlink_proto::{
    new_connection,
    sys::{protocols::NETLINK_AUDIT, SocketAddr},
};

const AUDIT_STATUS_ENABLED: u32 = 1;
const AUDIT_STATUS_PID: u32 = 4;

#[tokio::main]
async fn main() -> Result<(), String> {
    // Create a netlink socket. Here:
    //
    // - `conn` is a `Connection` that has the netlink socket. It's a
    //   `Future` that keeps polling the socket and must be spawned an
    //   the event loop.
    //
    // - `handle` is a `Handle` to the `Connection`. We use it to send
    //   netlink messages and receive responses to these messages.
    //
    // - `messages` is a channel receiver through which we receive
    //   messages that we have not solicited, ie that are not
    //   response to a request we made. In this example, we'll receive
    //   the audit event through that channel.
    let (conn, mut handle, mut messages) = new_connection(NETLINK_AUDIT)
        .map_err(|e| format!("Failed to create a new netlink connection: {}", e))?;

    // Spawn the `Connection` so that it starts polling the netlink
    // socket in the background.
    tokio::spawn(conn);

    // Use the `ConnectionHandle` to send a request to the kernel
    // asking it to start multicasting audit event messages.
    tokio::spawn(async move {
        // Craft the packet to enable audit events
        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;

        // We'll send unicast messages to the kernel.
        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;
            }
        }
    });

    // Finally, start receiving event through the `messages` channel.
    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::{link::LinkMessage, RouteNetlinkMessage};
use netlink_packet_core::{
    NetlinkHeader,
    NetlinkMessage,
    NLM_F_REQUEST, NLM_F_DUMP
};

use netlink_proto::{
    new_connection,
    sys::{protocols::NETLINK_ROUTE, SocketAddr},
};

#[tokio::main]
async fn main() -> Result<(), String> {
    // Create the netlink socket. Here, we won't use the channel that
    // receives unsolicited messages.
    let (conn, mut handle, _) = new_connection(NETLINK_ROUTE)
        .map_err(|e| format!("Failed to create a new netlink connection: {}", e))?;

    // Spawn the `Connection` in the background
    tokio::spawn(conn);

    // Create the netlink message that requests the links to be dumped
    let mut nl_hdr = NetlinkHeader::default();
    nl_hdr.flags = NLM_F_DUMP | NLM_F_REQUEST;

    let msg = NetlinkMessage::new(
        nl_hdr,
        RouteNetlinkMessage::GetLink(LinkMessage::default()).into(),
    );

    // Send the request
    let mut response = handle
        .request(msg, SocketAddr::new(0, 0))
        .map_err(|e| format!("Failed to send request: {}", e))?;

    // Print all the messages received in response
    loop {
        if let Some(packet) = response.next().await {
            println!("<<< {:?}", packet);
        } else {
            break;
        }
    }

    Ok(())
}

Dependencies

~1–15MB
~163K SLoC