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 link::{LinkAttribute, LinkExtentMask, LinkMessage},
11 AddressFamily, RouteNetlinkMessage,
12};
13
14use crate::{try_rtnl, Error, Handle};
15
16pub struct LinkGetRequest {
17 handle: Handle,
18 message: LinkMessage,
19 dump: bool,
26}
27
28impl LinkGetRequest {
29 pub(crate) fn new(handle: Handle) -> Self {
30 LinkGetRequest {
31 handle,
32 message: LinkMessage::default(),
33 dump: true,
34 }
35 }
36
37 pub fn set_filter_mask(
39 mut self,
40 family: AddressFamily,
41 filter_mask: Vec<LinkExtentMask>,
42 ) -> Self {
43 self.message.header.interface_family = family;
44 self.message
45 .attributes
46 .push(LinkAttribute::ExtMask(filter_mask));
47 self
48 }
49
50 pub fn execute(self) -> impl Stream<Item = Result<LinkMessage, Error>> {
52 let LinkGetRequest {
53 mut handle,
54 message,
55 dump,
56 } = self;
57
58 let mut req =
59 NetlinkMessage::from(RouteNetlinkMessage::GetLink(message));
60
61 if dump {
62 req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
63 } else {
64 req.header.flags = NLM_F_REQUEST;
65 }
66
67 match handle.request(req) {
68 Ok(response) => Either::Left(response.map(move |msg| {
69 Ok(try_rtnl!(msg, RouteNetlinkMessage::NewLink))
70 })),
71 Err(e) => Either::Right(
72 future::err::<LinkMessage, Error>(e).into_stream(),
73 ),
74 }
75 }
76
77 pub fn message_mut(&mut self) -> &mut LinkMessage {
79 &mut self.message
80 }
81
82 pub fn match_index(mut self, index: u32) -> Self {
84 self.dump = false;
85 self.message.header.index = index;
86 self
87 }
88
89 pub fn match_name(mut self, name: String) -> Self {
94 self.dump = false;
95 self.message.attributes.push(LinkAttribute::IfName(name));
96 self
97 }
98}