Skip to main content

Connection

Struct Connection 

Source
pub struct Connection<P: ProtocolState> { /* private fields */ }
Expand description

High-level netlink connection parameterized by protocol state.

The type parameter P determines which protocol this connection uses and which methods are available:

§Example

use nlink::netlink::{Connection, Route, Generic};

// Route protocol connection
let route = Connection::<Route>::new()?;
route.get_links().await?;

// Generic netlink connection
let genl = Connection::<Generic>::new()?;
genl.get_family("wireguard").await?;

Implementations§

Source§

impl Connection<Route>

Source

pub async fn add_address<A: AddressConfig>(&self, config: A) -> Result<()>

Add an IP address to an interface.

This method is namespace-safe: interface names are resolved via netlink, which queries the namespace that this connection is bound to.

§Example
use nlink::netlink::addr::{Ipv4Address, Ipv6Address};
use std::net::{Ipv4Addr, Ipv6Addr};

// Add IPv4 address
conn.add_address(
    Ipv4Address::new("eth0", Ipv4Addr::new(192, 168, 1, 100), 24)
).await?;

// Add IPv6 address
conn.add_address(
    Ipv6Address::new("eth0", "2001:db8::1".parse()?, 64)
).await?;
Source

pub async fn del_address( &self, ifname: impl Into<InterfaceRef>, address: IpAddr, prefix_len: u8, ) -> Result<()>

Delete an IP address from an interface.

§Example
conn.del_address("eth0", IpAddr::V4(Ipv4Addr::new(192, 168, 1, 100)), 24).await?;
Source

pub async fn del_address_by_index( &self, ifindex: u32, address: IpAddr, prefix_len: u8, ) -> Result<()>

Delete an IP address from an interface by index.

This is namespace-safe as it doesn’t require interface name resolution.

Source

pub async fn add_address_by_index( &self, ifindex: u32, address: IpAddr, prefix_len: u8, ) -> Result<()>

Add an IP address to an interface by index.

This is namespace-safe as it doesn’t require interface name resolution.

§Example
// Get interface index via netlink
let link = conn.get_link_by_name("eth0").await?.unwrap();

// Add address by index
conn.add_address_by_index(link.ifindex(), "192.168.1.100".parse()?, 24).await?;
Source

pub async fn replace_address_by_index( &self, ifindex: u32, address: IpAddr, prefix_len: u8, ) -> Result<()>

Replace an IP address on an interface by index.

This is namespace-safe as it doesn’t require interface name resolution.

Source

pub async fn add_address_by_name( &self, ifname: impl Into<InterfaceRef>, address: IpAddr, prefix_len: u8, ) -> Result<()>

Add an IP address to an interface by name.

This is a convenience method that resolves the interface name internally.

§Example
conn.add_address_by_name("eth0", "192.168.1.100".parse()?, 24).await?;
Source

pub async fn replace_address_by_name( &self, ifname: impl Into<InterfaceRef>, address: IpAddr, prefix_len: u8, ) -> Result<()>

Replace an IP address on an interface by name.

This is a convenience method that resolves the interface name internally. If the address exists, it will be updated; otherwise it will be created.

§Example
conn.replace_address_by_name("eth0", "192.168.1.100".parse()?, 24).await?;
Source

pub async fn del_address_v4( &self, ifname: impl Into<InterfaceRef>, address: Ipv4Addr, prefix_len: u8, ) -> Result<()>

Delete an IPv4 address from an interface.

Source

pub async fn del_address_v6( &self, ifname: impl Into<InterfaceRef>, address: Ipv6Addr, prefix_len: u8, ) -> Result<()>

Delete an IPv6 address from an interface.

Source

pub async fn del_address_config<A: AddressConfig>( &self, config: A, ) -> Result<()>

Delete an IP address using a typed config.

Source

pub async fn replace_address<A: AddressConfig>(&self, config: A) -> Result<()>

Replace an IP address (add or update).

This is like add_address but will update if the address exists.

§Example
// Update address properties (lifetimes, etc.)
conn.replace_address(
    Ipv4Address::new("eth0", Ipv4Addr::new(192, 168, 1, 100), 24)
        .preferred_lifetime(3600)
        .valid_lifetime(7200)
).await?;
Source

pub async fn flush_addresses( &self, ifname: impl Into<InterfaceRef>, ) -> Result<()>

Flush all addresses from an interface.

§Example
conn.flush_addresses("eth0").await?;
Source

pub async fn flush_addresses_by_index(&self, ifindex: u32) -> Result<()>

Flush all addresses from an interface by index.

This is namespace-safe as it doesn’t require interface name resolution.

Source§

impl Connection<Audit>

Source

pub fn new() -> Result<Self>

Create a new Audit connection.

§Example
use nlink::netlink::{Connection, Audit};

let conn = Connection::<Audit>::new()?;
Source

pub async fn get_status(&self) -> Result<AuditStatus>

Get the current audit status.

§Example
use nlink::netlink::{Connection, Audit};

let conn = Connection::<Audit>::new()?;
let status = conn.get_status().await?;

println!("Audit enabled: {}", status.is_enabled());
println!("Audit locked: {}", status.is_locked());
println!("Failure mode: {:?}", status.failure_mode());
println!("Audit daemon PID: {}", status.pid);
println!("Rate limit: {} msgs/sec", status.rate_limit);
println!("Backlog: {}/{}", status.backlog, status.backlog_limit);
println!("Lost messages: {}", status.lost);
Source

pub async fn get_tty_status(&self) -> Result<AuditTtyStatus>

Get the TTY auditing status.

§Example
use nlink::netlink::{Connection, Audit};

let conn = Connection::<Audit>::new()?;
let tty_status = conn.get_tty_status().await?;

println!("TTY auditing enabled: {}", tty_status.enabled != 0);
println!("Log passwords: {}", tty_status.log_passwd != 0);
Source

pub async fn get_features(&self) -> Result<AuditFeatures>

Get audit features.

§Example
use nlink::netlink::{Connection, Audit};

let conn = Connection::<Audit>::new()?;
let features = conn.get_features().await?;

println!("Version: {}", features.vers);
println!("Features: 0x{:08x}", features.features);
println!("Mask: 0x{:08x}", features.mask);
Source§

impl Connection<Route>

Source

pub async fn get_bridge_vlans( &self, dev: impl Into<InterfaceRef>, ) -> Result<Vec<BridgeVlanEntry>>

Get VLAN configuration for a bridge port.

Returns all VLANs configured on the specified interface.

§Example
let vlans = conn.get_bridge_vlans("eth0").await?;
for vlan in &vlans {
    println!("VLAN {}: pvid={} untagged={}",
        vlan.vid, vlan.flags.pvid, vlan.flags.untagged);
}
Source

pub async fn get_bridge_vlans_by_index( &self, ifindex: u32, ) -> Result<Vec<BridgeVlanEntry>>

Get VLAN configuration for a bridge port by interface index.

Use this method when operating in a network namespace.

Source

pub async fn get_bridge_vlans_all( &self, bridge: impl Into<InterfaceRef>, ) -> Result<Vec<BridgeVlanEntry>>

Get VLAN configuration for all ports of a bridge.

Returns VLANs for all interfaces that are part of the bridge.

§Example
let vlans = conn.get_bridge_vlans_all("br0").await?;
for vlan in &vlans {
    println!("ifindex {}: VLAN {}", vlan.ifindex, vlan.vid);
}
Source

pub async fn get_bridge_vlans_all_by_index( &self, bridge_idx: u32, ) -> Result<Vec<BridgeVlanEntry>>

Get VLAN configuration for all ports of a bridge by interface index.

Source

pub async fn add_bridge_vlan(&self, config: BridgeVlanBuilder) -> Result<()>

Add VLAN to a bridge port.

§Example
use nlink::netlink::bridge_vlan::BridgeVlanBuilder;

// Add VLAN 100 as PVID and untagged (native VLAN)
conn.add_bridge_vlan(
    BridgeVlanBuilder::new(100)
        .dev("eth0")
        .pvid()
        .untagged()
).await?;

// Add VLAN range 200-210 as tagged
conn.add_bridge_vlan(
    BridgeVlanBuilder::new(200)
        .dev("eth0")
        .range(210)
).await?;
Source

pub async fn del_bridge_vlan( &self, dev: impl Into<InterfaceRef>, vid: u16, ) -> Result<()>

Delete VLAN from a bridge port.

§Example
conn.del_bridge_vlan("eth0", 100).await?;
Source

pub async fn del_bridge_vlan_by_index( &self, ifindex: u32, vid: u16, ) -> Result<()>

Delete VLAN from a bridge port by interface index.

Source

pub async fn del_bridge_vlan_range( &self, dev: impl Into<InterfaceRef>, vid_start: u16, vid_end: u16, ) -> Result<()>

Delete a range of VLANs from a bridge port.

§Example
conn.del_bridge_vlan_range("eth0", 200, 210).await?;
Source

pub async fn set_bridge_pvid( &self, dev: impl Into<InterfaceRef>, vid: u16, ) -> Result<()>

Set PVID for a bridge port.

This adds the VLAN as PVID and untagged, which is the typical configuration for a native VLAN.

§Example
conn.set_bridge_pvid("eth0", 100).await?;
Source

pub async fn set_bridge_pvid_by_index( &self, ifindex: u32, vid: u16, ) -> Result<()>

Set PVID for a bridge port by interface index.

Source

pub async fn add_bridge_vlan_tagged( &self, dev: impl Into<InterfaceRef>, vid: u16, ) -> Result<()>

Add a tagged VLAN to a bridge port.

This is a convenience method for adding a VLAN without PVID or untagged flags.

§Example
conn.add_bridge_vlan_tagged("eth0", 200).await?;
Source

pub async fn add_bridge_vlan_range( &self, dev: impl Into<InterfaceRef>, vid_start: u16, vid_end: u16, ) -> Result<()>

Add a range of tagged VLANs to a bridge port.

§Example
conn.add_bridge_vlan_range("eth0", 200, 210).await?;
Source

pub async fn get_vlan_tunnels( &self, dev: impl Into<InterfaceRef>, ) -> Result<Vec<BridgeVlanTunnelEntry>>

Get VLAN-to-tunnel ID mappings for a bridge port.

Returns all VLAN-to-VNI mappings configured on the specified interface. This is typically used on VXLAN bridge ports.

§Example
let tunnels = conn.get_vlan_tunnels("vxlan0").await?;
for t in &tunnels {
    println!("VLAN {} -> VNI {}", t.vid, t.tunnel_id);
}
Source

pub async fn get_vlan_tunnels_by_index( &self, ifindex: u32, ) -> Result<Vec<BridgeVlanTunnelEntry>>

Get VLAN-to-tunnel ID mappings by interface index.

Use this method when operating in a network namespace.

Source

pub async fn add_vlan_tunnel( &self, config: BridgeVlanTunnelBuilder, ) -> Result<()>

Add VLAN-to-tunnel ID mapping.

Creates a mapping between a VLAN ID and a tunnel ID (VNI) on a VXLAN bridge port.

§Example
use nlink::netlink::bridge_vlan::BridgeVlanTunnelBuilder;

// Map VLAN 100 to VNI 10000
conn.add_vlan_tunnel(
    BridgeVlanTunnelBuilder::new(100, 10000)
        .dev("vxlan0")
).await?;

// Map VLAN range 200-210 to VNI range 20000-20010
conn.add_vlan_tunnel(
    BridgeVlanTunnelBuilder::new(200, 20000)
        .dev("vxlan0")
        .range(210)
).await?;
Source

pub async fn del_vlan_tunnel( &self, dev: impl Into<InterfaceRef>, vid: u16, ) -> Result<()>

Delete VLAN-to-tunnel ID mapping.

§Example
conn.del_vlan_tunnel("vxlan0", 100).await?;
Source

pub async fn del_vlan_tunnel_by_index( &self, ifindex: u32, vid: u16, ) -> Result<()>

Delete VLAN-to-tunnel ID mapping by interface index.

Source

pub async fn del_vlan_tunnel_range( &self, dev: impl Into<InterfaceRef>, vid_start: u16, vid_end: u16, ) -> Result<()>

Delete a range of VLAN-to-tunnel ID mappings.

§Example
conn.del_vlan_tunnel_range("vxlan0", 200, 210).await?;
Source§

impl<P: ProtocolState + Default> Connection<P>

Source

pub fn new() -> Result<Self>

Create a new connection for this protocol type.

This is available for protocols that implement Default. For protocols that require special initialization (like Connector, KobjectUevent, or Wireguard), use their specific constructors.

§Example
use nlink::netlink::{Connection, Route, Generic};

let route = Connection::<Route>::new()?;
let genl = Connection::<Generic>::new()?;
Source

pub fn new_in_namespace(ns_fd: RawFd) -> Result<Self>

Create a connection that operates in a specific network namespace.

The namespace is specified by an open file descriptor to a namespace file (e.g., /proc/<pid>/ns/net or /var/run/netns/<name>).

§Example
use std::fs::File;
use std::os::unix::io::AsRawFd;
use nlink::netlink::{Connection, Route};

let ns_file = File::open("/var/run/netns/myns")?;
let conn = Connection::<Route>::new_in_namespace(ns_file.as_raw_fd())?;

// All operations now occur in the "myns" namespace
let links = conn.get_links().await?;
Source

pub fn new_in_namespace_path<T: AsRef<Path>>(ns_path: T) -> Result<Self>

Create a connection that operates in a network namespace specified by path.

§Example
use nlink::netlink::{Connection, Route};

// For a named namespace (created via `ip netns add myns`)
let conn = Connection::<Route>::new_in_namespace_path("/var/run/netns/myns")?;

// For a container's namespace
let conn = Connection::<Route>::new_in_namespace_path("/proc/1234/ns/net")?;

// Query interfaces in that namespace
let links = conn.get_links().await?;
Source§

