1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use futures::{Future, Stream};

use rtnetlink::constants::{NLM_F_DUMP, NLM_F_REQUEST};
use rtnetlink::{LinkMessage, NetlinkFlags, NetlinkMessage, RtnlMessage};

use super::Link;
use connection::ConnectionHandle;
use errors::NetlinkIpError;

use Stream2Vec;

lazy_static! {
    // Flags for `ip link get`
    static ref GET_FLAGS: NetlinkFlags = NetlinkFlags::from(NLM_F_REQUEST | NLM_F_DUMP);
}

pub struct LinkGetRequest {
    handle: ConnectionHandle,
    message: LinkMessage,
}

impl LinkGetRequest {
    pub(crate) fn new(handle: ConnectionHandle) -> Self {
        let message = LinkMessage::new();
        LinkGetRequest { handle, message }
    }

    /// Execute the request
    pub fn execute(self) -> impl Future<Item = Vec<Link>, Error = NetlinkIpError> {
        let LinkGetRequest {
            mut handle,
            message,
        } = self;
        let mut req = NetlinkMessage::from(RtnlMessage::GetLink(message));
        req.header_mut().set_flags(*GET_FLAGS);
        Stream2Vec::new(handle.request(req).map(move |msg| {
            if !msg.is_new_link() {
                return Err(NetlinkIpError::UnexpectedMessage(msg));
            }

            if let (_, RtnlMessage::NewLink(link_message)) = msg.into_parts() {
                Ok(Link::from_link_message(link_message)?)
            } else {
                // We checked that msg.is_new_link() above, so the should not be reachable.
                unreachable!();
            }
        }))
    }

    /// Return a mutable reference to the request
    pub fn message_mut(&mut self) -> &mut LinkMessage {
        &mut self.message
    }
}