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