Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions src/addrlabel/add.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: MIT

use std::net::IpAddr;

use futures_util::stream::StreamExt;
use netlink_packet_core::{
NetlinkMessage, NLM_F_ACK, NLM_F_CREATE, NLM_F_EXCL, NLM_F_REQUEST,
};
use netlink_packet_route::{
addrlabel::{AddrLabelAttribute, AddrLabelMessage},
AddressFamily, RouteNetlinkMessage,
};

use crate::{try_nl, Error, Handle};

/// A request to create a new address label. This is equivalent to the
/// `ip addrlabel add` command.
#[derive(Debug, Clone)]
pub struct AddrLabelAddRequest {
handle: Handle,
message: AddrLabelMessage,
}

impl AddrLabelAddRequest {
pub(crate) fn new(handle: Handle) -> Self {
let mut message = AddrLabelMessage::default();
// Kernel only registers `RTM_NEWADDRLABEL` handler for the IPv6
// address family, hence default to IPv6 like iproute2 does.
message.header.family = AddressFamily::Inet6;
AddrLabelAddRequest { handle, message }
}

/// Sets the address family of the address label.
pub fn family(mut self, family: AddressFamily) -> Self {
self.message.header.family = family;
self
}

/// Sets the address of the address label.
pub fn address(mut self, address: IpAddr) -> Self {
self.message
.attributes
.push(AddrLabelAttribute::Address(address));
self
}

/// Sets the prefix length of the address label.
pub fn prefix_len(mut self, prefix_len: u8) -> Self {
self.message.header.prefix_len = prefix_len;
self
}

/// Sets the interface index of the address label.
pub fn index(mut self, index: u32) -> Self {
self.message.header.index = index;
self
}

/// Sets the label of the address label.
pub fn label(mut self, label: u32) -> Self {
self.message
.attributes
.push(AddrLabelAttribute::Label(label));
self
}

/// Execute the request.
pub async fn execute(self) -> Result<(), Error> {
let AddrLabelAddRequest {
mut handle,
message,
} = self;
let mut req =
NetlinkMessage::from(RouteNetlinkMessage::NewAddrLabel(message));
req.header.flags =
NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;

let mut response = handle.request(req)?;
while let Some(message) = response.next().await {
try_nl!(message);
}

Ok(())
}

pub fn message_mut(&mut self) -> &mut AddrLabelMessage {
&mut self.message
}
}
86 changes: 86 additions & 0 deletions src/addrlabel/del.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: MIT

use std::net::IpAddr;

use futures_util::stream::StreamExt;
use netlink_packet_core::{NetlinkMessage, NLM_F_ACK, NLM_F_REQUEST};
use netlink_packet_route::{
addrlabel::{AddrLabelAttribute, AddrLabelMessage},
AddressFamily, RouteNetlinkMessage,
};

use crate::{try_nl, Error, Handle};

/// A request to delete an existing address label. This is equivalent to the
/// `ip addrlabel del` command.
#[derive(Debug, Clone)]
pub struct AddrLabelDelRequest {
handle: Handle,
message: AddrLabelMessage,
}

impl AddrLabelDelRequest {
pub(crate) fn new(handle: Handle) -> Self {
let mut message = AddrLabelMessage::default();
// Kernel only registers `RTM_DELADDRLABEL` handler for the IPv6
// address family, hence default to IPv6 like iproute2 does.
message.header.family = AddressFamily::Inet6;
AddrLabelDelRequest { handle, message }
}

/// Sets the address family of the address label.
pub fn family(mut self, family: AddressFamily) -> Self {
self.message.header.family = family;
self
}

/// Sets the address of the address label.
pub fn address(mut self, address: IpAddr) -> Self {
self.message
.attributes
.push(AddrLabelAttribute::Address(address));
self
}

/// Sets the prefix length of the address label.
pub fn prefix_len(mut self, prefix_len: u8) -> Self {
self.message.header.prefix_len = prefix_len;
self
}

/// Sets the interface index of the address label.
pub fn index(mut self, index: u32) -> Self {
self.message.header.index = index;
self
}

/// Sets the label of the address label.
pub fn label(mut self, label: u32) -> Self {
self.message
.attributes
.push(AddrLabelAttribute::Label(label));
self
}

/// Execute the request.
pub async fn execute(self) -> Result<(), Error> {
let AddrLabelDelRequest {
mut handle,
message,
} = self;
let mut req =
NetlinkMessage::from(RouteNetlinkMessage::DelAddrLabel(message));
req.header.flags = NLM_F_REQUEST | NLM_F_ACK;

let mut response = handle.request(req)?;
while let Some(message) = response.next().await {
try_nl!(message);
}

Ok(())
}

pub fn message_mut(&mut self) -> &mut AddrLabelMessage {
&mut self.message
}
}
52 changes: 52 additions & 0 deletions src/addrlabel/get.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT

