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.

§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: &str, 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_v4( &self, ifname: &str, address: Ipv4Addr, prefix_len: u8, ) -> Result<()>

Delete an IPv4 address from an interface.

Source

pub async fn del_address_v6( &self, ifname: &str, 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: &str) -> Result<()>

Flush all addresses from an interface.

§Example
conn.flush_addresses("eth0").await?;
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: &str) -> 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: &str, ) -> 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, ) -> 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: &str, 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: &str, 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§

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>

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 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_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_for( &self, ifname: &str, ) -> Result<Vec<AddressMessage>>

Get IP addresses for a specific interface by name.

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_for( &self, ifname: &str, ) -> Result<Vec<NeighborMessage>>

Get neighbor entries for a specific interface.

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_for(&self, ifname: &str) -> Result<Vec<TcMessage>>

Get qdiscs for a specific interface.

Source

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

Get all TC classes.

Source

pub async fn get_classes_for(&self, ifname: &str) -> Result<Vec<TcMessage>>

Get TC classes for a specific interface.

Source

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

Get all TC filters.

Source

pub async fn get_filters_for(&self, ifname: &str) -> Result<Vec<TcMessage>>

Get TC filters for a specific interface.

Source

pub async fn get_tc_chains( &self, ifname: &str, 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: &str, 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: &str, 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_for( &self, ifname: &str, ) -> Result<Option<TcMessage>>

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

Returns None if no root qdisc is configured.

§Example
if let Some(root) = conn.get_root_qdisc_for("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_for(&self, ifname: &str) -> 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.

§Example
if let Some(netem) = conn.get_netem_for("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.

§Example
conn.set_link_up("eth0").await?;

Bring a network interface up by index.

Bring a network interface down.

§Example
conn.set_link_down("eth0").await?;

Bring a network interface down by index.

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

§Arguments
  • ifname - The interface name (e.g., “eth0”)
  • 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
conn.set_link_state("eth0", false).await?;

Set the state of a network interface by index.

Set the MTU of a network interface.

§Example
conn.set_link_mtu("eth0", 9000).await?;

Set the MTU of a network interface by index.

Delete a network interface.

§Example
conn.del_link("veth0").await?;

Delete a network interface by index.

Set the TX queue length of a network interface.

§Example
conn.set_link_txqlen("eth0", 1000).await?;

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: &str) -> 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: &str, port: &str, ) -> 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?;
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: &str, 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: &str) -> 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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§

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, ifname: &str) -> Result<MacsecDevice>

Get device information.

Returns the current configuration and status of the MACsec interface.

§Example
let device = conn.get_device("macsec0").await?;
println!("SCI: {:016x}", device.sci);
println!("Cipher: {:?}", device.cipher);
Source

pub async fn add_tx_sa(&self, ifname: &str, sa: MacsecSaBuilder) -> Result<()>

Add a TX Security Association.

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

pub async fn del_tx_sa(&self, ifname: &str, an: u8) -> Result<()>

Delete a TX Security Association.

§Arguments
  • ifname - Interface name
  • an - Association Number (0-3)
Source

pub async fn update_tx_sa( &self, ifname: &str, sa: MacsecSaBuilder, ) -> Result<()>

Update a TX Security Association.

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

Source

pub async fn add_rx_sc(&self, ifname: &str, sci: u64) -> Result<()>

Add an RX Secure Channel.

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

pub async fn del_rx_sc(&self, ifname: &str, sci: u64) -> Result<()>

Delete an RX Secure Channel.

This also deletes all associated RX SAs.

Source

pub async fn add_rx_sa( &self, ifname: &str, sci: u64, sa: MacsecSaBuilder, ) -> Result<()>

Add an RX Security Association.

§Arguments
  • ifname - Interface name
  • sci - Secure Channel Identifier
  • sa - SA configuration
Source

pub async fn del_rx_sa(&self, ifname: &str, sci: u64, an: u8) -> Result<()>

Delete an RX Security Association.

Source

pub async fn update_rx_sa( &self, ifname: &str, sci: u64, sa: MacsecSaBuilder, ) -> Result<()>

Update an RX Security Association.

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 remove_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.remove_addr(connection_token, 1).await?;
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 async fn get_device(&self, ifname: &str) -> Result<WgDevice>

Get device information.

Returns the current configuration and status of the WireGuard interface.

Source

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

Set device configuration.

The builder closure allows configuring the device properties.

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

let conn = Connection::<Wireguard>::new_async().await?;
conn.set_device("wg0", |dev| {
    dev.private_key(my_key)
       .listen_port(51820)
}).await?;
Source

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

Add or update a peer.

If the peer already exists, its configuration is updated. If not, a new peer is added.

Source

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

Remove a peer by public key.

Source

pub fn family_id(&self) -> u16

Get the WireGuard family ID.

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?;

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?;

Set the master device by interface indices.

Remove an interface from its master device.

§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.

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.

§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.

§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.

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, 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, 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.

§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 del_neighbor_v4( &self, ifname: &str, 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_v6( &self, ifname: &str, destination: Ipv6Addr, ) -> Result<()>

Delete an IPv6 neighbor entry.

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 flush_neighbors(&self, ifname: &str) -> Result<()>

Flush all neighbor entries for an interface.

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

pub async fn add_proxy_arp( &self, ifname: &str, 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 del_proxy_arp( &self, ifname: &str, destination: Ipv4Addr, ) -> Result<()>

Delete a proxy ARP entry.

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, 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, 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<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?;
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.

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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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 remove_netem(&self, dev: &str) -> Result<()>

Remove netem configuration from an interface.

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

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

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

Remove netem configuration by interface index.

Source

pub async fn add_class( &self, dev: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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: &str, 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> !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.