1use futures::{
4 future::{self, Either},
5 stream::{StreamExt, TryStream},
6 FutureExt,
7};
8
9use netlink_packet_route::{constants::*, NetlinkMessage, RouteMessage, RtnlMessage};
10
11use crate::{try_rtnl, Error, Handle};
12
13pub struct RouteGetRequest {
14 handle: Handle,
15 message: RouteMessage,
16}
17
18#[derive(Debug, Clone, Eq, PartialEq, PartialOrd)]
20pub enum IpVersion {
21 V4,
23 V6,
25}
26
27impl IpVersion {
28 pub(crate) fn family(self) -> u8 {
29 match self {
30 IpVersion::V4 => AF_INET as u8,
31 IpVersion::V6 => AF_INET6 as u8,
32 }
33 }
34}
35
36impl RouteGetRequest {
37 pub(crate) fn new(handle: Handle, ip_version: IpVersion) -> Self {
38 let mut message = RouteMessage::default();
39 message.header.address_family = ip_version.family();
40
41 message.header.destination_prefix_length = 0;
49 message.header.source_prefix_length = 0;
50 message.header.scope = RT_SCOPE_UNIVERSE;
51 message.header.kind = RTN_UNSPEC;
52
53 message.header.table = RT_TABLE_UNSPEC;
55 message.header.protocol = RTPROT_UNSPEC;
56
57 RouteGetRequest { handle, message }
58 }
59
60 pub fn message_mut(&mut self) -> &mut RouteMessage {
61 &mut self.message
62 }
63
64 pub fn execute(self) -> impl TryStream<Ok = RouteMessage, Error = Error> {
65 let RouteGetRequest {
66 mut handle,
67 message,
68 } = self;
69
70 let mut req = NetlinkMessage::from(RtnlMessage::GetRoute(message));
71 req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
72
73 match handle.request(req) {
74 Ok(response) => {
75 Either::Left(response.map(move |msg| Ok(try_rtnl!(msg, RtnlMessage::NewRoute))))
76 }
77 Err(e) => Either::Right(future::err::<RouteMessage, Error>(e).into_stream()),
78 }
79 }
80}