rtnetlink/link/
get.rs

1// SPDX-License-Identifier: MIT
2
3use 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    // There are two ways to retrieve links: we can either dump them
17    // all and filter the result, or if we already know the index or
18    // the name of the link we're looking for, we can just retrieve
19    // that one. If `dump` is `true`, all the links are fetched.
20    // Otherwise, only the link that match the given index or name
21    // is fetched.
22    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    /// Setting filter mask(e.g. RTEXT_FILTER_BRVLAN and etc)
35    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    /// Execute the request
42    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    /// Return a mutable reference to the request
69    pub fn message_mut(&mut self) -> &mut LinkMessage {
70        &mut self.message
71    }
72
73    /// Lookup a link by index
74    pub fn match_index(mut self, index: u32) -> Self {
75        self.dump = false;
76        self.message.header.index = index;
77        self
78    }
79
80    /// Lookup a link by name
81    ///
82    /// This function requires support from your kernel (>= 2.6.33). If yours is
83    /// older, consider filtering the resulting stream of links.
84    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}