rtnetlink/route/
add.rs

1// SPDX-License-Identifier: MIT
2
3use std::{marker::PhantomData, net::IpAddr};
4
5use futures_util::stream::StreamExt;
6use netlink_packet_core::{
7    NetlinkMessage, NLM_F_ACK, NLM_F_CREATE, NLM_F_EXCL, NLM_F_REPLACE,
8    NLM_F_REQUEST,
9};
10use netlink_packet_route::{route::RouteMessage, RouteNetlinkMessage};
11
12use crate::{try_nl, Error, Handle};
13
14/// A request to create a new route. This is equivalent to the `ip route add`
15/// commands.
16#[derive(Debug, Clone)]
17pub struct RouteAddRequest<T = IpAddr> {
18    handle: Handle,
19    message: RouteMessage,
20    replace: bool,
21    _phantom: PhantomData<T>,
22}
23
24impl<T> RouteAddRequest<T> {
25    pub(crate) fn new(handle: Handle, message: RouteMessage) -> Self {
26        RouteAddRequest {
27            handle,
28            message,
29            replace: false,
30            _phantom: Default::default(),
31        }
32    }
33
34    pub fn message_mut(&mut self) -> &mut RouteMessage {
35        &mut self.message
36    }
37
38    /// Replace existing matching route.
39    pub fn replace(self) -> Self {
40        Self {
41            replace: true,
42            ..self
43        }
44    }
45
46    /// Execute the request.
47    pub async fn execute(self) -> Result<(), Error> {
48        let RouteAddRequest {
49            mut handle,
50            message,
51            replace,
52            ..
53        } = self;
54        let mut req =
55            NetlinkMessage::from(RouteNetlinkMessage::NewRoute(message));
56        let replace = if replace { NLM_F_REPLACE } else { NLM_F_EXCL };
57        req.header.flags = NLM_F_REQUEST | NLM_F_ACK | replace | NLM_F_CREATE;
58
59        let mut response = handle.request(req)?;
60        while let Some(message) = response.next().await {
61            try_nl!(message);
62        }
63        Ok(())
64    }
65}