1use 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}