impl<P: ProtocolState> Connection<P>

Source

pub fn socket(&self) -> &NetlinkSocket

Get the underlying socket.

Source

pub fn state(&self) -> &P

Get the protocol state.

Source

pub fn timeout(self, timeout: Duration) -> Self

Set a default timeout for all netlink operations.

Operations that exceed the timeout return Error::Timeout. By default, no timeout is set and operations wait indefinitely.

§Example
use nlink::{Connection, Route};
use std::time::Duration;

let conn = Connection::<Route>::new()?
    .timeout(Duration::from_secs(5));
Source

pub fn no_timeout(self) -> Self

Clear the timeout (operations will wait indefinitely).

Source

pub fn get_timeout(&self) -> Option<Duration>

Get the configured timeout.

Source§

impl Connection<Route>

Source

pub fn for_namespace(spec: NamespaceSpec<'_>) -> Result<Self>

Create a connection for the specified namespace.

This is a convenience method that creates a Route protocol connection for any namespace specification.

§Example
use nlink::netlink::{Connection, Route};
use nlink::netlink::namespace::NamespaceSpec;

// For a named namespace
let conn = Connection::<Route>::for_namespace(NamespaceSpec::Named("myns"))?;

// For a container by PID
let conn = Connection::<Route>::for_namespace(NamespaceSpec::Pid(1234))?;

// For the default namespace
let conn = Connection::<Route>::for_namespace(NamespaceSpec::Default)?;
Source

pub fn subscribe(&mut self, groups: &[RtnetlinkGroup]) -> Result<()>

Subscribe to multicast groups for event notifications.

§Example
use nlink::netlink::{Connection, Route, RtnetlinkGroup};

let mut conn = Connection::<Route>::new()?;
conn.subscribe(&[RtnetlinkGroup::Link, RtnetlinkGroup::Tc])?;
Source

pub fn subscribe_all(&mut self) -> Result<()>

Subscribe to all commonly-used event groups.

Subscribes to: Link, Ipv4Addr, Ipv6Addr, Ipv4Route, Ipv6Route, Neigh, Tc.

§Example
use nlink::netlink::{Connection, Route};

let mut conn = Connection::<Route>::new()?;
conn.subscribe_all()?;
let mut events = conn.events();
Source

pub async fn dump_typed<T: FromNetlink>(&self, msg_type: u16) -> Result<Vec<T>>

Send a dump request and parse all responses into typed messages.

This is a convenience method that combines dump() with parsing. The type T must implement FromNetlink::write_dump_header to provide the required message header (e.g., IfInfoMsg for links, IfAddrMsg for addresses).

§Example
use nlink::netlink::messages::AddressMessage;
use nlink::netlink::message::NlMsgType;

let addresses: Vec<AddressMessage> = conn.dump_typed(NlMsgType::RTM_GETADDR).await?;
for addr in addresses {
    println!("{}: {:?}", addr.ifindex(), addr.address);
}
Source

pub fn parse_response<T: FromNetlink>(&self, response: &[u8]) -> Result<T>

Parse a single response into a typed message.

Source§

impl Connection<Route>

Source

pub fn batch(&self) -> Batch<'_>

Create a batch for executing multiple operations in minimal syscalls.

Operations are buffered and sent as concatenated messages in a single sendmsg(). The kernel processes them sequentially and returns one ACK per message.

§Example
use nlink::netlink::{Connection, Route};
use nlink::netlink::route::Ipv4Route;

let conn = Connection::<Route>::new()?;
let results = conn.batch()
    .add_route(Ipv4Route::new("10.0.0.0", 8).dev_index(5))
    .add_route(Ipv4Route::new("10.1.0.0", 16).dev_index(5))
    .execute()
    .await?;
Source§

impl Connection<Route>

Get all network interfaces.

§Example
let links = conn.get_links().await?;
for link in links {
    println!("{}: {}", link.ifindex(), link.name.as_deref().unwrap_or("?"));
}

Get a network interface by name.

Returns None if the interface doesn’t exist.

Get a network interface by index.

Returns None if the interface doesn’t exist.

Source

pub async fn resolve_interface(&self, iface: &InterfaceRef) -> Result<u32>

Resolve an interface reference to an index.

This method is namespace-safe: it uses netlink to resolve interface names, which queries the namespace that this connection is bound to.

  • If the reference is already an index, returns it directly.
  • If the reference is a name, queries the kernel via netlink.
§Errors

Returns Error::InterfaceNotFound if the interface name doesn’t exist.

§Example
use nlink::netlink::{Connection, Route, InterfaceRef};

let conn = Connection::<Route>::new()?;

// Resolve a name
let ifindex = conn.resolve_interface(&InterfaceRef::name("eth0")).await?;

// Pass-through an index
let ifindex = conn.resolve_interface(&InterfaceRef::index(2)).await?;
assert_eq!(ifindex, 2);
Source

pub async fn resolve_interface_opt( &self, iface: Option<&InterfaceRef>, ) -> Result<Option<u32>>

Resolve an optional interface reference.

Returns None if the input is None, otherwise resolves the reference.

Source

pub async fn get_interface_names(&self) -> Result<HashMap<u32, String>>

Build a map of interface index to name.

This is a convenience method for code that needs to look up interface names by index (e.g., when displaying addresses, routes, or TC objects).

§Example
let names = conn.get_interface_names().await?;
let addresses = conn.get_addresses().await?;
for addr in addresses {
    let name = names.get(&addr.ifindex()).map(|s| s.as_str()).unwrap_or("?");
    println!("{}: {:?}", name, addr.address);
}
Source

pub async fn interface_name(&self, ifindex: u32) -> Result<Option<String>>

Get interface name by index.

This is a convenience method for getting a single interface name. For looking up multiple names, prefer [get_interface_names()] to build a lookup map.

Returns None if no interface with that index exists.

§Example
if let Some(name) = conn.interface_name(route.oif.unwrap()).await? {
    println!("Route via {}", name);
}
Source

pub async fn interface_name_or( &self, ifindex: u32, default: &str, ) -> Result<String>

Get interface name by index, or return a default value.

This is a convenience method for display purposes when you want a fallback value like “-” or “?” for unknown interfaces.

§Example
let dev = conn.interface_name_or(route.oif.unwrap_or(0), "-").await?;
println!("Route via {}", dev);
Source

pub async fn get_bond_info( &self, iface: impl Into<InterfaceRef>, ) -> Result<BondInfo>

Get bond information for a bond interface.

Returns the bond configuration as reported by the kernel.

§Errors

Returns an error if the interface doesn’t exist or is not a bond.

§Example
let info = conn.get_bond_info("bond0").await?;
println!("Mode: {:?}, miimon: {}ms", info.bond_mode(), info.miimon);
Source

pub async fn get_bond_slaves( &self, bond: impl Into<InterfaceRef>, ) -> Result<Vec<(LinkMessage, BondSlaveInfo)>>

List all slaves of a bond interface with their status.

Returns a list of (LinkMessage, BondSlaveInfo) pairs for each slave.

§Example
let slaves = conn.get_bond_slaves("bond0").await?;
for (link, info) in &slaves {
    println!("{}: state={:?}, mii={:?}",
        link.name_or("?"), info.state, info.mii_status);
}
Source

pub async fn get_addresses(&self) -> Result<Vec<AddressMessage>>

Get all IP addresses.

§Example
let addresses = conn.get_addresses().await?;
for addr in addresses {
    println!("{:?}/{} on idx {}", addr.address, addr.prefix_len(), addr.ifindex());
}
Source

pub async fn get_addresses_by_name( &self, iface: impl Into<InterfaceRef>, ) -> Result<Vec<AddressMessage>>

Get IP addresses for a specific interface.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn get_addresses_by_index( &self, ifindex: u32, ) -> Result<Vec<AddressMessage>>

Get IP addresses for a specific interface by index.

Source

pub async fn get_address_by_ip( &self, addr: IpAddr, ) -> Result<Option<AddressMessage>>

Get an address entry by IP address.

Returns None if no address entry matches the given IP.

§Example
use std::net::IpAddr;

let ip: IpAddr = "192.168.1.100".parse()?;
if let Some(addr) = conn.get_address_by_ip(ip).await? {
    println!("Found on interface index {}", addr.ifindex());
}
Source

pub async fn get_routes(&self) -> Result<Vec<RouteMessage>>

Get all routes.

§Example
let routes = conn.get_routes().await?;
for route in routes {
    println!("{:?}/{}", route.destination(), route.dst_len());
}
Source

pub async fn get_routes_for_table( &self, table_id: u32, ) -> Result<Vec<RouteMessage>>

Get routes for a specific table.

Source

pub async fn get_route_v4( &self, destination: Ipv4Addr, prefix_len: u8, ) -> Result<Option<RouteMessage>>

Get a specific IPv4 route by destination and prefix length.

Uses RTM_GETROUTE without NLM_F_DUMP to query the kernel directly, which is more efficient than dumping all routes for large routing tables.

Returns None if no matching route is found.

§Example
use std::net::Ipv4Addr;

// Look up route to 10.0.0.0/8
if let Some(route) = conn.get_route_v4(Ipv4Addr::new(10, 0, 0, 0), 8).await? {
    println!("Gateway: {:?}", route.gateway);
}
Source

pub async fn get_route_v6( &self, destination: Ipv6Addr, prefix_len: u8, ) -> Result<Option<RouteMessage>>

Get a specific IPv6 route by destination and prefix length.

Uses RTM_GETROUTE without NLM_F_DUMP to query the kernel directly, which is more efficient than dumping all routes for large routing tables.

Returns None if no matching route is found.

§Example
use std::net::Ipv6Addr;

// Look up route to 2001:db8::/32
let dest: Ipv6Addr = "2001:db8::".parse()?;
if let Some(route) = conn.get_route_v6(dest, 32).await? {
    println!("Gateway: {:?}", route.gateway);
}
Source

pub async fn get_neighbors(&self) -> Result<Vec<NeighborMessage>>

Get all neighbor entries.

§Example
let neighbors = conn.get_neighbors().await?;
for neigh in neighbors {
    println!("{:?} -> {:?}", neigh.destination, neigh.lladdr);
}
Source

pub async fn get_neighbors_by_name( &self, iface: impl Into<InterfaceRef>, ) -> Result<Vec<NeighborMessage>>

Get neighbor entries for a specific interface.

Accepts either an interface name or index via InterfaceRef.

See also get_neighbors_by_index in the neighbor module.

Source

pub async fn get_rules(&self) -> Result<Vec<RuleMessage>>

Get all routing rules.

§Example
let rules = conn.get_rules().await?;
for rule in rules {
    println!("{}: {:?} -> table {}", rule.priority, rule.source, rule.table);
}
Source

pub async fn get_rules_for_family(&self, family: u8) -> Result<Vec<RuleMessage>>

Get routing rules for a specific address family.

§Arguments
  • family - Address family: libc::AF_INET for IPv4, libc::AF_INET6 for IPv6
Source

pub async fn get_rules_v4(&self) -> Result<Vec<RuleMessage>>

Get IPv4 routing rules.

Source

pub async fn get_rules_v6(&self) -> Result<Vec<RuleMessage>>

Get IPv6 routing rules.

Source

pub async fn add_rule(&self, rule: RuleBuilder) -> Result<()>

Add a routing rule.

Use the super::rule::RuleBuilder to construct the rule.

§Example
use nlink::netlink::rule::RuleBuilder;

// Add a rule to lookup table 100 for traffic from 10.0.0.0/8
conn.add_rule(
    RuleBuilder::v4()
        .priority(100)
        .from("10.0.0.0", 8)
        .table(100)
).await?;
Source

pub async fn del_rule(&self, rule: RuleBuilder) -> Result<()>

Delete a routing rule.

§Example
use nlink::netlink::rule::RuleBuilder;

conn.del_rule(
    RuleBuilder::v4()
        .priority(100)
).await?;
Source

pub async fn del_rule_by_priority( &self, family: u8, priority: u32, ) -> Result<()>

Delete a rule by priority.

Source

pub async fn flush_rules(&self, family: u8) -> Result<()>

Flush all non-default routing rules for a family.

This deletes all rules except the default ones (priority 0, 32766, 32767).

Source

pub async fn get_qdiscs(&self) -> Result<Vec<TcMessage>>

Get all qdiscs.

§Example
let qdiscs = conn.get_qdiscs().await?;
for qdisc in qdiscs {
    println!("{}: {}", qdisc.ifindex(), qdisc.kind().unwrap_or("?"));
}
Source

pub async fn get_qdiscs_by_name( &self, iface: impl Into<InterfaceRef>, ) -> Result<Vec<TcMessage>>

Get qdiscs for a specific interface.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn get_qdiscs_by_index(&self, ifindex: u32) -> Result<Vec<TcMessage>>

Get qdiscs for a specific interface by index.

Source

pub async fn get_classes(&self) -> Result<Vec<TcMessage>>

Get all TC classes.

Source

pub async fn get_classes_by_name( &self, iface: impl Into<InterfaceRef>, ) -> Result<Vec<TcMessage>>

Get TC classes for a specific interface.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn get_classes_by_index(&self, ifindex: u32) -> Result<Vec<TcMessage>>

Get TC classes for a specific interface by index.

Source

pub async fn get_filters(&self) -> Result<Vec<TcMessage>>

Get all TC filters.

Source

pub async fn get_filters_by_name( &self, iface: impl Into<InterfaceRef>, ) -> Result<Vec<TcMessage>>

Get TC filters for a specific interface.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn get_filters_by_index(&self, ifindex: u32) -> Result<Vec<TcMessage>>

Get TC filters for a specific interface by index.

Source

pub async fn get_tc_chains( &self, ifname: impl Into<InterfaceRef>, parent: &str, ) -> Result<Vec<u32>>

Get all TC filter chains for an interface.

Filter chains provide logical grouping of filters for better performance and organization (Linux 4.1+).

§Example
let chains = conn.get_tc_chains("eth0", "ingress").await?;
for chain in chains {
    println!("Chain: {}", chain);
}
Source

pub async fn get_tc_chains_by_index( &self, ifindex: u32, parent: &str, ) -> Result<Vec<u32>>

Get all TC filter chains for an interface by index.

Source

pub async fn add_tc_chain( &self, ifname: impl Into<InterfaceRef>, parent: &str, chain: u32, ) -> Result<()>

Add a TC filter chain.

Chains provide logical grouping of filters (Linux 4.1+). Chain 0 is created automatically when adding filters.

§Example
// Create chain 100 on ingress qdisc
conn.add_tc_chain("eth0", "ingress", 100).await?;
Source

pub async fn add_tc_chain_by_index( &self, ifindex: u32, parent: &str, chain: u32, ) -> Result<()>

Add a TC filter chain by interface index.

Source

pub async fn del_tc_chain( &self, ifname: impl Into<InterfaceRef>, parent: &str, chain: u32, ) -> Result<()>

Delete a TC filter chain.

All filters in the chain must be deleted before the chain can be removed.

§Example
conn.del_tc_chain("eth0", "ingress", 100).await?;
Source

pub async fn del_tc_chain_by_index( &self, ifindex: u32, parent: &str, chain: u32, ) -> Result<()>

Delete a TC filter chain by interface index.

Source

pub async fn get_root_qdisc_by_name( &self, iface: impl Into<InterfaceRef>, ) -> Result<Option<TcMessage>>

Get the root qdisc for an interface (parent == ROOT).

Returns None if no root qdisc is configured.

Accepts either an interface name or index via InterfaceRef.

§Example
if let Some(root) = conn.get_root_qdisc_by_name("eth0").await? {
    println!("Root qdisc: {}", root.kind().unwrap_or("?"));
}
Source

pub async fn get_root_qdisc_by_index( &self, ifindex: u32, ) -> Result<Option<TcMessage>>

Get the root qdisc for an interface by index.

Returns None if no root qdisc is configured.

Source

pub async fn get_qdisc_by_handle( &self, ifname: &str, handle: &str, ) -> Result<Option<TcMessage>>

Get a qdisc by interface name and handle.

§Example
// Get the qdisc with handle 1:0 on eth0
if let Some(qdisc) = conn.get_qdisc_by_handle("eth0", "1:").await? {
    println!("Found qdisc: {}", qdisc.kind().unwrap_or("?"));
}
Source

pub async fn get_qdisc_by_handle_index( &self, ifindex: u32, handle: &str, ) -> Result<Option<TcMessage>>

Get a qdisc by interface index and handle.

§Example
// Get the qdisc with handle 1:0 on interface index 2
if let Some(qdisc) = conn.get_qdisc_by_handle_index(2, "1:").await? {
    println!("Found qdisc: {}", qdisc.kind().unwrap_or("?"));
}
Source

pub async fn get_netem_by_name( &self, iface: impl Into<InterfaceRef>, ) -> Result<Option<NetemOptions>>

Get netem options for an interface, if a netem qdisc is configured at root.

This is a convenience method that returns Some only if a netem qdisc is the root qdisc and its options can be parsed.

Accepts either an interface name or index via InterfaceRef.

§Example
if let Some(netem) = conn.get_netem_by_name("eth0").await? {
    if let Some(delay) = netem.delay() {
        println!("Delay: {:?}", delay);
    }
    if let Some(loss) = netem.loss() {
        println!("Loss: {:.2}%", loss);
    }
    if let Some(rate) = netem.rate_bps() {
        println!("Rate limit: {} bytes/sec", rate);
    }
}
Source

pub async fn get_netem_by_index( &self, ifindex: u32, ) -> Result<Option<NetemOptions>>

Get netem options for an interface by index.

Returns None if no netem qdisc is configured at root.

Source§

impl Connection<Route>

Bring a network interface up.

Accepts either an interface name or index via InterfaceRef.

§Example
conn.set_link_up("eth0").await?;
conn.set_link_up(5u32).await?;  // by index

Bring a network interface up by index.

Bring a network interface down.

Accepts either an interface name or index via InterfaceRef.

§Example
conn.set_link_down("eth0").await?;
conn.set_link_down(5u32).await?;  // by index

Bring a network interface down by index.

Set the state of a network interface (up or down).

Accepts either an interface name or index via InterfaceRef.

§Arguments
  • iface - The interface name or index
  • up - true to bring the interface up, false to bring it down
§Example
// Bring interface up
conn.set_link_state("eth0", true).await?;

// Bring interface down by index
conn.set_link_state(5u32, false).await?;

Set the state of a network interface by index.

Set the MTU of a network interface.

Accepts either an interface name or index via InterfaceRef.

§Example
conn.set_link_mtu("eth0", 9000).await?;
conn.set_link_mtu(5u32, 9000).await?;  // by index

Set the MTU of a network interface by index.

Delete a network interface.

Accepts either an interface name or index via InterfaceRef.

§Example
conn.del_link("veth0").await?;
conn.del_link(5u32).await?;  // by index

Delete a network interface by index.

Set the TX queue length of a network interface.

Accepts either an interface name or index via InterfaceRef.

§Example
conn.set_link_txqlen("eth0", 1000).await?;
conn.set_link_txqlen(5u32, 1000).await?;  // by index

Set the TX queue length of a network interface by index.

Source§

impl Connection<Route>

Source

pub async fn get_nsid(&self, ns_fd: RawFd) -> Result<u32>

Get the namespace ID for a given file descriptor.

The file descriptor should be an open reference to a network namespace (e.g., from opening /proc/<pid>/ns/net).

§Errors

Returns an error if the namespace ID cannot be determined.

§Example
use std::fs::File;
use std::os::unix::io::AsRawFd;

let ns_file = File::open("/var/run/netns/myns")?;
let nsid = conn.get_nsid(ns_file.as_raw_fd()).await?;
println!("Namespace ID: {}", nsid);
Source

pub async fn get_nsid_for_pid(&self, pid: u32) -> Result<u32>

Get the namespace ID for a given process’s network namespace.

§Errors

Returns an error if the namespace ID cannot be determined.

§Example
// Get the namespace ID for process 1234
let nsid = conn.get_nsid_for_pid(1234).await?;
println!("Namespace ID for PID 1234: {}", nsid);
Source§

impl Connection<Generic>

Source

pub async fn get_family(&self, name: &str) -> Result<FamilyInfo>

Get information about a Generic Netlink family.

The result is cached, so subsequent calls for the same family do not require kernel communication.

§Example
use nlink::netlink::{Connection, Generic};

let conn = Connection::<Generic>::new()?;
let wg = conn.get_family("wireguard").await?;
println!("WireGuard family ID: {}", wg.id);
Source

pub async fn get_family_id(&self, name: &str) -> Result<u16>

Get the family ID for a given family name.

This is a convenience method that returns just the ID.

Source

pub fn clear_cache(&self)

Clear the family cache.

This is rarely needed, but may be useful if families are dynamically loaded/unloaded.

Source

pub async fn command( &self, family_id: u16, cmd: u8, version: u8, build_attrs: impl FnOnce(&mut MessageBuilder), ) -> Result<Vec<u8>>

Send a GENL command and wait for a response.

This is a low-level method for sending arbitrary GENL commands. Family-specific wrappers (like Connection<Wireguard>) should use this.

Source

pub async fn dump_command( &self, family_id: u16, cmd: u8, version: u8, build_attrs: impl FnOnce(&mut MessageBuilder), ) -> Result<Vec<Vec<u8>>>

Send a GENL dump command and collect all responses.

Source§

impl Connection<Connector>

Source

pub async fn new() -> Result<Self>

Create a new connector and register for process events.

This requires CAP_NET_ADMIN capability.

§Example
use nlink::netlink::{Connection, Connector};

let conn = Connection::<Connector>::new().await?;
Source

pub async fn unregister(&self) -> Result<()>

Unregister from process events.

After calling this, no more events will be received.

Source

pub async fn recv(&self) -> Result<ProcEvent>

Receive the next process event.

This method blocks until an event is available.

§Example
use nlink::netlink::{Connection, Connector};
use nlink::netlink::connector::ProcEvent;

let conn = Connection::<Connector>::new_proc_events().await?;

loop {
    let event = conn.recv().await?;
    if let Some(pid) = event.pid() {
        println!("Event for PID {}: {:?}", pid, event);
    }
}
Source§

impl Connection<Route>

Source

pub async fn get_fdb( &self, bridge: impl Into<InterfaceRef>, ) -> Result<Vec<FdbEntry>>

Get all FDB entries for a bridge.

Returns entries where the master device matches the specified bridge, or entries directly on the bridge interface itself.

§Example
let entries = conn.get_fdb("br0").await?;
for entry in &entries {
    println!("{} on ifindex {} vlan={:?}",
        entry.mac_str(), entry.ifindex, entry.vlan);
}
Source

pub async fn get_fdb_by_index(&self, bridge_idx: u32) -> Result<Vec<FdbEntry>>

Get all FDB entries for a bridge by interface index.

Use this method when operating in a network namespace to avoid reading /sys/class/net/ from the wrong namespace.

Source

pub async fn get_fdb_for_port( &self, bridge: impl Into<InterfaceRef>, port: impl Into<InterfaceRef>, ) -> Result<Vec<FdbEntry>>

Get FDB entries for a specific bridge port.

§Example
let entries = conn.get_fdb_for_port("br0", "veth0").await?;
Source

pub async fn add_fdb(&self, entry: FdbEntryBuilder) -> Result<()>

Add an FDB entry.

§Example
use nlink::netlink::fdb::FdbEntryBuilder;

let mac = FdbEntryBuilder::parse_mac("aa:bb:cc:dd:ee:ff")?;
conn.add_fdb(
    FdbEntryBuilder::new(mac)
        .dev("veth0")
        .master("br0")
        .vlan(100)
).await?;

// Namespace-safe version using interface index
conn.add_fdb(
    FdbEntryBuilder::new(mac)
        .ifindex(5)
        .master_ifindex(3)
).await?;
Source

pub async fn replace_fdb(&self, entry: FdbEntryBuilder) -> Result<()>

Replace an FDB entry (add or update).

If the entry exists, it will be updated. Otherwise, it will be created.

Source

pub async fn del_fdb( &self, dev: impl Into<InterfaceRef>, mac: [u8; 6], vlan: Option<u16>, ) -> Result<()>

Delete an FDB entry by device name, MAC address, and optional VLAN.

§Example
// Delete entry without VLAN
conn.del_fdb("veth0", [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff], None).await?;

// Delete entry with specific VLAN
conn.del_fdb("veth0", [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff], Some(100)).await?;
Source

pub async fn del_fdb_by_index( &self, ifindex: u32, mac: [u8; 6], vlan: Option<u16>, ) -> Result<()>

Delete an FDB entry by interface index, MAC address, and optional VLAN.

Use this method when operating in a network namespace.

Source

pub async fn flush_fdb(&self, bridge: impl Into<InterfaceRef>) -> Result<()>

Flush all dynamic FDB entries for a bridge.

Permanent (static) entries are not removed.

§Example
conn.flush_fdb("br0").await?;
Source§

impl Connection<FibLookup>

Source

pub fn new() -> Result<Self>

Create a new FIB lookup connection.

§Example
use nlink::netlink::{Connection, FibLookup};

let conn = Connection::<FibLookup>::new()?;
Source

pub async fn lookup(&self, addr: Ipv4Addr) -> Result<FibLookupResult>

Look up a route for an IPv4 address.

§Example
use nlink::netlink::{Connection, FibLookup};
use std::net::Ipv4Addr;

let conn = Connection::<FibLookup>::new()?;
let result = conn.lookup(Ipv4Addr::new(8, 8, 8, 8)).await?;

if result.is_success() {
    println!("Route found: type={:?}, table={}, prefix=/{}",
        result.route_type, result.table_id, result.prefix_len);
}
Source

pub async fn lookup_in_table( &self, addr: Ipv4Addr, table: u8, ) -> Result<FibLookupResult>

Look up a route for an IPv4 address in a specific routing table.

§Example
use nlink::netlink::{Connection, FibLookup};
use std::net::Ipv4Addr;

let conn = Connection::<FibLookup>::new()?;
// Look up in table 254 (main)
let result = conn.lookup_in_table(Ipv4Addr::new(10, 0, 0, 1), 254).await?;
Source

pub async fn lookup_with_mark( &self, addr: Ipv4Addr, mark: u32, ) -> Result<FibLookupResult>

Look up a route for an IPv4 address with a specific firewall mark.

Firewall marks can be used for policy routing decisions.

§Example
use nlink::netlink::{Connection, FibLookup};
use std::net::Ipv4Addr;

let conn = Connection::<FibLookup>::new()?;
let result = conn.lookup_with_mark(Ipv4Addr::new(8, 8, 8, 8), 0x100).await?;
Source

pub async fn lookup_with_options( &self, request: FibResultNl, ) -> Result<FibLookupResult>

Look up a route with custom options.

This method allows full control over the lookup parameters.

§Example
use nlink::netlink::{Connection, FibLookup};
use nlink::netlink::fib_lookup::FibResultNl;
use std::net::Ipv4Addr;

let conn = Connection::<FibLookup>::new()?;
let request = FibResultNl {
    fl_addr: u32::from_be_bytes(Ipv4Addr::new(8, 8, 8, 8).octets()),
    fl_tos: 0x10,  // Specific TOS value
    ..Default::default()
};
let result = conn.lookup_with_options(request).await?;
Source§

impl Connection<Route>

Source

pub async fn add_filter( &self, dev: impl Into<InterfaceRef>, parent: &str, config: impl FilterConfig, ) -> Result<()>

Add a filter to an interface.

§Example
use nlink::netlink::filter::FlowerFilter;

let filter = FlowerFilter::new()
    .classid("1:10")
    .ip_proto_tcp()
    .dst_port(80)
    .build();

conn.add_filter("eth0", "1:", filter).await?;
Source

pub async fn add_filter_full( &self, dev: impl Into<InterfaceRef>, parent: &str, handle: Option<&str>, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>

Add a filter with explicit parameters.

§Arguments
  • dev - Interface name
  • parent - Parent qdisc handle (e.g., “1:”)
  • handle - Filter handle (optional)
  • protocol - Ethernet protocol (e.g., 0x0800 for IPv4)
  • priority - Filter priority (lower = higher priority)
  • config - Filter configuration
Source

pub async fn add_filter_by_index( &self, ifindex: u32, parent: &str, config: impl FilterConfig, ) -> Result<()>

Add a filter by interface index.

Source

pub async fn add_filter_by_index_full( &self, ifindex: u32, parent: &str, handle: Option<&str>, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>

Add a filter by interface index with explicit parameters.

Source

pub async fn replace_filter( &self, dev: impl Into<InterfaceRef>, parent: &str, config: impl FilterConfig, ) -> Result<()>

Replace a filter on an interface (create if not exists).

This uses NLM_F_CREATE | NLM_F_REPLACE flags to atomically replace an existing filter or create a new one.

§Example
let filter = U32Filter::new()
    .classid("1:10")
    .match_dst_port(80)
    .build();
conn.replace_filter("eth0", "1:", filter).await?;
Source

pub async fn replace_filter_full( &self, dev: impl Into<InterfaceRef>, parent: &str, handle: Option<&str>, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>

Replace a filter with explicit parameters.

Source

pub async fn replace_filter_by_index( &self, ifindex: u32, parent: &str, config: impl FilterConfig, ) -> Result<()>

Replace a filter by interface index.

Source

pub async fn replace_filter_by_index_full( &self, ifindex: u32, parent: &str, handle: Option<&str>, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>

Replace a filter by interface index with explicit parameters.

Source

pub async fn change_filter( &self, dev: impl Into<InterfaceRef>, parent: &str, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>

Change an existing filter’s parameters.

Unlike replace_filter, this fails if the filter doesn’t exist.

§Example
let filter = U32Filter::new()
    .classid("1:20")  // Change to different class
    .match_dst_port(80)
    .build();
conn.change_filter("eth0", "1:", 0x0800, 100, filter).await?;
Source

pub async fn change_filter_full( &self, dev: impl Into<InterfaceRef>, parent: &str, handle: Option<&str>, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>

Change a filter with explicit handle.

Source

pub async fn change_filter_by_index( &self, ifindex: u32, parent: &str, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>

Change a filter by interface index.

Source

pub async fn change_filter_by_index_full( &self, ifindex: u32, parent: &str, handle: Option<&str>, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>

Change a filter by interface index with explicit handle.

Source

pub async fn del_filter( &self, dev: impl Into<InterfaceRef>, parent: &str, protocol: u16, priority: u16, ) -> Result<()>

Delete a filter from an interface.

§Example
conn.del_filter("eth0", "1:", 0x0800, 100).await?;
Source

pub async fn del_filter_by_index( &self, ifindex: u32, parent: &str, protocol: u16, priority: u16, ) -> Result<()>

Delete a filter by interface index.

Source

pub async fn flush_filters( &self, dev: impl Into<InterfaceRef>, parent: &str, ) -> Result<()>

Delete all filters from a parent qdisc.

Source

pub async fn flush_filters_by_index( &self, ifindex: u32, parent: &str, ) -> Result<()>

Delete all filters from a parent qdisc by interface index.

Source

pub async fn attach_bpf( &self, dev: impl Into<InterfaceRef>, direction: BpfDirection, filter: BpfFilter, ) -> Result<()>

Attach a BPF program to ingress or egress using clsact.

Creates the clsact qdisc if it doesn’t exist, then attaches the BPF filter. This is the standard pattern for BPF TC programs.

§Example
use nlink::netlink::filter::{BpfFilter, BpfDirection};

let filter = BpfFilter::from_pinned("/sys/fs/bpf/my_prog")?
    .direct_action();
conn.attach_bpf("eth0", BpfDirection::Ingress, filter).await?;
Source

pub async fn attach_bpf_by_index( &self, ifindex: u32, direction: BpfDirection, filter: BpfFilter, ) -> Result<()>

Attach a BPF program by interface index (namespace-safe).

Source

pub async fn detach_bpf( &self, dev: impl Into<InterfaceRef>, direction: BpfDirection, ) -> Result<()>

Detach all BPF filters from an interface direction.

Flushes all filters attached to the ingress or egress hook of the clsact qdisc.

§Example
use nlink::netlink::filter::BpfDirection;

conn.detach_bpf("eth0", BpfDirection::Ingress).await?;
Source

pub async fn detach_bpf_by_index( &self, ifindex: u32, direction: BpfDirection, ) -> Result<()>

Detach all BPF filters from an interface direction by index.

Source

pub async fn list_bpf_programs( &self, dev: impl Into<InterfaceRef>, ) -> Result<Vec<BpfInfo>>

List attached BPF programs on an interface (both directions).

Returns [BpfInfo] for each BPF filter found on the interface’s clsact qdisc. Returns an empty vec if no clsact qdisc exists.

§Example
let programs = conn.list_bpf_programs("eth0").await?;
for prog in &programs {
    println!("BPF: id={:?} name={:?} da={}", prog.id, prog.name, prog.direct_action);
}
Source

pub async fn list_bpf_programs_by_index( &self, ifindex: u32, ) -> Result<Vec<BpfInfo>>

List attached BPF programs by interface index.

Source§

impl Connection<Devlink>

Source

pub async fn new_async() -> Result<Self>

Create a new devlink connection.

Resolves the “devlink” GENL family ID during initialization.

§Example
use nlink::netlink::{Connection, Devlink};

let conn = Connection::<Devlink>::new_async().await?;
let devices = conn.get_devices().await?;
Source

pub fn family_id(&self) -> u16

Get the devlink family ID.

Source

pub fn subscribe(&mut self) -> Result<()>

Subscribe to devlink multicast events.

After subscribing, use events() or into_events() to receive events.

Source

pub async fn get_devices(&self) -> Result<Vec<DevlinkDevice>>

List all devlink devices.

§Example
let devices = conn.get_devices().await?;
for dev in &devices {
    println!("{}", dev.path());
}
Source

pub async fn get_device_info( &self, bus: &str, device: &str, ) -> Result<DevlinkInfo>

Get information for a specific device (driver, firmware versions).

§Example
let info = conn.get_device_info("pci", "0000:03:00.0").await?;
println!("Driver: {}", info.driver);
for v in &info.versions_running {
    println!("  {}: {}", v.name, v.value);
}
Source

pub async fn get_ports(&self) -> Result<Vec<DevlinkPort>>

List all ports across all devices.

Source

pub async fn get_device_ports( &self, bus: &str, device: &str, ) -> Result<Vec<DevlinkPort>>

List ports for a specific device.

Source

pub async fn get_port( &self, bus: &str, device: &str, index: u32, ) -> Result<Option<DevlinkPort>>

Get a specific port by device and index.

Source

pub async fn get_port_by_netdev( &self, netdev: &str, ) -> Result<Option<DevlinkPort>>

Find the port associated with a network interface name.

Source

pub async fn get_health_reporters( &self, bus: &str, device: &str, ) -> Result<Vec<HealthReporter>>

List all health reporters for a device.

Source

pub async fn get_health_reporter( &self, bus: &str, device: &str, name: &str, ) -> Result<Option<HealthReporter>>

Get a specific health reporter by name.

Source

pub async fn get_health_errors( &self, bus: &str, device: &str, ) -> Result<Vec<HealthReporter>>

List health reporters that are in error state.

Source

pub async fn get_params( &self, bus: &str, device: &str, ) -> Result<Vec<DevlinkParam>>

List all parameters for a device.

Source

pub async fn get_param( &self, bus: &str, device: &str, name: &str, ) -> Result<Option<DevlinkParam>>

Get a specific parameter by name.

Source

pub async fn health_reporter_recover( &self, bus: &str, device: &str, reporter: &str, ) -> Result<()>

Trigger recovery on a health reporter.

Source

pub async fn set_health_reporter( &self, bus: &str, device: &str, reporter: &str, auto_recover: Option<bool>, auto_dump: Option<bool>, graceful_period_ms: Option<u64>, ) -> Result<()>

Configure a health reporter’s settings.

Source

pub async fn flash_update( &self, bus: &str, device: &str, request: FlashRequest, ) -> Result<()>

Flash firmware to a device.

This is a long-running operation. The kernel will send progress notifications asynchronously.

Source

pub async fn reload( &self, bus: &str, device: &str, action: ReloadAction, ) -> Result<()>

Reload the device with the specified action.

Source

pub async fn port_split( &self, bus: &str, device: &str, port_index: u32, count: u32, ) -> Result<()>

Split a port into sub-ports.

Source

pub async fn port_unsplit( &self, bus: &str, device: &str, port_index: u32, ) -> Result<()>

Unsplit a previously split port.

Source

pub async fn set_param( &self, bus: &str, device: &str, name: &str, cmode: ConfigMode, data: ParamData, ) -> Result<()>

Set a device parameter.

Source§

impl Connection<Ethtool>

Source

pub async fn new_async() -> Result<Self>

Create a new ethtool connection.

This resolves the ethtool GENL family ID during initialization.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;
let state = conn.get_link_state("eth0").await?;
println!("Link: {}", if state.link { "up" } else { "down" });
Source

pub fn family_id(&self) -> u16

Get the ethtool family ID.

Source

pub fn monitor_group_id(&self) -> Option<u32>

Get the monitor multicast group ID (if available).

Get link state (carrier detection, signal quality).

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
let state = conn.get_link_state("eth0").await?;

// By index
let state = conn.get_link_state(5u32).await?;

println!("Link detected: {}", state.link);

Get link state by interface name.

Get link info (port type, transceiver, MDI-X).

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
let info = conn.get_link_info("eth0").await?;

// By index
let info = conn.get_link_info(5u32).await?;

println!("Port: {:?}", info.port);
println!("Transceiver: {:?}", info.transceiver);

Get link info by interface name.

Get link modes (speed, duplex, autonegotiation).

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
let modes = conn.get_link_modes("eth0").await?;

// By index
let modes = conn.get_link_modes(5u32).await?;

println!("Speed: {:?} Mb/s", modes.speed);
println!("Duplex: {:?}", modes.duplex);
println!("Autoneg: {}", modes.autoneg);
println!("Supported modes: {:?}", modes.supported_modes());

Get link modes by interface name.

Set link modes (speed, duplex, autonegotiation).

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};
use nlink::netlink::genl::ethtool::Duplex;

let conn = Connection::<Ethtool>::new_async().await?;

// Force 1000Mbps full duplex (by name)
conn.set_link_modes("eth0", |m| {
    m.autoneg(false)
     .speed(1000)
     .duplex(Duplex::Full)
}).await?;

// By index
conn.set_link_modes(5u32, |m| {
    m.autoneg(true)
     .advertise("1000baseT/Full")
     .advertise("100baseT/Full")
}).await?;

Set link modes by interface name.

Source

pub async fn get_features( &self, iface: impl Into<InterfaceRef>, ) -> Result<Features>

Get device features (offloads).

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
let features = conn.get_features("eth0").await?;

// By index
let features = conn.get_features(5u32).await?;

println!("TSO: {}", features.is_active("tx-tcp-segmentation"));
println!("GRO: {}", features.is_active("rx-gro"));

for (name, enabled) in features.iter() {
    println!("{}: {}", name, if enabled { "on" } else { "off" });
}
Source

pub async fn get_features_by_name(&self, ifname: &str) -> Result<Features>

Get device features by interface name.

Source

pub async fn set_features( &self, iface: impl Into<InterfaceRef>, configure: impl FnOnce(FeaturesBuilder) -> FeaturesBuilder, ) -> Result<()>

Set device features (offloads).

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
conn.set_features("eth0", |f| {
    f.enable("tx-checksumming")
     .disable("rx-gro")
}).await?;

// By index
conn.set_features(5u32, |f| {
    f.enable("tx-checksumming")
}).await?;
Source

pub async fn set_features_by_name( &self, ifname: &str, configure: impl FnOnce(FeaturesBuilder) -> FeaturesBuilder, ) -> Result<()>

Set device features by interface name.

Source

pub async fn get_rings(&self, iface: impl Into<InterfaceRef>) -> Result<Rings>

Get ring buffer sizes.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
let rings = conn.get_rings("eth0").await?;

// By index
let rings = conn.get_rings(5u32).await?;

println!("RX: {:?} (max {:?})", rings.rx, rings.rx_max);
println!("TX: {:?} (max {:?})", rings.tx, rings.tx_max);
Source

pub async fn get_rings_by_name(&self, ifname: &str) -> Result<Rings>

Get ring buffer sizes by interface name.

Source

pub async fn set_rings( &self, iface: impl Into<InterfaceRef>, configure: impl FnOnce(RingsBuilder) -> RingsBuilder, ) -> Result<()>

Set ring buffer sizes.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
conn.set_rings("eth0", |r| {
    r.rx(4096).tx(4096)
}).await?;

// By index
conn.set_rings(5u32, |r| {
    r.rx(4096).tx(4096)
}).await?;
Source

pub async fn set_rings_by_name( &self, ifname: &str, configure: impl FnOnce(RingsBuilder) -> RingsBuilder, ) -> Result<()>

Set ring buffer sizes by interface name.

Source

pub async fn get_channels( &self, iface: impl Into<InterfaceRef>, ) -> Result<Channels>

Get channel counts (RX/TX queues).

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
let channels = conn.get_channels("eth0").await?;

// By index
let channels = conn.get_channels(5u32).await?;

println!("RX: {:?} (max {:?})", channels.rx_count, channels.rx_max);
println!("TX: {:?} (max {:?})", channels.tx_count, channels.tx_max);
println!("Combined: {:?} (max {:?})", channels.combined_count, channels.combined_max);
Source

pub async fn get_channels_by_name(&self, ifname: &str) -> Result<Channels>

Get channel counts by interface name.

Source

pub async fn set_channels( &self, iface: impl Into<InterfaceRef>, configure: impl FnOnce(ChannelsBuilder) -> ChannelsBuilder, ) -> Result<()>

Set channel counts.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
conn.set_channels("eth0", |c| {
    c.combined(4)
}).await?;

// By index
conn.set_channels(5u32, |c| {
    c.combined(4)
}).await?;
Source

pub async fn set_channels_by_name( &self, ifname: &str, configure: impl FnOnce(ChannelsBuilder) -> ChannelsBuilder, ) -> Result<()>

Set channel counts by interface name.

Source

pub async fn get_coalesce( &self, iface: impl Into<InterfaceRef>, ) -> Result<Coalesce>

Get interrupt coalescing parameters.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
let coalesce = conn.get_coalesce("eth0").await?;

// By index
let coalesce = conn.get_coalesce(5u32).await?;

println!("RX usecs: {:?}", coalesce.rx_usecs);
println!("TX usecs: {:?}", coalesce.tx_usecs);
println!("Adaptive RX: {:?}", coalesce.use_adaptive_rx);
Source

pub async fn get_coalesce_by_name(&self, ifname: &str) -> Result<Coalesce>

Get interrupt coalescing parameters by interface name.

Source

pub async fn set_coalesce( &self, iface: impl Into<InterfaceRef>, configure: impl FnOnce(CoalesceBuilder) -> CoalesceBuilder, ) -> Result<()>

Set interrupt coalescing parameters.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
conn.set_coalesce("eth0", |c| {
    c.rx_usecs(100)
     .tx_usecs(100)
     .use_adaptive_rx(true)
}).await?;

// By index
conn.set_coalesce(5u32, |c| {
    c.rx_usecs(100)
}).await?;
Source

pub async fn set_coalesce_by_name( &self, ifname: &str, configure: impl FnOnce(CoalesceBuilder) -> CoalesceBuilder, ) -> Result<()>

Set interrupt coalescing parameters by interface name.

Source

pub async fn get_pause(&self, iface: impl Into<InterfaceRef>) -> Result<Pause>

Get pause/flow control settings.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
let pause = conn.get_pause("eth0").await?;

// By index
let pause = conn.get_pause(5u32).await?;

println!("Autoneg: {:?}", pause.autoneg);
println!("RX pause: {:?}", pause.rx);
println!("TX pause: {:?}", pause.tx);
Source

pub async fn get_pause_by_name(&self, ifname: &str) -> Result<Pause>

Get pause/flow control settings by interface name.

Source

pub async fn set_pause( &self, iface: impl Into<InterfaceRef>, configure: impl FnOnce(PauseBuilder) -> PauseBuilder, ) -> Result<()>

Set pause/flow control settings.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Ethtool};

let conn = Connection::<Ethtool>::new_async().await?;

// By name
conn.set_pause("eth0", |p| {
    p.autoneg(true)
     .rx(true)
     .tx(true)
}).await?;

// By index
conn.set_pause(5u32, |p| {
    p.autoneg(true)
}).await?;
Source

pub async fn set_pause_by_name( &self, ifname: &str, configure: impl FnOnce(PauseBuilder) -> PauseBuilder, ) -> Result<()>

Set pause/flow control settings by interface name.

Source

pub fn subscribe(&mut self) -> Result<()>

Subscribe to ethtool events.

After subscribing, use events() or into_events() to receive notifications about ethtool configuration changes.

§Example
use nlink::netlink::{Connection, Ethtool};
use tokio_stream::StreamExt;

let mut conn = Connection::<Ethtool>::new_async().await?;
conn.subscribe()?;

let mut events = conn.events();
while let Some(event) = events.next().await {
    println!("{:?}", event?);
}
Source§

impl Connection<Macsec>

Source

pub async fn new_async() -> Result<Self>

Create a new MACsec connection.

This resolves the MACsec GENL family ID during initialization.

§Example
use nlink::netlink::{Connection, Macsec};

let conn = Connection::<Macsec>::new_async().await?;
let device = conn.get_device("macsec0").await?;
Source

pub fn family_id(&self) -> u16

Get the MACsec family ID.

Source

pub async fn get_device( &self, iface: impl Into<InterfaceRef>, ) -> Result<MacsecDevice>

Get device information.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Macsec};

let conn = Connection::<Macsec>::new_async().await?;

// By name (convenient)
let device = conn.get_device("macsec0").await?;

// By index (efficient for repeated operations)
let device = conn.get_device(5u32).await?;
Source

pub async fn get_device_by_index(&self, ifindex: u32) -> Result<MacsecDevice>

Get device information by interface index.

Returns the current configuration and status of the MACsec interface. This is the preferred method for namespace operations.

§Example
// Get ifindex via Route connection first
let route_conn = Connection::<Route>::new()?;
let link = route_conn.get_link_by_name("macsec0").await?.unwrap();

let macsec_conn = Connection::<Macsec>::new_async().await?;
let device = macsec_conn.get_device_by_index(link.ifindex()).await?;
println!("SCI: {:016x}", device.sci);
Source

pub async fn add_tx_sa_by_index( &self, ifindex: u32, sa: MacsecSaBuilder, ) -> Result<()>

Add a TX Security Association by interface index.

§Example
let key = [0u8; 16]; // 128-bit key
conn.add_tx_sa_by_index(ifindex,
    MacsecSaBuilder::new(0, &key)
        .packet_number(1)
        .active(true)
).await?;
Source

pub async fn del_tx_sa_by_index(&self, ifindex: u32, an: u8) -> Result<()>

Delete a TX Security Association by interface index.

§Arguments
  • ifindex - Interface index
  • an - Association Number (0-3)
Source

pub async fn update_tx_sa_by_index( &self, ifindex: u32, sa: MacsecSaBuilder, ) -> Result<()>

Update a TX Security Association by interface index.

This can be used to activate/deactivate an SA or update the packet number.

Source

pub async fn add_rx_sc_by_index(&self, ifindex: u32, sci: u64) -> Result<()>

Add an RX Secure Channel by interface index.

§Arguments
  • ifindex - Interface index
  • sci - Secure Channel Identifier (typically peer’s MAC + port)
Source

pub async fn del_rx_sc_by_index(&self, ifindex: u32, sci: u64) -> Result<()>

Delete an RX Secure Channel by interface index.

This also deletes all associated RX SAs.

Source

pub async fn add_rx_sa_by_index( &self, ifindex: u32, sci: u64, sa: MacsecSaBuilder, ) -> Result<()>

Add an RX Security Association by interface index.

§Arguments
  • ifindex - Interface index
  • sci - Secure Channel Identifier
  • sa - SA configuration
Source

pub async fn del_rx_sa_by_index( &self, ifindex: u32, sci: u64, an: u8, ) -> Result<()>

Delete an RX Security Association by interface index.

Source

pub async fn update_rx_sa_by_index( &self, ifindex: u32, sci: u64, sa: MacsecSaBuilder, ) -> Result<()>

Update an RX Security Association by interface index.

Source

pub async fn add_tx_sa( &self, iface: impl Into<InterfaceRef>, sa: MacsecSaBuilder, ) -> Result<()>

Add a TX Security Association.

Accepts either an interface name or index via InterfaceRef.

§Example
let key = [0u8; 16];
conn.add_tx_sa("macsec0", MacsecSaBuilder::new(0).key(&key).active(true)).await?;
Source

pub async fn del_tx_sa( &self, iface: impl Into<InterfaceRef>, an: u8, ) -> Result<()>

Delete a TX Security Association.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn update_tx_sa( &self, iface: impl Into<InterfaceRef>, sa: MacsecSaBuilder, ) -> Result<()>

Update a TX Security Association.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn add_rx_sc( &self, iface: impl Into<InterfaceRef>, sci: u64, ) -> Result<()>

Add an RX Secure Channel.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn del_rx_sc( &self, iface: impl Into<InterfaceRef>, sci: u64, ) -> Result<()>

Delete an RX Secure Channel.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn add_rx_sa( &self, iface: impl Into<InterfaceRef>, sci: u64, sa: MacsecSaBuilder, ) -> Result<()>

Add an RX Security Association.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn del_rx_sa( &self, iface: impl Into<InterfaceRef>, sci: u64, an: u8, ) -> Result<()>

Delete an RX Security Association.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn update_rx_sa( &self, iface: impl Into<InterfaceRef>, sci: u64, sa: MacsecSaBuilder, ) -> Result<()>

Update an RX Security Association.

Accepts either an interface name or index via InterfaceRef.

Source§

impl Connection<Mptcp>

Source

pub async fn new_async() -> Result<Self>

Create a new MPTCP connection.

This resolves the MPTCP PM GENL family ID during initialization.

§Example
use nlink::netlink::{Connection, Mptcp};

let conn = Connection::<Mptcp>::new_async().await?;
let endpoints = conn.get_endpoints().await?;
Source

pub fn family_id(&self) -> u16

Get the MPTCP PM family ID.

Source

pub async fn get_endpoints(&self) -> Result<Vec<MptcpEndpoint>>

Get all configured MPTCP endpoints.

§Example
let conn = Connection::<Mptcp>::new_async().await?;
for ep in conn.get_endpoints().await? {
    println!("Endpoint {}: {} flags={:?}", ep.id, ep.address, ep.flags);
}
Source

pub async fn add_endpoint(&self, endpoint: MptcpEndpointBuilder) -> Result<()>

Add an MPTCP endpoint.

§Example
use nlink::netlink::genl::mptcp::MptcpEndpointBuilder;

conn.add_endpoint(
    MptcpEndpointBuilder::new("192.168.2.1".parse()?)
        .id(1)
        .dev("eth1")
        .subflow()
        .signal()
).await?;
Source

pub async fn del_endpoint(&self, id: u8) -> Result<()>

Delete an MPTCP endpoint by ID.

§Example
conn.del_endpoint(1).await?;
Source

pub async fn flush_endpoints(&self) -> Result<()>

Flush all MPTCP endpoints.

§Example
conn.flush_endpoints().await?;
Source

pub async fn get_limits(&self) -> Result<MptcpLimits>

Get MPTCP limits.

§Example
let limits = conn.get_limits().await?;
println!("Max subflows: {:?}", limits.subflows);
println!("Max add_addr_accepted: {:?}", limits.add_addr_accepted);
Source

pub async fn set_limits(&self, limits: MptcpLimits) -> Result<()>

Set MPTCP limits.

§Example
use nlink::netlink::genl::mptcp::MptcpLimits;

conn.set_limits(
    MptcpLimits::new()
        .subflows(4)
        .add_addr_accepted(4)
).await?;
Source

pub async fn set_endpoint_flags(&self, id: u8, flags: MptcpFlags) -> Result<()>

Set endpoint flags by ID.

§Example
use nlink::netlink::genl::mptcp::MptcpFlags;

// Mark endpoint 1 as backup
conn.set_endpoint_flags(1, MptcpFlags { backup: true, ..Default::default() }).await?;
Source

pub async fn create_subflow(&self, subflow: MptcpSubflowBuilder) -> Result<()>

Create a new subflow on an existing MPTCP connection.

This allows programmatic creation of subflows between specific local and remote addresses on an active MPTCP connection.

§Example
use nlink::netlink::genl::mptcp::MptcpSubflowBuilder;
use std::net::Ipv4Addr;

// Create a subflow using local address ID 1 to the remote
conn.create_subflow(
    MptcpSubflowBuilder::new(connection_token)
        .local_id(1)
        .remote_addr(Ipv4Addr::new(10, 0, 0, 1).into())
        .remote_port(80)
).await?;
Source

pub async fn destroy_subflow(&self, subflow: MptcpSubflowBuilder) -> Result<()>

Destroy a subflow on an existing MPTCP connection.

This closes a specific subflow identified by its local and remote addresses.

§Example
use nlink::netlink::genl::mptcp::MptcpSubflowBuilder;
use std::net::Ipv4Addr;

// Destroy the subflow between specific addresses
conn.destroy_subflow(
    MptcpSubflowBuilder::new(connection_token)
        .local_addr(Ipv4Addr::new(192, 168, 1, 1).into())
        .local_port(12345)
        .remote_addr(Ipv4Addr::new(10, 0, 0, 1).into())
        .remote_port(80)
).await?;
Source

pub async fn announce_addr(&self, announce: MptcpAnnounceBuilder) -> Result<()>

Announce an address to a peer on a specific connection.

This sends an ADD_ADDR message to the peer on the specified connection.

§Example
use nlink::netlink::genl::mptcp::MptcpAnnounceBuilder;
use std::net::Ipv4Addr;

// Announce address ID 1 to the peer
conn.announce_addr(
    MptcpAnnounceBuilder::new(connection_token)
        .addr_id(1)
        .address(Ipv4Addr::new(192, 168, 2, 1).into())
).await?;
Source

pub async fn del_addr(&self, token: u32, addr_id: u8) -> Result<()>

Remove an address announcement from a specific connection.

This sends a REMOVE_ADDR message to the peer.

§Example
// Remove address ID 1 from the connection
conn.del_addr(connection_token, 1).await?;
Source§

impl Connection<Nl80211>

Source

pub async fn new_async() -> Result<Self>

Create a new nl80211 connection.

Resolves the “nl80211” GENL family ID during initialization.

§Example
use nlink::netlink::{Connection, Nl80211};

let conn = Connection::<Nl80211>::new_async().await?;
let ifaces = conn.get_interfaces().await?;
Source

pub fn family_id(&self) -> u16

Get the nl80211 family ID.

Source

pub fn subscribe(&mut self) -> Result<()>

Subscribe to nl80211 multicast events (scan, mlme, regulatory, config).

After subscribing, use events() or into_events() to receive events.

§Example
use nlink::netlink::{Connection, Nl80211};
use tokio_stream::StreamExt;

let mut conn = Connection::<Nl80211>::new_async().await?;
conn.subscribe()?;

let mut events = conn.events();
while let Some(event) = events.next().await {
    println!("{:?}", event?);
}
Source

pub async fn get_interfaces(&self) -> Result<Vec<WirelessInterface>>

List all wireless interfaces.

§Example
let ifaces = conn.get_interfaces().await?;
for iface in &ifaces {
    println!("{}: {:?}", iface.name.as_deref().unwrap_or("?"), iface.iftype);
}
Source

pub async fn get_interface( &self, name: &str, ) -> Result<Option<WirelessInterface>>

Get a specific wireless interface by name.

Source

pub async fn get_interface_by_index( &self, ifindex: u32, ) -> Result<Option<WirelessInterface>>

Get a specific wireless interface by index.

Source

pub async fn trigger_scan( &self, iface: &str, request: &ScanRequest, ) -> Result<()>

Trigger a scan on an interface.

This is asynchronous: the kernel starts the scan and returns immediately. Poll get_scan_results() to get results.

§Errors

Returns Error::Kernel with EBUSY if a scan is already in progress.

Source

pub async fn trigger_scan_by_index( &self, ifindex: u32, request: &ScanRequest, ) -> Result<()>

Trigger a scan by interface index (namespace-safe).

Source

pub async fn get_scan_results(&self, iface: &str) -> Result<Vec<ScanResult>>

Get cached scan results for an interface.

Returns the most recent scan results. Call trigger_scan() first to ensure fresh results.

Source

pub async fn get_scan_results_by_index( &self, ifindex: u32, ) -> Result<Vec<ScanResult>>

Get scan results by interface index (namespace-safe).

Source

pub async fn get_station(&self, iface: &str) -> Result<Option<StationInfo>>

Get station info for the currently associated AP.

Source

pub async fn get_station_by_index( &self, ifindex: u32, ) -> Result<Option<StationInfo>>

Get station info by interface index (namespace-safe).

Source

pub async fn get_stations(&self, iface: &str) -> Result<Vec<StationInfo>>

List all stations (useful in AP mode).

Source

pub async fn get_stations_by_index( &self, ifindex: u32, ) -> Result<Vec<StationInfo>>

List all stations by interface index.

Source

pub async fn get_phys(&self) -> Result<Vec<PhyInfo>>

List all physical wireless devices.

Source

pub async fn get_phy(&self, wiphy: u32) -> Result<Option<PhyInfo>>

Get capabilities of a specific physical device.

Source

pub async fn get_regulatory(&self) -> Result<RegulatoryDomain>

Get the current regulatory domain.

Source

pub async fn connect(&self, iface: &str, request: ConnectRequest) -> Result<()>

Connect to a wireless network.

§Errors

Returns Error::Kernel with EALREADY if already connected.

Source

pub async fn connect_by_index( &self, ifindex: u32, request: ConnectRequest, ) -> Result<()>

Connect by interface index (namespace-safe).

Source

pub async fn disconnect(&self, iface: &str) -> Result<()>

Disconnect from the current network.

Source

pub async fn disconnect_by_index(&self, ifindex: u32) -> Result<()>

Disconnect by interface index (namespace-safe).

Source

pub async fn set_power_save(&self, iface: &str, enabled: bool) -> Result<()>

Set power save mode.

Source

pub async fn get_power_save(&self, iface: &str) -> Result<PowerSaveState>

Get power save mode.

Source§

impl Connection<Wireguard>

Source

pub async fn new_async() -> Result<Self>

Create a new WireGuard connection.

This resolves the WireGuard GENL family ID during initialization.

§Example
use nlink::netlink::{Connection, Wireguard};

let conn = Connection::<Wireguard>::new().await?;
let device = conn.get_device("wg0").await?;
Source

pub fn family_id(&self) -> u16

Get the WireGuard family ID.

Source

pub async fn get_device( &self, iface: impl Into<InterfaceRef>, ) -> Result<WgDevice>

Get device information.

Accepts either an interface name or index via InterfaceRef.

§Example
use nlink::netlink::{Connection, Wireguard};

let conn = Connection::<Wireguard>::new_async().await?;

// By name
let device = conn.get_device("wg0").await?;

// By index
let device = conn.get_device(5u32).await?;
Source

pub async fn set_device( &self, iface: impl Into<InterfaceRef>, configure: impl FnOnce(WgDeviceBuilder) -> WgDeviceBuilder, ) -> Result<()>

Set device configuration.

Accepts either an interface name or index via InterfaceRef.

§Example
conn.set_device("wg0", |dev| {
    dev.private_key(my_key)
       .listen_port(51820)
}).await?;
Source

pub async fn set_peer( &self, iface: impl Into<InterfaceRef>, public_key: [u8; 32], configure: impl FnOnce(WgPeerBuilder) -> WgPeerBuilder, ) -> Result<()>

Add or update a peer.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn del_peer( &self, iface: impl Into<InterfaceRef>, public_key: [u8; 32], ) -> Result<()>

Remove a peer by public key.

Accepts either an interface name or index via InterfaceRef.

Source

pub async fn get_device_by_name(&self, ifname: &str) -> Result<WgDevice>

Get device information by interface name.

Returns the current configuration and status of the WireGuard interface.

Source

pub async fn set_device_by_name( &self, ifname: &str, configure: impl FnOnce(WgDeviceBuilder) -> WgDeviceBuilder, ) -> Result<()>

Set device configuration by interface name.

Source

pub async fn set_peer_by_name( &self, ifname: &str, public_key: [u8; 32], configure: impl FnOnce(WgPeerBuilder) -> WgPeerBuilder, ) -> Result<()>

Add or update a peer by interface name.

Source

pub async fn del_peer_by_name( &self, ifname: &str, public_key: [u8; 32], ) -> Result<()>

Remove a peer by public key using interface name.

Source§

impl Connection<Route>

Add a new network interface.

§Example
use nlink::netlink::link::{DummyLink, VethLink, BridgeLink};

// Create a dummy interface
conn.add_link(DummyLink::new("dummy0")).await?;

// Create a veth pair
conn.add_link(VethLink::new("veth0", "veth1")).await?;

// Create a bridge
conn.add_link(BridgeLink::new("br0").stp(true)).await?;

// Create a VLAN with parent by index (namespace-safe)
conn.add_link(VlanLink::with_parent_index("vlan100", 5, 100)).await?;

Set the master (controller) device for an interface.

This is used to add an interface to a bridge or bond.

§Example
// Add eth0 to bridge br0
conn.set_link_master("eth0", "br0").await?;

// Or by index
conn.set_link_master(InterfaceRef::Index(5), InterfaceRef::Index(10)).await?;

Set the master device by interface indices.

Source

pub async fn enslave( &self, member: impl Into<InterfaceRef>, master: impl Into<InterfaceRef>, ) -> Result<()>

Enslave an interface to a bond or bridge.

This convenience method handles the required down/master/up sequence: the member interface must be brought down before enslaving, then brought back up afterward.

§Example
// Enslave eth0 to bond0 (handles down/master/up automatically)
conn.enslave("eth0", "bond0").await?;
Source

pub async fn enslave_by_index( &self, member_index: u32, master_index: u32, ) -> Result<()>

Enslave an interface to a bond or bridge by index.

Remove an interface from its master device.

Accepts either an interface name or index via InterfaceRef.

§Example
// Remove eth0 from its bridge/bond
conn.set_link_nomaster("eth0").await?;

Remove an interface from its master by index.

Rename a network interface.

Accepts either an interface name or index via InterfaceRef. Note: The interface must be down to be renamed.

§Example
conn.set_link_name("eth0", "lan0").await?;

Rename a network interface by index.

Set the MAC address of a network interface.

Accepts either an interface name or index via InterfaceRef.

§Example
conn.set_link_address("eth0", [0x00, 0x11, 0x22, 0x33, 0x44, 0x55]).await?;

Set the MAC address by interface index.

Move a network interface to a different network namespace.

Accepts either an interface name or index via InterfaceRef.

§Example
// Move veth1 to namespace by PID
conn.set_link_netns_pid("veth1", container_pid).await?;

Move a network interface to a namespace by PID (by index).

Move a network interface to a namespace by file descriptor.

Accepts either an interface name or index via InterfaceRef.

Move a network interface to a namespace by fd (by index).

Source§

impl Connection<Route>

Source

pub async fn get_mpls_routes(&self) -> Result<Vec<MplsRoute>>

Get all MPLS routes.

§Example
let routes = conn.get_mpls_routes().await?;
for route in &routes {
    println!("Label {}: {:?}", route.label.0, route.action);
}
Source

pub async fn add_mpls_route( &self, route_builder: MplsRouteBuilder, ) -> Result<()>

Add an MPLS route.

§Example
// Pop route
conn.add_mpls_route(
    MplsRouteBuilder::pop(100)
        .dev("eth0")
).await?;

// Swap route
conn.add_mpls_route(
    MplsRouteBuilder::swap(100, 200)
        .via("192.168.1.1".parse()?)
        .dev("eth0")
).await?;
Source

pub async fn replace_mpls_route( &self, route_builder: MplsRouteBuilder, ) -> Result<()>

Replace an MPLS route (add or update).

Source

pub async fn del_mpls_route(&self, label: u32) -> Result<()>

Delete an MPLS route by label.

§Example
conn.del_mpls_route(100).await?;
Source§

impl Connection<Route>

Source

pub async fn add_neighbor<N: NeighborConfig>(&self, config: N) -> Result<()>

Add a neighbor entry.

This method is namespace-safe: interface names are resolved via netlink.

§Example
use nlink::netlink::neigh::{Neighbor, NeighborState};
use std::net::Ipv4Addr;

// Add a permanent ARP entry
conn.add_neighbor(
    Neighbor::new_v4("eth0", Ipv4Addr::new(192, 168, 1, 100))
        .lladdr([0x00, 0x11, 0x22, 0x33, 0x44, 0x55])
        .state(NeighborState::Permanent)
).await?;
Source

pub async fn del_neighbor<N: NeighborConfig>(&self, config: N) -> Result<()>

Delete a neighbor entry using a config.

Source

pub async fn add_neighbor_v4_by_index( &self, ifindex: u32, destination: Ipv4Addr, lladdr: [u8; 6], ) -> Result<()>

Add an IPv4 neighbor entry by interface index.

This is namespace-safe as it doesn’t require interface name resolution.

Source

pub async fn add_neighbor_v6_by_index( &self, ifindex: u32, destination: Ipv6Addr, lladdr: [u8; 6], ) -> Result<()>

Add an IPv6 neighbor entry by interface index.

This is namespace-safe as it doesn’t require interface name resolution.

Source

pub async fn del_neighbor_v4( &self, ifname: impl Into<InterfaceRef>, destination: Ipv4Addr, ) -> Result<()>

Delete an IPv4 neighbor entry.

§Example
conn.del_neighbor_v4("eth0", Ipv4Addr::new(192, 168, 1, 100)).await?;
Source

pub async fn del_neighbor_v4_by_index( &self, ifindex: u32, destination: Ipv4Addr, ) -> Result<()>

Delete an IPv4 neighbor entry by interface index.

Source

pub async fn del_neighbor_v6( &self, ifname: impl Into<InterfaceRef>, destination: Ipv6Addr, ) -> Result<()>

Delete an IPv6 neighbor entry.

Source

pub async fn del_neighbor_v6_by_index( &self, ifindex: u32, destination: Ipv6Addr, ) -> Result<()>

Delete an IPv6 neighbor entry by interface index.

Source

pub async fn replace_neighbor<N: NeighborConfig>(&self, config: N) -> Result<()>

Replace a neighbor entry (add or update).

If the entry exists, it will be updated. Otherwise, it will be created.

Source

pub async fn replace_neighbor_v4_by_index( &self, ifindex: u32, destination: Ipv4Addr, lladdr: [u8; 6], ) -> Result<()>

Replace an IPv4 neighbor entry by interface index.

This is namespace-safe as it doesn’t require interface name resolution.

Source

pub async fn replace_neighbor_v6_by_index( &self, ifindex: u32, destination: Ipv6Addr, lladdr: [u8; 6], ) -> Result<()>

Replace an IPv6 neighbor entry by interface index.

This is namespace-safe as it doesn’t require interface name resolution.

Source

pub async fn flush_neighbors( &self, ifname: impl Into<InterfaceRef>, ) -> Result<()>

Flush all neighbor entries for an interface.

§Example
conn.flush_neighbors("eth0").await?;
Source

pub async fn flush_neighbors_by_index(&self, ifindex: u32) -> Result<()>

Flush all neighbor entries for an interface by index.

Source

pub async fn add_proxy_arp( &self, ifname: impl Into<InterfaceRef>, destination: Ipv4Addr, ) -> Result<()>

Add a proxy ARP entry.

§Example
conn.add_proxy_arp("eth0", Ipv4Addr::new(192, 168, 1, 100)).await?;
Source

pub async fn add_proxy_arp_by_index( &self, ifindex: u32, destination: Ipv4Addr, ) -> Result<()>

Add a proxy ARP entry by interface index.

Source

pub async fn del_proxy_arp( &self, ifname: impl Into<InterfaceRef>, destination: Ipv4Addr, ) -> Result<()>

Delete a proxy ARP entry.

Source

pub async fn del_proxy_arp_by_index( &self, ifindex: u32, destination: Ipv4Addr, ) -> Result<()>

Delete a proxy ARP entry by interface index.

Source

pub async fn get_neighbors_by_index( &self, ifindex: u32, ) -> Result<Vec<NeighborMessage>>

Get neighbor entries for an interface by index.

Source§

impl Connection<Netfilter>

Source

pub fn new() -> Result<Self>

Create a new netfilter connection.

§Example
use nlink::netlink::{Connection, Netfilter};

let conn = Connection::<Netfilter>::new()?;
Source

pub async fn get_conntrack(&self) -> Result<Vec<ConntrackEntry>>

Get all connection tracking entries.

§Example
use nlink::netlink::{Connection, Netfilter};

let conn = Connection::<Netfilter>::new()?;
let entries = conn.get_conntrack().await?;

for entry in &entries {
    println!("{:?}: {:?} -> {:?}",
        entry.proto,
        entry.orig.src_ip,
        entry.orig.dst_ip);
}
Source

pub async fn get_conntrack_v6(&self) -> Result<Vec<ConntrackEntry>>

Get connection tracking entries for IPv6.

Source§

impl Connection<Route>

Source

pub async fn get_nexthops(&self) -> Result<Vec<Nexthop>>

Get all nexthops (including groups).

§Example
let nexthops = conn.get_nexthops().await?;
for nh in &nexthops {
    if nh.is_group() {
        println!("Group {}: {:?}", nh.id, nh.group);
    } else {
        println!("NH {}: {:?} via {:?}", nh.id, nh.gateway, nh.ifindex);
    }
}
Source

pub async fn get_nexthop(&self, id: u32) -> Result<Option<Nexthop>>

Get a specific nexthop by ID.

Returns None if the nexthop doesn’t exist.

Source

pub async fn add_nexthop(&self, nh_builder: NexthopBuilder) -> Result<()>

Add a nexthop.

§Example
use nlink::netlink::nexthop::NexthopBuilder;

conn.add_nexthop(
    NexthopBuilder::new(1)
        .gateway("192.168.1.1".parse()?)
        .dev("eth0")
).await?;
Source

pub async fn replace_nexthop(&self, nh_builder: NexthopBuilder) -> Result<()>

Replace a nexthop (add or update).

If the nexthop exists, it’s updated. If it doesn’t exist, it’s created.

Source

pub async fn del_nexthop(&self, id: u32) -> Result<()>

Delete a nexthop by ID.

Note: Deleting a nexthop that is in use by routes or groups will fail.

Source

pub async fn add_nexthop_group( &self, builder: NexthopGroupBuilder, ) -> Result<()>

Add a nexthop group.

§Example
use nlink::netlink::nexthop::NexthopGroupBuilder;

// ECMP group with equal weights
conn.add_nexthop_group(
    NexthopGroupBuilder::new(100)
        .member(1, 1)
        .member(2, 1)
).await?;

// Weighted multipath (2:1 ratio)
conn.add_nexthop_group(
    NexthopGroupBuilder::new(101)
        .member(1, 2)
        .member(2, 1)
).await?;

// Resilient group with custom parameters
conn.add_nexthop_group(
    NexthopGroupBuilder::new(102)
        .resilient()
        .member(1, 1)
        .member(2, 1)
        .buckets(128)
        .idle_timer(120)
).await?;
Source

pub async fn replace_nexthop_group( &self, builder: NexthopGroupBuilder, ) -> Result<()>

Replace a nexthop group (add or update).

Source

pub async fn del_nexthop_group(&self, id: u32) -> Result<()>

Delete a nexthop group by ID.

Note: Deleting a group that is in use by routes will fail.

Source

pub async fn get_nexthop_groups(&self) -> Result<Vec<Nexthop>>

Get only nexthop groups (not individual nexthops).

Source§

impl Connection<Nftables>

Source

pub async fn add_table(&self, name: &str, family: Family) -> Result<()>

Create an nftables table.

§Example
conn.add_table("filter", Family::Inet).await?;
Source

pub async fn list_tables(&self) -> Result<Vec<Table>>

List all nftables tables.

Source

pub async fn del_table(&self, name: &str, family: Family) -> Result<()>

Delete an nftables table.

Source

pub async fn flush_table(&self, name: &str, family: Family) -> Result<()>

Flush all rules from a table (keeps chains).

Source

pub async fn add_chain(&self, chain: Chain) -> Result<()>

Create an nftables chain.

§Example
conn.add_chain(
    Chain::new("filter", "input")
        .family(Family::Inet)
        .hook(Hook::Input)
        .priority(Priority::Filter)
        .policy(Policy::Accept)
        .chain_type(ChainType::Filter)
).await?;
Source

pub async fn list_chains(&self) -> Result<Vec<ChainInfo>>

List all chains.

Source

pub async fn del_chain( &self, table: &str, name: &str, family: Family, ) -> Result<()>

Delete a chain.

Source

pub async fn add_rule(&self, rule: Rule) -> Result<()>

Add a rule to a chain.

§Example
conn.add_rule(
    Rule::new("filter", "input")
        .family(Family::Inet)
        .match_tcp_dport(22)
        .accept()
).await?;
Source

pub async fn list_rules( &self, table: &str, family: Family, ) -> Result<Vec<RuleInfo>>

List all rules in a table.

Source

pub async fn del_rule( &self, table: &str, chain: &str, family: Family, handle: u64, ) -> Result<()>

Delete a rule by handle.

Source

pub async fn add_set(&self, set: Set) -> Result<()>

Create an nftables set.

Source

pub async fn list_sets(&self, family: Family) -> Result<Vec<SetInfo>>

List all sets.

Source

pub async fn del_set( &self, table: &str, name: &str, family: Family, ) -> Result<()>

Delete a set.

Source

pub async fn add_set_elements( &self, table: &str, set: &str, family: Family, elements: &[SetElement], ) -> Result<()>

Add elements to a set.

Source

pub async fn del_set_elements( &self, table: &str, set: &str, family: Family, elements: &[SetElement], ) -> Result<()>

Delete elements from a set.

Source

pub fn transaction(&self) -> Transaction

Create a new batch transaction builder.

All operations added to the transaction are applied atomically.

§Example
conn.transaction()
    .add_table("filter", Family::Inet)
    .add_chain(chain)
    .add_rule(rule)
    .commit(&conn)
    .await?;
Source

pub async fn flush_ruleset(&self) -> Result<()>

Flush the entire ruleset (all tables, chains, rules, sets).

Source§

impl Connection<Route>

Source

pub async fn add_route<R: RouteConfig>(&self, config: R) -> Result<()>

Add a route.

§Example
use nlink::netlink::route::{Ipv4Route, Ipv6Route};
use std::net::{Ipv4Addr, Ipv6Addr};

// Add IPv4 route
conn.add_route(
    Ipv4Route::new("192.168.2.0", 24)
        .gateway(Ipv4Addr::new(192, 168, 1, 1))
).await?;

// Add IPv6 route
conn.add_route(
    Ipv6Route::new("2001:db8:2::", 48)
        .gateway("2001:db8::1".parse()?)
).await?;

// Add route with interface by index (namespace-safe)
conn.add_route(
    Ipv4Route::new("10.0.0.0", 8)
        .dev_index(5)
).await?;
Source

pub async fn del_route<R: RouteConfig>(&self, config: R) -> Result<()>

Delete a route using a config.

Source

pub async fn del_route_v4( &self, destination: &str, prefix_len: u8, ) -> Result<()>

Delete an IPv4 route by destination.

§Example
conn.del_route_v4("192.168.2.0", 24).await?;
Source

pub async fn del_route_v6( &self, destination: &str, prefix_len: u8, ) -> Result<()>

Delete an IPv6 route by destination.

Source

pub async fn replace_route<R: RouteConfig>(&self, config: R) -> Result<()>

Replace a route (add or update).

If the route exists, it will be updated. Otherwise, it will be created.

Source§

impl Connection<SELinux>

Source

pub fn new() -> Result<Self>

Create a new SELinux connection.

This creates a netlink socket bound to the SELNLGRP_AVC multicast group to receive SELinux event notifications.

§Example
use nlink::netlink::{Connection, SELinux};

let conn = Connection::<SELinux>::new()?;
Source

pub async fn recv(&self) -> Result<SELinuxEvent>

Receive the next SELinux event.

This method blocks until an event is received from the kernel.

§Example
use nlink::netlink::{Connection, SELinux};
use nlink::netlink::selinux::SELinuxEvent;

let conn = Connection::<SELinux>::new()?;

loop {
    match conn.recv().await? {
        SELinuxEvent::SetEnforce { enforcing } => {
            if enforcing {
                println!("SELinux now enforcing");
            } else {
                println!("SELinux now permissive");
            }
        }
        SELinuxEvent::PolicyLoad { seqno } => {
            println!("New policy loaded (seqno: {})", seqno);
        }
    }
}
Source

pub fn is_available() -> bool

Check if SELinux is available on this system.

This checks if the SELinux filesystem is mounted.

Source

pub fn get_enforce() -> Result<bool>

Get the current SELinux enforcement mode.

Returns true if enforcing, false if permissive, or an error if SELinux is not available.

Source§

impl Connection<SockDiag>

Source

pub async fn query(&self, filter: &SocketFilter) -> Result<Vec<SocketInfo>>

Query sockets matching the given filter.

§Example
use nlink::netlink::{Connection, SockDiag};
use nlink::sockdiag::SocketFilter;

let conn = Connection::<SockDiag>::new()?;
let filter = SocketFilter::tcp().listening().build();
let sockets = conn.query(&filter).await?;
Source

pub async fn query_tcp(&self) -> Result<Vec<InetSocket>>

Query TCP sockets with default filter.

§Example
use nlink::netlink::{Connection, SockDiag};

let conn = Connection::<SockDiag>::new()?;
let sockets = conn.query_tcp().await?;
for sock in sockets {
    println!("{} -> {}", sock.local, sock.remote);
}
Source

pub async fn query_udp(&self) -> Result<Vec<InetSocket>>

Query UDP sockets with default filter.

Source

pub async fn query_unix_sockets(&self) -> Result<Vec<UnixSocket>>

Query Unix sockets with default filter.

Query Netlink sockets with default filter.

Source

pub async fn socket_summary(&self) -> Result<SocketSummary>

Get aggregated socket statistics across all families.

Queries TCP, UDP, raw, and Unix sockets and aggregates the counts by state. This is equivalent to ss -s.

§Example
use nlink::netlink::{Connection, SockDiag};

let conn = Connection::<SockDiag>::new()?;
let summary = conn.socket_summary().await?;
println!("{}", summary);
// Total: 234
// TCP:   45 (estab 23, closed 12, orphaned 0, timewait 8)
// UDP:   12
// RAW:   2
// UNIX:  175
Source

pub async fn destroy_tcp_socket(&self, socket: &InetSocket) -> Result<()>

Force-close a TCP socket by sending SOCK_DESTROY.

The kernel sends a RST to the remote peer. Requires CAP_NET_ADMIN and Linux 4.9+. Only TCP sockets can be destroyed.

§Errors

Returns Error::Kernel with EPERM if insufficient privileges. Returns Error::Kernel with EOPNOTSUPP if the socket type doesn’t support destruction.

§Example
let sockets = conn.query_tcp().await?;
for sock in &sockets {
    if sock.remote.port() == 8080 {
        conn.destroy_tcp_socket(sock).await?;
    }
}
Source

pub async fn destroy_matching( &self, filter: &InetFilter, ) -> Result<DestroyResult>

Destroy all TCP sockets matching the given filter.

Queries sockets matching the filter, then destroys each one. Returns a DestroyResult with the count of destroyed sockets and any errors. Requires CAP_NET_ADMIN.

§Example
use nlink::sockdiag::{InetFilter, Protocol, TcpState};

let conn = Connection::<SockDiag>::new()?;
let filter = InetFilter {
    protocol: Protocol::Tcp,
    states: TcpState::TimeWait.mask(),
    ..Default::default()
};
let result = conn.destroy_matching(&filter).await?;
println!("Destroyed {} sockets", result.destroyed);
Source§

impl Connection<Route>

Source

pub async fn get_srv6_local_routes(&self) -> Result<Vec<Srv6LocalRoute>>

Get all SRv6 local routes.

Returns routes that use LWTUNNEL_ENCAP_SEG6_LOCAL encapsulation.

§Example
let routes = conn.get_srv6_local_routes().await?;
for route in &routes {
    println!("SID {:?}: {:?}", route.sid, route.action);
}
Source

pub async fn add_srv6_local(&self, builder: Srv6LocalBuilder) -> Result<()>

Add an SRv6 local route.

§Example
// End.DT4 SID
conn.add_srv6_local(
    Srv6LocalBuilder::end_dt4("fc00:1::100".parse()?, 100)
        .dev("eth0")
).await?;

// End.X SID
conn.add_srv6_local(
    Srv6LocalBuilder::end_x("fc00:1::1".parse()?, "fe80::1".parse()?)
        .dev("eth0")
).await?;
Source

pub async fn replace_srv6_local(&self, builder: Srv6LocalBuilder) -> Result<()>

Replace an SRv6 local route (add or update).

Source

pub async fn del_srv6_local(&self, sid: Ipv6Addr) -> Result<()>

Delete an SRv6 local route by SID.

§Example
conn.del_srv6_local("fc00:1::100".parse()?).await?;
Source§

impl<P: EventSource> Connection<P>

Source

pub fn events(&self) -> EventSubscription<'_, P>

Create an event stream that borrows this connection.

Returns a Stream that borrows the connection. The connection remains usable for queries while the stream is active.

§Example
use nlink::netlink::{Connection, KobjectUevent};
use tokio_stream::StreamExt;

let conn = Connection::<KobjectUevent>::new()?;

// Borrow connection for streaming
let mut events = conn.events();
while let Some(event) = events.try_next().await? {
    if event.is_add() {
        println!("Device added: {}", event.devpath);
    }
}

// Connection still usable
drop(events);
Source

pub fn into_events(self) -> OwnedEventStream<P>

Convert this connection into an owned event stream.

This consumes the connection. Use events() if you need to keep using the connection for queries.

§Example
use nlink::netlink::{Connection, SELinux};
use tokio_stream::StreamExt;

let conn = Connection::<SELinux>::new()?;
let mut stream = conn.into_events();

while let Some(event) = stream.try_next().await? {
    println!("{:?}", event);
}

// Recover connection if needed
let conn = stream.into_connection();
Source§

impl Connection<Route>

Source

pub async fn add_qdisc( &self, dev: impl Into<InterfaceRef>, config: impl QdiscConfig, ) -> Result<()>

Add a qdisc to an interface.

§Example
use nlink::netlink::tc::NetemConfig;
use std::time::Duration;

let netem = NetemConfig::new()
    .delay(Duration::from_millis(100))
    .loss(1.0)
    .build();

conn.add_qdisc("eth0", netem).await?;
Source

pub async fn add_qdisc_full( &self, dev: impl Into<InterfaceRef>, parent: &str, handle: Option<&str>, config: impl QdiscConfig, ) -> Result<()>

Add a qdisc with explicit parent and handle.

Source

pub async fn add_qdisc_by_index( &self, ifindex: u32, config: impl QdiscConfig, ) -> Result<()>

Add a qdisc by interface index.

This is useful for namespace-aware operations where you’ve already resolved the interface index via conn.get_link_by_name().

§Example
use nlink::netlink::{Connection, Route, namespace, tc::NetemConfig};
use std::time::Duration;

let conn: Connection<Route> = namespace::connection_for("myns")?;
let link = conn.get_link_by_name("eth0").await?;

let netem = NetemConfig::new()
    .delay(Duration::from_millis(100))
    .build();

conn.add_qdisc_by_index(link.ifindex(), netem).await?;
Source

pub async fn add_qdisc_by_index_full( &self, ifindex: u32, parent: &str, handle: Option<&str>, config: impl QdiscConfig, ) -> Result<()>

Add a qdisc by interface index with explicit parent and handle.

Source

pub async fn del_qdisc( &self, dev: impl Into<InterfaceRef>, parent: &str, ) -> Result<()>

Delete a qdisc from an interface.

§Example
conn.del_qdisc("eth0", "root").await?;
Source

pub async fn del_qdisc_full( &self, dev: impl Into<InterfaceRef>, parent: &str, handle: Option<&str>, ) -> Result<()>

Delete a qdisc with explicit handle.

Source

pub async fn del_qdisc_by_index(&self, ifindex: u32, parent: &str) -> Result<()>

Delete a qdisc by interface index.

This is useful for namespace-aware operations where you’ve already resolved the interface index via conn.get_link_by_name().

Source

pub async fn del_qdisc_by_index_full( &self, ifindex: u32, parent: &str, handle: Option<&str>, ) -> Result<()>

Delete a qdisc by interface index with explicit handle.

Source

pub async fn replace_qdisc( &self, dev: impl Into<InterfaceRef>, config: impl QdiscConfig, ) -> Result<()>

Replace a qdisc (add or update).

§Example
let netem = NetemConfig::new()
    .delay(Duration::from_millis(50))
    .build();

conn.replace_qdisc("eth0", netem).await?;
Source

pub async fn replace_qdisc_full( &self, dev: impl Into<InterfaceRef>, parent: &str, handle: Option<&str>, config: impl QdiscConfig, ) -> Result<()>

Replace a qdisc with explicit parent and handle.

Source

pub async fn replace_qdisc_by_index( &self, ifindex: u32, config: impl QdiscConfig, ) -> Result<()>

Replace a qdisc by interface index (add or update).

This is useful for namespace-aware operations where you’ve already resolved the interface index via conn.get_link_by_name().

Source

pub async fn replace_qdisc_by_index_full( &self, ifindex: u32, parent: &str, handle: Option<&str>, config: impl QdiscConfig, ) -> Result<()>

Replace a qdisc by interface index with explicit parent and handle.

Source

pub async fn change_qdisc( &self, dev: impl Into<InterfaceRef>, parent: &str, config: impl QdiscConfig, ) -> Result<()>

Change a qdisc’s parameters.

§Example
let netem = NetemConfig::new()
    .delay(Duration::from_millis(200))
    .build();

conn.change_qdisc("eth0", "root", netem).await?;
Source

pub async fn change_qdisc_full( &self, dev: impl Into<InterfaceRef>, parent: &str, handle: Option<&str>, config: impl QdiscConfig, ) -> Result<()>

Change a qdisc with explicit handle.

Source

pub async fn change_qdisc_by_index( &self, ifindex: u32, parent: &str, config: impl QdiscConfig, ) -> Result<()>

Change a qdisc’s parameters by interface index.

This is useful for namespace-aware operations where you’ve already resolved the interface index via conn.get_link_by_name().

Source

pub async fn change_qdisc_by_index_full( &self, ifindex: u32, parent: &str, handle: Option<&str>, config: impl QdiscConfig, ) -> Result<()>

Change a qdisc by interface index with explicit handle.

Source

pub async fn apply_netem( &self, dev: impl Into<InterfaceRef>, config: NetemConfig, ) -> Result<()>

Apply a netem configuration to an interface.

This is a convenience method that replaces any existing root qdisc with a netem qdisc. If no root qdisc exists, it creates one.

§Example
use nlink::netlink::tc::NetemConfig;
use std::time::Duration;

let netem = NetemConfig::new()
    .delay(Duration::from_millis(100))
    .jitter(Duration::from_millis(10))
    .loss(1.0)
    .build();

conn.apply_netem("eth0", netem).await?;
Source

pub async fn apply_netem_by_index( &self, ifindex: u32, config: NetemConfig, ) -> Result<()>

Apply a netem configuration by interface index.

This is useful for namespace-aware operations where you’ve already resolved the interface index via conn.get_link_by_name(). If no root qdisc exists, it creates one.

Source

pub async fn del_netem(&self, dev: impl Into<InterfaceRef>) -> Result<()>

Remove netem configuration from an interface.

This deletes the root qdisc, which restores the default qdisc.

§Example
conn.del_netem("eth0").await?;
Source

pub async fn del_netem_by_index(&self, ifindex: u32) -> Result<()>

Remove netem configuration by interface index.

Source

pub async fn add_class( &self, dev: impl Into<InterfaceRef>, parent: &str, classid: &str, kind: &str, params: &[&str], ) -> Result<()>

Add a TC class.

§Example
use nlink::netlink::{Connection, Route};
use nlink::netlink::tc::HtbQdiscConfig;

let conn = Connection::<Route>::new()?;

// First add an HTB qdisc
let htb = HtbQdiscConfig::new().default_class(0x10).build();
conn.add_qdisc_full("eth0", "root", Some("1:"), htb).await?;

// Then add a class with rate 10mbit, ceil 100mbit
conn.add_class("eth0", "1:0", "1:10", "htb",
    &["rate", "10mbit", "ceil", "100mbit"]).await?;
Source

pub async fn add_class_by_index( &self, ifindex: u32, parent: &str, classid: &str, kind: &str, params: &[&str], ) -> Result<()>

Add a TC class by interface index.

This is useful for namespace-aware operations where you’ve already resolved the interface index via conn.get_link_by_name().

Source

pub async fn del_class( &self, dev: impl Into<InterfaceRef>, parent: &str, classid: &str, ) -> Result<()>

Delete a TC class.

§Example
conn.del_class("eth0", "1:0", "1:10").await?;
Source

pub async fn del_class_by_index( &self, ifindex: u32, parent: &str, classid: &str, ) -> Result<()>

Delete a TC class by interface index.

Source

pub async fn change_class( &self, dev: impl Into<InterfaceRef>, parent: &str, classid: &str, kind: &str, params: &[&str], ) -> Result<()>

Change a TC class’s parameters.

§Example
conn.change_class("eth0", "1:0", "1:10", "htb",
    &["rate", "20mbit", "ceil", "100mbit"]).await?;
Source

pub async fn change_class_by_index( &self, ifindex: u32, parent: &str, classid: &str, kind: &str, params: &[&str], ) -> Result<()>

Change a TC class by interface index.

Source

pub async fn replace_class( &self, dev: impl Into<InterfaceRef>, parent: &str, classid: &str, kind: &str, params: &[&str], ) -> Result<()>

Replace a TC class (add or update).

§Example
conn.replace_class("eth0", "1:0", "1:10", "htb",
    &["rate", "10mbit", "ceil", "100mbit"]).await?;
Source

pub async fn replace_class_by_index( &self, ifindex: u32, parent: &str, classid: &str, kind: &str, params: &[&str], ) -> Result<()>

Replace a TC class by interface index.

Source

pub async fn add_class_config<C: ClassConfig>( &self, dev: impl Into<InterfaceRef>, parent: &str, classid: &str, config: C, ) -> Result<()>

Add a TC class with typed configuration.

This method provides a type-safe way to add classes, as an alternative to the string-based add_class method.

§Example
use nlink::netlink::{Connection, Route};
use nlink::netlink::tc::{HtbQdiscConfig, HtbClassConfig};

let conn = Connection::<Route>::new()?;

// First add HTB qdisc
let htb = HtbQdiscConfig::new().default_class(0x30).build();
conn.add_qdisc_full("eth0", "root", Some("1:"), htb).await?;

// Add a class with guaranteed 100mbit, ceiling 500mbit
conn.add_class_config("eth0", "1:0", "1:10",
    HtbClassConfig::new("100mbit")?
        .ceil("500mbit")?
        .prio(1)
        .build()
).await?;
Source

pub async fn add_class_config_by_index<C: ClassConfig>( &self, ifindex: u32, parent: &str, classid: &str, config: C, ) -> Result<()>

Add a TC class with typed configuration by interface index.

This is useful for namespace-aware operations where you’ve already resolved the interface index via conn.get_link_by_name().

Source

pub async fn change_class_config<C: ClassConfig>( &self, dev: impl Into<InterfaceRef>, parent: &str, classid: &str, config: C, ) -> Result<()>

Change a TC class with typed configuration.

§Example
// Update an existing class's rate
conn.change_class_config("eth0", "1:0", "1:10",
    HtbClassConfig::new("200mbit")?
        .ceil("800mbit")?
        .build()
).await?;
Source

pub async fn change_class_config_by_index<C: ClassConfig>( &self, ifindex: u32, parent: &str, classid: &str, config: C, ) -> Result<()>

Change a TC class with typed configuration by interface index.

Source

pub async fn replace_class_config<C: ClassConfig>( &self, dev: impl Into<InterfaceRef>, parent: &str, classid: &str, config: C, ) -> Result<()>

Replace a TC class with typed configuration (add or update).

§Example
// Create or update a class
conn.replace_class_config("eth0", "1:0", "1:10",
    HtbClassConfig::new("100mbit")?
        .ceil("500mbit")?
        .build()
).await?;
Source

pub async fn replace_class_config_by_index<C: ClassConfig>( &self, ifindex: u32, parent: &str, classid: &str, config: C, ) -> Result<()>

Replace a TC class with typed configuration by interface index.

Source§

impl Connection<KobjectUevent>

Source

pub fn new() -> Result<Self>

Create a new uevent connection subscribed to kernel events.

The connection is automatically subscribed to the kernel uevent multicast group.

§Example
use nlink::netlink::{Connection, KobjectUevent};

let conn = Connection::<KobjectUevent>::new()?;
Source

pub async fn recv(&self) -> Result<Uevent>

Receive the next uevent from the kernel.

This method blocks until a uevent is available.

§Example
use nlink::netlink::{Connection, KobjectUevent};

let conn = Connection::<KobjectUevent>::new()?;

loop {
    let event = conn.recv().await?;
    if event.is_add() && event.subsystem == "usb" {
        println!("USB device added: {:?}", event.devname());
    }
}
Source

pub fn try_recv(&self) -> Result<Option<Uevent>>

Try to receive a uevent without blocking.

Returns Ok(None) if no event is immediately available.

Source§

impl Connection<Xfrm>

Source

pub fn new() -> Result<Self>

Create a new XFRM connection.

§Example
use nlink::netlink::{Connection, Xfrm};

let conn = Connection::<Xfrm>::new()?;
Source

pub async fn get_security_associations( &self, ) -> Result<Vec<SecurityAssociation>>

Get all Security Associations.

§Example
use nlink::netlink::{Connection, Xfrm};

let conn = Connection::<Xfrm>::new()?;
let sas = conn.get_security_associations().await?;

for sa in &sas {
    println!("{:?} -> {:?} SPI={:08x} proto={:?}",
        sa.src_addr, sa.dst_addr, sa.spi, sa.protocol);
}
Source

pub async fn get_security_policies(&self) -> Result<Vec<SecurityPolicy>>

Get all Security Policies.

§Example
use nlink::netlink::{Connection, Xfrm};

let conn = Connection::<Xfrm>::new()?;
let policies = conn.get_security_policies().await?;

for pol in &policies {
    println!("dir={:?} action={:?} priority={}",
        pol.direction, pol.action, pol.priority);
}

Auto Trait Implementations§

§

impl<P> !Freeze for Connection<P>

§

impl<P> !RefUnwindSafe for Connection<P>

§

impl<P> Send for Connection<P>
where P: Send,

§

impl<P> Sync for Connection<P>
where P: Sync,

§

impl<P> Unpin for Connection<P>
where P: Unpin,

§

impl<P> UnsafeUnpin for Connection<P>
where P: UnsafeUnpin,

§

impl<P> !UnwindSafe for Connection<P>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.