rtnetlink/link/
get.rs

1// SPDX-License-Identifier: MIT
2
3use futures::{
4    future::{self, Either},
5    stream::{StreamExt, TryStream},
6    FutureExt,
7};
8
9use crate::{
10    packet::{constants::*, nlas::link::Nla, LinkMessage, NetlinkMessage, RtnlMessage},
11    try_rtnl,
12    Error,
13    Handle,
14};
15
16pub struct LinkGetRequest {
17    handle: Handle,
18    message: LinkMessage,
19    // There are two ways to retrieve links: we can either dump them
20    // all and filter the result, or if we already know the index or
21    // the name of the link we're looking for, we can just retrieve
22    // that one. If `dump` is `true`, all the links are fetched.
23    // Otherwise, only the link that match the given index or name
24    // is fetched.
25    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    /// Setting filter mask(e.g. RTEXT_FILTER_BRVLAN and etc)
38    pub fn set_filter_mask(mut self, family: u8, filter_mask: u32) -> Self {
39        self.message.header.interface_family = family;
40        self.message.nlas.push(Nla::ExtMask(filter_mask));
41        self
42    }
43
44    /// Execute the request
45    pub fn execute(self) -> impl TryStream<Ok = LinkMessage, Error = Error> {
46        let LinkGetRequest {
47            mut handle,
48            message,
49            dump,
50        } = self;
51
52        let mut req = NetlinkMessage::from(RtnlMessage::GetLink(message));
53
54        if dump {
55            req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
56        } else {
57            req.header.flags = NLM_F_REQUEST;
58        }
59
60        match handle.request(req) {
61            Ok(response) => {
62                Either::Left(response.map(move |msg| Ok(try_rtnl!(msg, RtnlMessage::NewLink))))
63            }
64            Err(e) => Either::Right(future::err::<LinkMessage, Error>(e).into_stream()),
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}