rtnetlink/rule/
get.rs

1// SPDX-License-Identifier: MIT
2
3use futures_util::{
4    future::{self, Either},
5    stream::{Stream, StreamExt},
6    FutureExt,
7};
8use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST};
9use netlink_packet_route::{
10    route::RouteHeader,
11    rule::{RuleAction, RuleMessage},
12    RouteNetlinkMessage,
13};
14
15use crate::{try_rtnl, Error, Handle, IpVersion};
16
17#[derive(Debug, Clone)]
18pub struct RuleGetRequest {
19    handle: Handle,
20    message: RuleMessage,
21}
22
23impl RuleGetRequest {
24    pub(crate) fn new(handle: Handle, ip_version: IpVersion) -> Self {
25        let mut message = RuleMessage::default();
26        message.header.family = ip_version.family();
27
28        message.header.dst_len = 0;
29        message.header.src_len = 0;
30        message.header.tos = 0;
31        message.header.action = RuleAction::Unspec;
32        message.header.table = RouteHeader::RT_TABLE_UNSPEC;
33
34        RuleGetRequest { handle, message }
35    }
36
37    pub fn message_mut(&mut self) -> &mut RuleMessage {
38        &mut self.message
39    }
40
41    pub fn execute(self) -> impl Stream<Item = Result<RuleMessage, Error>> {
42        let RuleGetRequest {
43            mut handle,
44            message,
45        } = self;
46
47        let mut req =
48            NetlinkMessage::from(RouteNetlinkMessage::GetRule(message));
49        req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
50
51        match handle.request(req) {
52            Ok(response) => Either::Left(response.map(move |msg| {
53                Ok(try_rtnl!(msg, RouteNetlinkMessage::NewRule))
54            })),
55            Err(e) => Either::Right(
56                future::err::<RuleMessage, Error>(e).into_stream(),
57            ),
58        }
59    }
60}