use futures_util::{
future::{self, Either},
stream::{Stream, StreamExt},
FutureExt,
};
use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST};
use netlink_packet_route::{addrlabel::AddrLabelMessage, RouteNetlinkMessage};

use crate::{try_rtnl, Error, Handle, IpVersion};

#[derive(Debug, Clone)]
pub struct AddrLabelGetRequest {
handle: Handle,
message: AddrLabelMessage,
}

impl AddrLabelGetRequest {
pub(crate) fn new(handle: Handle, ip_version: IpVersion) -> Self {
let mut message = AddrLabelMessage::default();
message.header.family = ip_version.family();
AddrLabelGetRequest { handle, message }
}

pub fn message_mut(&mut self) -> &mut AddrLabelMessage {
&mut self.message
}

/// Execute the request
pub fn execute(
self,
) -> impl Stream<Item = Result<AddrLabelMessage, Error>> {
let AddrLabelGetRequest {
mut handle,
message,
} = self;

let mut req =
NetlinkMessage::from(RouteNetlinkMessage::GetAddrLabel(message));
req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;

match handle.request(req) {
Ok(response) => Either::Left(response.map(move |msg| {
Ok(try_rtnl!(msg, RouteNetlinkMessage::NewAddrLabel))
})),
Err(e) => Either::Right(
future::err::<AddrLabelMessage, Error>(e).into_stream(),
),
}
}
}
30 changes: 30 additions & 0 deletions src/addrlabel/handle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT

use crate::{
AddrLabelAddRequest, AddrLabelDelRequest, AddrLabelGetRequest, Handle,
IpVersion,
};

#[derive(Debug, Clone)]
pub struct AddrLabelHandle(Handle);

impl AddrLabelHandle {
pub fn new(handle: Handle) -> Self {
AddrLabelHandle(handle)
}

/// List address labels (equivalent to `ip addrlabel show`)
pub fn get(&self, ip_version: IpVersion) -> AddrLabelGetRequest {
AddrLabelGetRequest::new(self.0.clone(), ip_version)
}

/// Add an address label (equivalent to `ip addrlabel add`)
pub fn add(&self) -> AddrLabelAddRequest {
AddrLabelAddRequest::new(self.0.clone())
}

/// Delete an address label (equivalent to `ip addrlabel del`)
pub fn del(&self) -> AddrLabelDelRequest {
AddrLabelDelRequest::new(self.0.clone())
}
}
11 changes: 11 additions & 0 deletions src/addrlabel/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT

mod add;
mod del;
mod get;
mod handle;

pub use self::{
add::AddrLabelAddRequest, del::AddrLabelDelRequest,
get::AddrLabelGetRequest, handle::AddrLabelHandle,
};
9 changes: 8 additions & 1 deletion src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use netlink_packet_route::RouteNetlinkMessage;
use netlink_proto::{sys::SocketAddr, ConnectionHandle};

use crate::{
AddressHandle, Error, LinkHandle, NeighbourHandle, RouteHandle, RuleHandle,
AddrLabelHandle, AddressHandle, Error, LinkHandle, NeighbourHandle,
RouteHandle, RuleHandle,
};
#[cfg(not(target_os = "freebsd"))]
use crate::{
Expand Down Expand Up @@ -53,6 +54,12 @@ impl Handle {
AddressHandle::new(self.clone())
}

/// Create a new handle, specifically for address label requests
/// (equivalent to `ip addrlabel` commands)
pub fn addrlabel(&self) -> AddrLabelHandle {
AddrLabelHandle::new(self.clone())
}

/// Create a new handle, specifically for routing table requests (equivalent
/// to `ip route` commands)
pub fn route(&self) -> RouteHandle {
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub use netlink_proto as proto;
pub use netlink_sys as sys;

mod addr;
mod addrlabel;
mod connection;
pub mod constants;
mod errors;
Expand Down Expand Up @@ -44,6 +45,10 @@ pub use crate::{
AddressAddRequest, AddressDelRequest, AddressGetRequest, AddressHandle,
AddressMessageBuilder,
},
addrlabel::{
AddrLabelAddRequest, AddrLabelDelRequest, AddrLabelGetRequest,
AddrLabelHandle,
},
connection::{
from_socket, new_connection_with_socket,
new_multicast_connection_with_socket,
Expand Down
Loading