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:
Connection<Route>: RTNetlink for interfaces, addresses, routes, TCConnection<Generic>: Generic netlink for WireGuard, MACsec, etc.
§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>
impl Connection<Route>
Sourcepub async fn add_address<A: AddressConfig>(&self, config: A) -> Result<()>
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?;Sourcepub async fn del_address(
&self,
ifname: &str,
address: IpAddr,
prefix_len: u8,
) -> Result<()>
pub async fn del_address( &self, ifname: &str, address: IpAddr, prefix_len: u8, ) -> Result<()>
Sourcepub async fn del_address_v4(
&self,
ifname: &str,
address: Ipv4Addr,
prefix_len: u8,
) -> Result<()>
pub async fn del_address_v4( &self, ifname: &str, address: Ipv4Addr, prefix_len: u8, ) -> Result<()>
Delete an IPv4 address from an interface.
Sourcepub async fn del_address_v6(
&self,
ifname: &str,
address: Ipv6Addr,
prefix_len: u8,
) -> Result<()>
pub async fn del_address_v6( &self, ifname: &str, address: Ipv6Addr, prefix_len: u8, ) -> Result<()>
Delete an IPv6 address from an interface.
Sourcepub async fn del_address_config<A: AddressConfig>(
&self,
config: A,
) -> Result<()>
pub async fn del_address_config<A: AddressConfig>( &self, config: A, ) -> Result<()>
Delete an IP address using a typed config.
Sourcepub async fn replace_address<A: AddressConfig>(&self, config: A) -> Result<()>
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§impl Connection<Audit>
impl Connection<Audit>
Sourcepub async fn get_status(&self) -> Result<AuditStatus>
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);Sourcepub async fn get_tty_status(&self) -> Result<AuditTtyStatus>
pub async fn get_tty_status(&self) -> Result<AuditTtyStatus>
Sourcepub async fn get_features(&self) -> Result<AuditFeatures>
pub async fn get_features(&self) -> Result<AuditFeatures>
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn get_bridge_vlans(&self, dev: &str) -> Result<Vec<BridgeVlanEntry>>
pub async fn get_bridge_vlans(&self, dev: &str) -> Result<Vec<BridgeVlanEntry>>
Sourcepub async fn get_bridge_vlans_by_index(
&self,
ifindex: u32,
) -> Result<Vec<BridgeVlanEntry>>
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.
Sourcepub async fn get_bridge_vlans_all(
&self,
bridge: &str,
) -> Result<Vec<BridgeVlanEntry>>
pub async fn get_bridge_vlans_all( &self, bridge: &str, ) -> Result<Vec<BridgeVlanEntry>>
Sourcepub async fn get_bridge_vlans_all_by_index(
&self,
bridge_idx: u32,
) -> Result<Vec<BridgeVlanEntry>>
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.
Sourcepub async fn add_bridge_vlan(&self, config: BridgeVlanBuilder) -> Result<()>
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?;Sourcepub async fn del_bridge_vlan_by_index(
&self,
ifindex: u32,
vid: u16,
) -> Result<()>
pub async fn del_bridge_vlan_by_index( &self, ifindex: u32, vid: u16, ) -> Result<()>
Delete VLAN from a bridge port by interface index.
Sourcepub async fn del_bridge_vlan_range(
&self,
dev: &str,
vid_start: u16,
vid_end: u16,
) -> Result<()>
pub async fn del_bridge_vlan_range( &self, dev: &str, vid_start: u16, vid_end: u16, ) -> Result<()>
Sourcepub async fn set_bridge_pvid_by_index(
&self,
ifindex: u32,
vid: u16,
) -> Result<()>
pub async fn set_bridge_pvid_by_index( &self, ifindex: u32, vid: u16, ) -> Result<()>
Set PVID for a bridge port by interface index.
Sourcepub async fn add_bridge_vlan_range(
&self,
dev: &str,
vid_start: u16,
vid_end: u16,
) -> Result<()>
pub async fn add_bridge_vlan_range( &self, dev: &str, vid_start: u16, vid_end: u16, ) -> Result<()>
Sourcepub async fn get_vlan_tunnels(
&self,
dev: &str,
) -> Result<Vec<BridgeVlanTunnelEntry>>
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);
}Sourcepub async fn get_vlan_tunnels_by_index(
&self,
ifindex: u32,
) -> Result<Vec<BridgeVlanTunnelEntry>>
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.
Sourcepub async fn add_vlan_tunnel(
&self,
config: BridgeVlanTunnelBuilder,
) -> Result<()>
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§impl<P: ProtocolState + Default> Connection<P>
impl<P: ProtocolState + Default> Connection<P>
Sourcepub fn new() -> Result<Self>
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()?;Sourcepub fn new_in_namespace(ns_fd: RawFd) -> Result<Self>
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?;Sourcepub fn new_in_namespace_path<T: AsRef<Path>>(ns_path: T) -> Result<Self>
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>
impl<P: ProtocolState> Connection<P>
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub fn for_namespace(spec: NamespaceSpec<'_>) -> Result<Self>
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)?;Sourcepub fn subscribe(&mut self, groups: &[RtnetlinkGroup]) -> Result<()>
pub fn subscribe(&mut self, groups: &[RtnetlinkGroup]) -> Result<()>
Sourcepub fn subscribe_all(&mut self) -> Result<()>
pub fn subscribe_all(&mut self) -> Result<()>
Sourcepub async fn dump_typed<T: FromNetlink>(&self, msg_type: u16) -> Result<Vec<T>>
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);
}Sourcepub fn parse_response<T: FromNetlink>(&self, response: &[u8]) -> Result<T>
pub fn parse_response<T: FromNetlink>(&self, response: &[u8]) -> Result<T>
Parse a single response into a typed message.
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn get_links(&self) -> Result<Vec<LinkMessage>>
pub async fn get_links(&self) -> Result<Vec<LinkMessage>>
Sourcepub async fn get_link_by_name(&self, name: &str) -> Result<Option<LinkMessage>>
pub async fn get_link_by_name(&self, name: &str) -> Result<Option<LinkMessage>>
Get a network interface by name.
Returns None if the interface doesn’t exist.
Sourcepub async fn get_link_by_index(&self, index: u32) -> Result<Option<LinkMessage>>
pub async fn get_link_by_index(&self, index: u32) -> Result<Option<LinkMessage>>
Get a network interface by index.
Returns None if the interface doesn’t exist.
Sourcepub async fn get_interface_names(&self) -> Result<HashMap<u32, String>>
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);
}Sourcepub async fn interface_name(&self, ifindex: u32) -> Result<Option<String>>
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);
}Sourcepub async fn get_addresses(&self) -> Result<Vec<AddressMessage>>
pub async fn get_addresses(&self) -> Result<Vec<AddressMessage>>
Sourcepub async fn get_addresses_for(
&self,
ifname: &str,
) -> Result<Vec<AddressMessage>>
pub async fn get_addresses_for( &self, ifname: &str, ) -> Result<Vec<AddressMessage>>
Get IP addresses for a specific interface by name.
Sourcepub async fn get_addresses_by_index(
&self,
ifindex: u32,
) -> Result<Vec<AddressMessage>>
pub async fn get_addresses_by_index( &self, ifindex: u32, ) -> Result<Vec<AddressMessage>>
Get IP addresses for a specific interface by index.
Sourcepub async fn get_address_by_ip(
&self,
addr: IpAddr,
) -> Result<Option<AddressMessage>>
pub async fn get_address_by_ip( &self, addr: IpAddr, ) -> Result<Option<AddressMessage>>
Sourcepub async fn get_routes(&self) -> Result<Vec<RouteMessage>>
pub async fn get_routes(&self) -> Result<Vec<RouteMessage>>
Sourcepub async fn get_routes_for_table(
&self,
table_id: u32,
) -> Result<Vec<RouteMessage>>
pub async fn get_routes_for_table( &self, table_id: u32, ) -> Result<Vec<RouteMessage>>
Get routes for a specific table.
Sourcepub async fn get_route_v4(
&self,
destination: Ipv4Addr,
prefix_len: u8,
) -> Result<Option<RouteMessage>>
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);
}Sourcepub async fn get_route_v6(
&self,
destination: Ipv6Addr,
prefix_len: u8,
) -> Result<Option<RouteMessage>>
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);
}Sourcepub async fn get_neighbors(&self) -> Result<Vec<NeighborMessage>>
pub async fn get_neighbors(&self) -> Result<Vec<NeighborMessage>>
Sourcepub async fn get_neighbors_for(
&self,
ifname: &str,
) -> Result<Vec<NeighborMessage>>
pub async fn get_neighbors_for( &self, ifname: &str, ) -> Result<Vec<NeighborMessage>>
Get neighbor entries for a specific interface.
Sourcepub async fn get_rules(&self) -> Result<Vec<RuleMessage>>
pub async fn get_rules(&self) -> Result<Vec<RuleMessage>>
Sourcepub async fn get_rules_for_family(&self, family: u8) -> Result<Vec<RuleMessage>>
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_INETfor IPv4,libc::AF_INET6for IPv6
Sourcepub async fn get_rules_v4(&self) -> Result<Vec<RuleMessage>>
pub async fn get_rules_v4(&self) -> Result<Vec<RuleMessage>>
Get IPv4 routing rules.
Sourcepub async fn get_rules_v6(&self) -> Result<Vec<RuleMessage>>
pub async fn get_rules_v6(&self) -> Result<Vec<RuleMessage>>
Get IPv6 routing rules.
Sourcepub async fn add_rule(&self, rule: RuleBuilder) -> Result<()>
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?;Sourcepub async fn del_rule(&self, rule: RuleBuilder) -> Result<()>
pub async fn del_rule(&self, rule: RuleBuilder) -> Result<()>
Sourcepub async fn del_rule_by_priority(
&self,
family: u8,
priority: u32,
) -> Result<()>
pub async fn del_rule_by_priority( &self, family: u8, priority: u32, ) -> Result<()>
Delete a rule by priority.
Sourcepub async fn flush_rules(&self, family: u8) -> Result<()>
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).
Sourcepub async fn get_qdiscs(&self) -> Result<Vec<TcMessage>>
pub async fn get_qdiscs(&self) -> Result<Vec<TcMessage>>
Sourcepub async fn get_qdiscs_for(&self, ifname: &str) -> Result<Vec<TcMessage>>
pub async fn get_qdiscs_for(&self, ifname: &str) -> Result<Vec<TcMessage>>
Get qdiscs for a specific interface.
Sourcepub async fn get_classes(&self) -> Result<Vec<TcMessage>>
pub async fn get_classes(&self) -> Result<Vec<TcMessage>>
Get all TC classes.
Sourcepub async fn get_classes_for(&self, ifname: &str) -> Result<Vec<TcMessage>>
pub async fn get_classes_for(&self, ifname: &str) -> Result<Vec<TcMessage>>
Get TC classes for a specific interface.
Sourcepub async fn get_filters(&self) -> Result<Vec<TcMessage>>
pub async fn get_filters(&self) -> Result<Vec<TcMessage>>
Get all TC filters.
Sourcepub async fn get_filters_for(&self, ifname: &str) -> Result<Vec<TcMessage>>
pub async fn get_filters_for(&self, ifname: &str) -> Result<Vec<TcMessage>>
Get TC filters for a specific interface.
Sourcepub async fn get_tc_chains_by_index(
&self,
ifindex: u32,
parent: &str,
) -> Result<Vec<u32>>
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.
Sourcepub async fn add_tc_chain_by_index(
&self,
ifindex: u32,
parent: &str,
chain: u32,
) -> Result<()>
pub async fn add_tc_chain_by_index( &self, ifindex: u32, parent: &str, chain: u32, ) -> Result<()>
Add a TC filter chain by interface index.
Sourcepub async fn del_tc_chain_by_index(
&self,
ifindex: u32,
parent: &str,
chain: u32,
) -> Result<()>
pub async fn del_tc_chain_by_index( &self, ifindex: u32, parent: &str, chain: u32, ) -> Result<()>
Delete a TC filter chain by interface index.
Sourcepub async fn get_root_qdisc_by_index(
&self,
ifindex: u32,
) -> Result<Option<TcMessage>>
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.
Sourcepub async fn get_qdisc_by_handle(
&self,
ifname: &str,
handle: &str,
) -> Result<Option<TcMessage>>
pub async fn get_qdisc_by_handle( &self, ifname: &str, handle: &str, ) -> Result<Option<TcMessage>>
Sourcepub async fn get_qdisc_by_handle_index(
&self,
ifindex: u32,
handle: &str,
) -> Result<Option<TcMessage>>
pub async fn get_qdisc_by_handle_index( &self, ifindex: u32, handle: &str, ) -> Result<Option<TcMessage>>
Sourcepub async fn get_netem_for(&self, ifname: &str) -> Result<Option<NetemOptions>>
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);
}
}Sourcepub async fn get_netem_by_index(
&self,
ifindex: u32,
) -> Result<Option<NetemOptions>>
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>
impl Connection<Route>
Sourcepub async fn set_link_up(&self, ifname: &str) -> Result<()>
pub async fn set_link_up(&self, ifname: &str) -> Result<()>
Sourcepub async fn set_link_up_by_index(&self, ifindex: u32) -> Result<()>
pub async fn set_link_up_by_index(&self, ifindex: u32) -> Result<()>
Bring a network interface up by index.
Sourcepub async fn set_link_down(&self, ifname: &str) -> Result<()>
pub async fn set_link_down(&self, ifname: &str) -> Result<()>
Sourcepub async fn set_link_down_by_index(&self, ifindex: u32) -> Result<()>
pub async fn set_link_down_by_index(&self, ifindex: u32) -> Result<()>
Bring a network interface down by index.
Sourcepub async fn set_link_state(&self, ifname: &str, up: bool) -> Result<()>
pub async fn set_link_state(&self, ifname: &str, up: bool) -> Result<()>
Set the state of a network interface (up or down).
§Arguments
ifname- The interface name (e.g., “eth0”)up-trueto bring the interface up,falseto bring it down
§Example
// Bring interface up
conn.set_link_state("eth0", true).await?;
// Bring interface down
conn.set_link_state("eth0", false).await?;Sourcepub async fn set_link_state_by_index(
&self,
ifindex: u32,
up: bool,
) -> Result<()>
pub async fn set_link_state_by_index( &self, ifindex: u32, up: bool, ) -> Result<()>
Set the state of a network interface by index.
Sourcepub async fn set_link_mtu_by_index(&self, ifindex: u32, mtu: u32) -> Result<()>
pub async fn set_link_mtu_by_index(&self, ifindex: u32, mtu: u32) -> Result<()>
Set the MTU of a network interface by index.
Sourcepub async fn del_link_by_index(&self, ifindex: u32) -> Result<()>
pub async fn del_link_by_index(&self, ifindex: u32) -> Result<()>
Delete a network interface by index.
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn get_nsid(&self, ns_fd: RawFd) -> Result<u32>
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);Sourcepub async fn get_nsid_for_pid(&self, pid: u32) -> Result<u32>
pub async fn get_nsid_for_pid(&self, pid: u32) -> Result<u32>
Source§impl Connection<Generic>
impl Connection<Generic>
Sourcepub async fn get_family(&self, name: &str) -> Result<FamilyInfo>
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);Sourcepub async fn get_family_id(&self, name: &str) -> Result<u16>
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.
Sourcepub fn clear_cache(&self)
pub fn clear_cache(&self)
Clear the family cache.
This is rarely needed, but may be useful if families are dynamically loaded/unloaded.
Sourcepub async fn command(
&self,
family_id: u16,
cmd: u8,
version: u8,
build_attrs: impl FnOnce(&mut MessageBuilder),
) -> Result<Vec<u8>>
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§impl Connection<Connector>
impl Connection<Connector>
Sourcepub async fn unregister(&self) -> Result<()>
pub async fn unregister(&self) -> Result<()>
Unregister from process events.
After calling this, no more events will be received.
Sourcepub async fn recv(&self) -> Result<ProcEvent>
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>
impl Connection<Route>
Sourcepub async fn get_fdb(&self, bridge: &str) -> Result<Vec<FdbEntry>>
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);
}Sourcepub async fn get_fdb_by_index(&self, bridge_idx: u32) -> Result<Vec<FdbEntry>>
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.
Sourcepub async fn add_fdb(&self, entry: FdbEntryBuilder) -> Result<()>
pub async fn add_fdb(&self, entry: FdbEntryBuilder) -> Result<()>
Sourcepub async fn replace_fdb(&self, entry: FdbEntryBuilder) -> Result<()>
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§impl Connection<FibLookup>
impl Connection<FibLookup>
Sourcepub async fn lookup(&self, addr: Ipv4Addr) -> Result<FibLookupResult>
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);
}Sourcepub async fn lookup_in_table(
&self,
addr: Ipv4Addr,
table: u8,
) -> Result<FibLookupResult>
pub async fn lookup_in_table( &self, addr: Ipv4Addr, table: u8, ) -> Result<FibLookupResult>
Sourcepub async fn lookup_with_mark(
&self,
addr: Ipv4Addr,
mark: u32,
) -> Result<FibLookupResult>
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?;Sourcepub async fn lookup_with_options(
&self,
request: FibResultNl,
) -> Result<FibLookupResult>
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>
impl Connection<Route>
Sourcepub async fn add_filter(
&self,
dev: &str,
parent: &str,
config: impl FilterConfig,
) -> Result<()>
pub async fn add_filter( &self, dev: &str, parent: &str, config: impl FilterConfig, ) -> Result<()>
Sourcepub async fn add_filter_full(
&self,
dev: &str,
parent: &str,
handle: Option<&str>,
protocol: u16,
priority: u16,
config: impl FilterConfig,
) -> Result<()>
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 nameparent- 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
Sourcepub async fn add_filter_by_index(
&self,
ifindex: u32,
parent: &str,
config: impl FilterConfig,
) -> Result<()>
pub async fn add_filter_by_index( &self, ifindex: u32, parent: &str, config: impl FilterConfig, ) -> Result<()>
Add a filter by interface index.
Sourcepub async fn add_filter_by_index_full(
&self,
ifindex: u32,
parent: &str,
handle: Option<&str>,
protocol: u16,
priority: u16,
config: impl FilterConfig,
) -> Result<()>
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.
Sourcepub async fn replace_filter(
&self,
dev: &str,
parent: &str,
config: impl FilterConfig,
) -> Result<()>
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?;Sourcepub async fn replace_filter_full(
&self,
dev: &str,
parent: &str,
handle: Option<&str>,
protocol: u16,
priority: u16,
config: impl FilterConfig,
) -> Result<()>
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.
Sourcepub async fn replace_filter_by_index(
&self,
ifindex: u32,
parent: &str,
config: impl FilterConfig,
) -> Result<()>
pub async fn replace_filter_by_index( &self, ifindex: u32, parent: &str, config: impl FilterConfig, ) -> Result<()>
Replace a filter by interface index.
Sourcepub async fn replace_filter_by_index_full(
&self,
ifindex: u32,
parent: &str,
handle: Option<&str>,
protocol: u16,
priority: u16,
config: impl FilterConfig,
) -> Result<()>
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.
Sourcepub async fn change_filter(
&self,
dev: &str,
parent: &str,
protocol: u16,
priority: u16,
config: impl FilterConfig,
) -> Result<()>
pub async fn change_filter( &self, dev: &str, parent: &str, protocol: u16, priority: u16, config: impl FilterConfig, ) -> Result<()>
Sourcepub async fn change_filter_full(
&self,
dev: &str,
parent: &str,
handle: Option<&str>,
protocol: u16,
priority: u16,
config: impl FilterConfig,
) -> Result<()>
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.
Sourcepub async fn change_filter_by_index(
&self,
ifindex: u32,
parent: &str,
protocol: u16,
priority: u16,
config: impl FilterConfig,
) -> Result<()>
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.
Sourcepub async fn change_filter_by_index_full(
&self,
ifindex: u32,
parent: &str,
handle: Option<&str>,
protocol: u16,
priority: u16,
config: impl FilterConfig,
) -> Result<()>
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.
Sourcepub async fn del_filter(
&self,
dev: &str,
parent: &str,
protocol: u16,
priority: u16,
) -> Result<()>
pub async fn del_filter( &self, dev: &str, parent: &str, protocol: u16, priority: u16, ) -> Result<()>
Sourcepub async fn del_filter_by_index(
&self,
ifindex: u32,
parent: &str,
protocol: u16,
priority: u16,
) -> Result<()>
pub async fn del_filter_by_index( &self, ifindex: u32, parent: &str, protocol: u16, priority: u16, ) -> Result<()>
Delete a filter by interface index.
Source§impl Connection<Macsec>
impl Connection<Macsec>
Sourcepub async fn get_device(&self, ifname: &str) -> Result<MacsecDevice>
pub async fn get_device(&self, ifname: &str) -> Result<MacsecDevice>
Sourcepub async fn update_tx_sa(
&self,
ifname: &str,
sa: MacsecSaBuilder,
) -> Result<()>
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.
Sourcepub async fn add_rx_sc(&self, ifname: &str, sci: u64) -> Result<()>
pub async fn add_rx_sc(&self, ifname: &str, sci: u64) -> Result<()>
Add an RX Secure Channel.
§Arguments
ifname- Interface namesci- Secure Channel Identifier (typically peer’s MAC + port)
Sourcepub async fn del_rx_sc(&self, ifname: &str, sci: u64) -> Result<()>
pub async fn del_rx_sc(&self, ifname: &str, sci: u64) -> Result<()>
Delete an RX Secure Channel.
This also deletes all associated RX SAs.
Sourcepub async fn add_rx_sa(
&self,
ifname: &str,
sci: u64,
sa: MacsecSaBuilder,
) -> Result<()>
pub async fn add_rx_sa( &self, ifname: &str, sci: u64, sa: MacsecSaBuilder, ) -> Result<()>
Add an RX Security Association.
§Arguments
ifname- Interface namesci- Secure Channel Identifiersa- SA configuration
Sourcepub async fn del_rx_sa(&self, ifname: &str, sci: u64, an: u8) -> Result<()>
pub async fn del_rx_sa(&self, ifname: &str, sci: u64, an: u8) -> Result<()>
Delete an RX Security Association.
Sourcepub async fn update_rx_sa(
&self,
ifname: &str,
sci: u64,
sa: MacsecSaBuilder,
) -> Result<()>
pub async fn update_rx_sa( &self, ifname: &str, sci: u64, sa: MacsecSaBuilder, ) -> Result<()>
Update an RX Security Association.
Source§impl Connection<Mptcp>
impl Connection<Mptcp>
Sourcepub async fn get_endpoints(&self) -> Result<Vec<MptcpEndpoint>>
pub async fn get_endpoints(&self) -> Result<Vec<MptcpEndpoint>>
Sourcepub async fn add_endpoint(&self, endpoint: MptcpEndpointBuilder) -> Result<()>
pub async fn add_endpoint(&self, endpoint: MptcpEndpointBuilder) -> Result<()>
Sourcepub async fn del_endpoint(&self, id: u8) -> Result<()>
pub async fn del_endpoint(&self, id: u8) -> Result<()>
Sourcepub async fn flush_endpoints(&self) -> Result<()>
pub async fn flush_endpoints(&self) -> Result<()>
Sourcepub async fn get_limits(&self) -> Result<MptcpLimits>
pub async fn get_limits(&self) -> Result<MptcpLimits>
Sourcepub async fn set_limits(&self, limits: MptcpLimits) -> Result<()>
pub async fn set_limits(&self, limits: MptcpLimits) -> Result<()>
Sourcepub async fn set_endpoint_flags(&self, id: u8, flags: MptcpFlags) -> Result<()>
pub async fn set_endpoint_flags(&self, id: u8, flags: MptcpFlags) -> Result<()>
Sourcepub async fn create_subflow(&self, subflow: MptcpSubflowBuilder) -> Result<()>
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?;Sourcepub async fn destroy_subflow(&self, subflow: MptcpSubflowBuilder) -> Result<()>
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?;Sourcepub async fn announce_addr(&self, announce: MptcpAnnounceBuilder) -> Result<()>
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§impl Connection<Wireguard>
impl Connection<Wireguard>
Sourcepub async fn get_device(&self, ifname: &str) -> Result<WgDevice>
pub async fn get_device(&self, ifname: &str) -> Result<WgDevice>
Get device information.
Returns the current configuration and status of the WireGuard interface.
Sourcepub async fn set_device(
&self,
ifname: &str,
configure: impl FnOnce(WgDeviceBuilder) -> WgDeviceBuilder,
) -> Result<()>
pub async fn set_device( &self, ifname: &str, configure: impl FnOnce(WgDeviceBuilder) -> WgDeviceBuilder, ) -> Result<()>
Sourcepub async fn set_peer(
&self,
ifname: &str,
public_key: [u8; 32],
configure: impl FnOnce(WgPeerBuilder) -> WgPeerBuilder,
) -> Result<()>
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§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn add_link<L: LinkConfig>(&self, config: L) -> Result<()>
pub async fn add_link<L: LinkConfig>(&self, config: L) -> Result<()>
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?;Sourcepub async fn set_link_master_by_index(
&self,
ifindex: u32,
master_index: u32,
) -> Result<()>
pub async fn set_link_master_by_index( &self, ifindex: u32, master_index: u32, ) -> Result<()>
Set the master device by interface indices.
Sourcepub async fn set_link_nomaster(&self, ifname: &str) -> Result<()>
pub async fn set_link_nomaster(&self, ifname: &str) -> Result<()>
Sourcepub async fn set_link_nomaster_by_index(&self, ifindex: u32) -> Result<()>
pub async fn set_link_nomaster_by_index(&self, ifindex: u32) -> Result<()>
Remove an interface from its master by index.
Sourcepub async fn set_link_name_by_index(
&self,
ifindex: u32,
new_name: &str,
) -> Result<()>
pub async fn set_link_name_by_index( &self, ifindex: u32, new_name: &str, ) -> Result<()>
Rename a network interface by index.
Sourcepub async fn set_link_address_by_index(
&self,
ifindex: u32,
address: [u8; 6],
) -> Result<()>
pub async fn set_link_address_by_index( &self, ifindex: u32, address: [u8; 6], ) -> Result<()>
Set the MAC address by interface index.
Sourcepub async fn set_link_netns_pid_by_index(
&self,
ifindex: u32,
pid: u32,
) -> Result<()>
pub async fn set_link_netns_pid_by_index( &self, ifindex: u32, pid: u32, ) -> Result<()>
Move a network interface to a namespace by PID (by index).
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn get_mpls_routes(&self) -> Result<Vec<MplsRoute>>
pub async fn get_mpls_routes(&self) -> Result<Vec<MplsRoute>>
Sourcepub async fn add_mpls_route(&self, builder: MplsRouteBuilder) -> Result<()>
pub async fn add_mpls_route(&self, builder: MplsRouteBuilder) -> Result<()>
Sourcepub async fn replace_mpls_route(&self, builder: MplsRouteBuilder) -> Result<()>
pub async fn replace_mpls_route(&self, builder: MplsRouteBuilder) -> Result<()>
Replace an MPLS route (add or update).
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn add_neighbor<N: NeighborConfig>(&self, config: N) -> Result<()>
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?;Sourcepub async fn del_neighbor<N: NeighborConfig>(&self, config: N) -> Result<()>
pub async fn del_neighbor<N: NeighborConfig>(&self, config: N) -> Result<()>
Delete a neighbor entry using a config.
Sourcepub async fn del_neighbor_v6(
&self,
ifname: &str,
destination: Ipv6Addr,
) -> Result<()>
pub async fn del_neighbor_v6( &self, ifname: &str, destination: Ipv6Addr, ) -> Result<()>
Delete an IPv6 neighbor entry.
Sourcepub async fn replace_neighbor<N: NeighborConfig>(&self, config: N) -> Result<()>
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.
Sourcepub async fn flush_neighbors(&self, ifname: &str) -> Result<()>
pub async fn flush_neighbors(&self, ifname: &str) -> Result<()>
Source§impl Connection<Netfilter>
impl Connection<Netfilter>
Sourcepub async fn get_conntrack(&self) -> Result<Vec<ConntrackEntry>>
pub async fn get_conntrack(&self) -> Result<Vec<ConntrackEntry>>
Sourcepub async fn get_conntrack_v6(&self) -> Result<Vec<ConntrackEntry>>
pub async fn get_conntrack_v6(&self) -> Result<Vec<ConntrackEntry>>
Get connection tracking entries for IPv6.
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn get_nexthops(&self) -> Result<Vec<Nexthop>>
pub async fn get_nexthops(&self) -> Result<Vec<Nexthop>>
Sourcepub async fn get_nexthop(&self, id: u32) -> Result<Option<Nexthop>>
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.
Sourcepub async fn add_nexthop(&self, builder: NexthopBuilder) -> Result<()>
pub async fn add_nexthop(&self, builder: NexthopBuilder) -> Result<()>
Sourcepub async fn replace_nexthop(&self, builder: NexthopBuilder) -> Result<()>
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.
Sourcepub async fn del_nexthop(&self, id: u32) -> Result<()>
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.
Sourcepub async fn add_nexthop_group(
&self,
builder: NexthopGroupBuilder,
) -> Result<()>
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?;Sourcepub async fn replace_nexthop_group(
&self,
builder: NexthopGroupBuilder,
) -> Result<()>
pub async fn replace_nexthop_group( &self, builder: NexthopGroupBuilder, ) -> Result<()>
Replace a nexthop group (add or update).
Sourcepub async fn del_nexthop_group(&self, id: u32) -> Result<()>
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.
Sourcepub async fn get_nexthop_groups(&self) -> Result<Vec<Nexthop>>
pub async fn get_nexthop_groups(&self) -> Result<Vec<Nexthop>>
Get only nexthop groups (not individual nexthops).
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn add_route<R: RouteConfig>(&self, config: R) -> Result<()>
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?;Sourcepub async fn del_route<R: RouteConfig>(&self, config: R) -> Result<()>
pub async fn del_route<R: RouteConfig>(&self, config: R) -> Result<()>
Delete a route using a config.
Sourcepub async fn del_route_v6(
&self,
destination: &str,
prefix_len: u8,
) -> Result<()>
pub async fn del_route_v6( &self, destination: &str, prefix_len: u8, ) -> Result<()>
Delete an IPv6 route by destination.
Sourcepub async fn replace_route<R: RouteConfig>(&self, config: R) -> Result<()>
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>
impl Connection<SELinux>
Sourcepub async fn recv(&self) -> Result<SELinuxEvent>
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);
}
}
}Sourcepub fn is_available() -> bool
pub fn is_available() -> bool
Check if SELinux is available on this system.
This checks if the SELinux filesystem is mounted.
Sourcepub fn get_enforce() -> Result<bool>
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>
impl Connection<SockDiag>
Sourcepub async fn query(&self, filter: &SocketFilter) -> Result<Vec<SocketInfo>>
pub async fn query(&self, filter: &SocketFilter) -> Result<Vec<SocketInfo>>
Sourcepub async fn query_tcp(&self) -> Result<Vec<InetSocket>>
pub async fn query_tcp(&self) -> Result<Vec<InetSocket>>
Sourcepub async fn query_udp(&self) -> Result<Vec<InetSocket>>
pub async fn query_udp(&self) -> Result<Vec<InetSocket>>
Query UDP sockets with default filter.
Sourcepub async fn query_unix_sockets(&self) -> Result<Vec<UnixSocket>>
pub async fn query_unix_sockets(&self) -> Result<Vec<UnixSocket>>
Query Unix sockets with default filter.
Source§impl Connection<Route>
impl Connection<Route>
Sourcepub async fn get_srv6_local_routes(&self) -> Result<Vec<Srv6LocalRoute>>
pub async fn get_srv6_local_routes(&self) -> Result<Vec<Srv6LocalRoute>>
Sourcepub async fn add_srv6_local(&self, builder: Srv6LocalBuilder) -> Result<()>
pub async fn add_srv6_local(&self, builder: Srv6LocalBuilder) -> Result<()>
Sourcepub async fn replace_srv6_local(&self, builder: Srv6LocalBuilder) -> Result<()>
pub async fn replace_srv6_local(&self, builder: Srv6LocalBuilder) -> Result<()>
Replace an SRv6 local route (add or update).
Source§impl<P: EventSource> Connection<P>
impl<P: EventSource> Connection<P>
Sourcepub fn events(&self) -> EventSubscription<'_, P>
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);Sourcepub fn into_events(self) -> OwnedEventStream<P>
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>
impl Connection<Route>
Sourcepub async fn add_qdisc_full(
&self,
dev: &str,
parent: &str,
handle: Option<&str>,
config: impl QdiscConfig,
) -> Result<()>
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.
Sourcepub async fn add_qdisc_by_index(
&self,
ifindex: u32,
config: impl QdiscConfig,
) -> Result<()>
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?;Sourcepub async fn add_qdisc_by_index_full(
&self,
ifindex: u32,
parent: &str,
handle: Option<&str>,
config: impl QdiscConfig,
) -> Result<()>
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.
Sourcepub async fn del_qdisc_full(
&self,
dev: &str,
parent: &str,
handle: Option<&str>,
) -> Result<()>
pub async fn del_qdisc_full( &self, dev: &str, parent: &str, handle: Option<&str>, ) -> Result<()>
Delete a qdisc with explicit handle.
Sourcepub async fn del_qdisc_by_index(&self, ifindex: u32, parent: &str) -> Result<()>
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().
Sourcepub async fn del_qdisc_by_index_full(
&self,
ifindex: u32,
parent: &str,
handle: Option<&str>,
) -> Result<()>
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.
Sourcepub async fn replace_qdisc(
&self,
dev: &str,
config: impl QdiscConfig,
) -> Result<()>
pub async fn replace_qdisc( &self, dev: &str, config: impl QdiscConfig, ) -> Result<()>
Sourcepub async fn replace_qdisc_full(
&self,
dev: &str,
parent: &str,
handle: Option<&str>,
config: impl QdiscConfig,
) -> Result<()>
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.
Sourcepub async fn replace_qdisc_by_index(
&self,
ifindex: u32,
config: impl QdiscConfig,
) -> Result<()>
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().
Sourcepub async fn replace_qdisc_by_index_full(
&self,
ifindex: u32,
parent: &str,
handle: Option<&str>,
config: impl QdiscConfig,
) -> Result<()>
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.
Sourcepub async fn change_qdisc(
&self,
dev: &str,
parent: &str,
config: impl QdiscConfig,
) -> Result<()>
pub async fn change_qdisc( &self, dev: &str, parent: &str, config: impl QdiscConfig, ) -> Result<()>
Sourcepub async fn change_qdisc_full(
&self,
dev: &str,
parent: &str,
handle: Option<&str>,
config: impl QdiscConfig,
) -> Result<()>
pub async fn change_qdisc_full( &self, dev: &str, parent: &str, handle: Option<&str>, config: impl QdiscConfig, ) -> Result<()>
Change a qdisc with explicit handle.
Sourcepub async fn change_qdisc_by_index(
&self,
ifindex: u32,
parent: &str,
config: impl QdiscConfig,
) -> Result<()>
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().
Sourcepub async fn change_qdisc_by_index_full(
&self,
ifindex: u32,
parent: &str,
handle: Option<&str>,
config: impl QdiscConfig,
) -> Result<()>
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.
Sourcepub async fn apply_netem(&self, dev: &str, config: NetemConfig) -> Result<()>
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?;Sourcepub async fn apply_netem_by_index(
&self,
ifindex: u32,
config: NetemConfig,
) -> Result<()>
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.
Sourcepub async fn remove_netem(&self, dev: &str) -> Result<()>
pub async fn remove_netem(&self, dev: &str) -> Result<()>
Sourcepub async fn remove_netem_by_index(&self, ifindex: u32) -> Result<()>
pub async fn remove_netem_by_index(&self, ifindex: u32) -> Result<()>
Remove netem configuration by interface index.
Sourcepub async fn add_class(
&self,
dev: &str,
parent: &str,
classid: &str,
kind: &str,
params: &[&str],
) -> Result<()>
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?;Sourcepub async fn add_class_by_index(
&self,
ifindex: u32,
parent: &str,
classid: &str,
kind: &str,
params: &[&str],
) -> Result<()>
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().
Sourcepub async fn del_class_by_index(
&self,
ifindex: u32,
parent: &str,
classid: &str,
) -> Result<()>
pub async fn del_class_by_index( &self, ifindex: u32, parent: &str, classid: &str, ) -> Result<()>
Delete a TC class by interface index.
Sourcepub async fn change_class(
&self,
dev: &str,
parent: &str,
classid: &str,
kind: &str,
params: &[&str],
) -> Result<()>
pub async fn change_class( &self, dev: &str, parent: &str, classid: &str, kind: &str, params: &[&str], ) -> Result<()>
Sourcepub async fn change_class_by_index(
&self,
ifindex: u32,
parent: &str,
classid: &str,
kind: &str,
params: &[&str],
) -> Result<()>
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.
Sourcepub async fn replace_class(
&self,
dev: &str,
parent: &str,
classid: &str,
kind: &str,
params: &[&str],
) -> Result<()>
pub async fn replace_class( &self, dev: &str, parent: &str, classid: &str, kind: &str, params: &[&str], ) -> Result<()>
Sourcepub async fn replace_class_by_index(
&self,
ifindex: u32,
parent: &str,
classid: &str,
kind: &str,
params: &[&str],
) -> Result<()>
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.
Sourcepub async fn add_class_config<C: ClassConfig>(
&self,
dev: &str,
parent: &str,
classid: &str,
config: C,
) -> Result<()>
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?;Sourcepub async fn add_class_config_by_index<C: ClassConfig>(
&self,
ifindex: u32,
parent: &str,
classid: &str,
config: C,
) -> Result<()>
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().
Sourcepub async fn change_class_config<C: ClassConfig>(
&self,
dev: &str,
parent: &str,
classid: &str,
config: C,
) -> Result<()>
pub async fn change_class_config<C: ClassConfig>( &self, dev: &str, parent: &str, classid: &str, config: C, ) -> Result<()>
Sourcepub async fn change_class_config_by_index<C: ClassConfig>(
&self,
ifindex: u32,
parent: &str,
classid: &str,
config: C,
) -> Result<()>
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.
Sourcepub async fn replace_class_config<C: ClassConfig>(
&self,
dev: &str,
parent: &str,
classid: &str,
config: C,
) -> Result<()>
pub async fn replace_class_config<C: ClassConfig>( &self, dev: &str, parent: &str, classid: &str, config: C, ) -> Result<()>
Sourcepub async fn replace_class_config_by_index<C: ClassConfig>(
&self,
ifindex: u32,
parent: &str,
classid: &str,
config: C,
) -> Result<()>
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>
impl Connection<KobjectUevent>
Sourcepub async fn recv(&self) -> Result<Uevent>
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());
}
}