1use futures::{
4 future::{self, Either},
5 stream::{StreamExt, TryStream},
6 FutureExt,
7};
8use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST};
9use netlink_packet_route::{link::nlas::Nla, LinkMessage, RtnlMessage};
10
11use crate::{try_rtnl, Error, Handle};
12
13pub struct LinkGetRequest {
14 handle: Handle,
15 message: LinkMessage,
16 dump: bool,
23}
24
25impl LinkGetRequest {
26 pub(crate) fn new(handle: Handle) -> Self {
27 LinkGetRequest {
28 handle,
29 message: LinkMessage::default(),
30 dump: true,
31 }
32 }
33
34 pub fn set_filter_mask(mut self, family: u8, filter_mask: u32) -> Self {
36 self.message.header.interface_family = family;
37 self.message.nlas.push(Nla::ExtMask(filter_mask));
38 self
39 }
40
41 pub fn execute(self) -> impl TryStream<Ok = LinkMessage, Error = Error> {
43 let LinkGetRequest {
44 mut handle,
45 message,
46 dump,
47 } = self;
48
49 let mut req = NetlinkMessage::from(RtnlMessage::GetLink(message));
50
51 if dump {
52 req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
53 } else {
54 req.header.flags = NLM_F_REQUEST;
55 }
56
57 match handle.request(req) {
58 Ok(response) => Either::Left(
59 response
60 .map(move |msg| Ok(try_rtnl!(msg, RtnlMessage::NewLink))),
61 ),
62 Err(e) => Either::Right(
63 future::err::<LinkMessage, Error>(e).into_stream(),
64 ),
65 }
66 }
67
68 pub fn message_mut(&mut self) -> &mut LinkMessage {
70 &mut self.message
71 }
72
73 pub fn match_index(mut self, index: u32) -> Self {
75 self.dump = false;
76 self.message.header.index = index;
77 self
78 }
79
80 pub fn match_name(mut self, name: String) -> Self {
85 self.dump = false;
86 self.message.nlas.push(Nla::IfName(name));
87 self
88 }
89}