Skip to main content

ip_nlroute/addr/
get.rs

1use crate::NetlinkRouteHandle;
2#[allow(unused)]
3use crate::addr::{AddrGetInterface, AddrGetInterfaceAddressV4, AddrGetResponse, AddressFlags};
4use crate::error::Error;
5#[cfg(all(target_os = "linux", feature = "netlink"))]
6use neli::{
7    consts::{
8        nl::NlmF,
9        rtnl::{Ifa, RtAddrFamily, RtScope, Rtm},
10    },
11    nl::{NlPayload, Nlmsghdr},
12    router::synchronous::NlRouterReceiverHandle,
13    rtnl::{Ifaddrmsg, IfaddrmsgBuilder},
14};
15use std::collections::BTreeMap;
16
17pub struct AddrGetRequest {
18    if_index: Option<u32>,
19}
20
21impl AddrGetRequest {
22    #[cfg(not(all(target_os = "linux", feature = "netlink")))]
23    pub fn for_ifname(_ifname: &str) -> Result<Self, Error> {
24        Err(Error::NotImplemented)
25    }
26    #[cfg(all(target_os = "linux", feature = "netlink"))]
27    pub fn for_ifname(ifname: &str) -> Result<Self, Error> {
28        use nix::net::if_::if_nametoindex;
29        let if_index = if_nametoindex(ifname).map_err(|e| Error::InterfaceLookup {
30            ifname: ifname.to_owned(),
31            source: e,
32        })?;
33        Ok(AddrGetRequest {
34            if_index: Some(if_index),
35        })
36    }
37
38    pub fn all() -> Self {
39        AddrGetRequest { if_index: None }
40    }
41
42    #[cfg(not(all(target_os = "linux", feature = "netlink")))]
43    pub fn send(&self, _h: &mut NetlinkRouteHandle) -> Result<AddrGetResponse, Error> {
44        Err(Error::NotImplemented)
45    }
46    #[cfg(all(target_os = "linux", feature = "netlink"))]
47    pub fn send(&self, h: &mut NetlinkRouteHandle) -> Result<AddrGetResponse, Error> {
48        use crate::util::mappers::ip::{rtattr_to_ipv4, rtattr_to_string};
49        use nix::net::if_::if_indextoname;
50
51        let ifaddrmsg = IfaddrmsgBuilder::default()
52            .ifa_family(RtAddrFamily::Inet)
53            .ifa_prefixlen(0)
54            .ifa_scope(RtScope::Universe)
55            .ifa_index(self.if_index.unwrap_or(0))
56            .build()?;
57        let recv: NlRouterReceiverHandle<Rtm, Ifaddrmsg> = h
58            .rtnl
59            .send(Rtm::Getaddr, NlmF::DUMP, NlPayload::Payload(ifaddrmsg))
60            .map_err(|e| Error::Send(Box::new(e)))?;
61
62        let mut interfaces_by_index = BTreeMap::new();
63
64        for response in recv {
65            let header: Nlmsghdr<Rtm, Ifaddrmsg> =
66                response.map_err(|e| Error::Receive(Box::new(e)))?;
67            if let NlPayload::Payload(p) = header.nl_payload() {
68                if header.nl_type() != &Rtm::Newaddr {
69                    return Err(Error::UnexpectedNlType {
70                        expected: format!("{:?}", Rtm::Newaddr),
71                        actual: format!("{:?}", header.nl_type()),
72                    });
73                }
74
75                let if_index: u32 = *p.ifa_index();
76
77                let mut interface =
78                    interfaces_by_index
79                        .remove(&if_index)
80                        .unwrap_or_else(|| AddrGetInterface {
81                            if_name: if_indextoname(if_index)
82                                .ok()
83                                .and_then(|n| n.into_string().ok()),
84                            addresses: vec![],
85                        });
86
87                let family = *p.ifa_family();
88                let if_name = if_indextoname(if_index)
89                    .ok()
90                    .and_then(|n| n.into_string().ok());
91                let prefix_len: u8 = *p.ifa_prefixlen();
92
93                println!(
94                    "family: {:?} idx={if_index} if_name={:?} scope={:?} prefix={prefix_len}",
95                    family,
96                    if_name,
97                    p.ifa_scope()
98                );
99
100                let mut local = None;
101                let mut address = None;
102                let mut broadcast = None;
103                let mut label = None;
104                let flags = AddressFlags::from(*p.ifa_flags());
105                for rtattr in p.rtattrs().iter() {
106                    match *rtattr.rta_type() {
107                        Ifa::Local => local = Some(rtattr_to_ipv4(rtattr)?),
108                        Ifa::Address => address = Some(rtattr_to_ipv4(rtattr)?),
109                        Ifa::Broadcast => broadcast = Some(rtattr_to_ipv4(rtattr)?),
110                        Ifa::Label => label = Some(rtattr_to_string(rtattr)?),
111                        _other => {
112                            //    println!("{:?}:{:?}", _other, rtattr.payload().as_ref());
113                        }
114                    }
115                }
116
117                interface.addresses.push(AddrGetInterfaceAddressV4 {
118                    prefix_len,
119                    flags,
120                    local,
121                    address,
122                    broadcast,
123                    label,
124                });
125
126                interfaces_by_index.insert(if_index, interface);
127                //println!("---\n");
128            }
129        }
130
131        if let Some(if_index) = self.if_index
132            && interfaces_by_index.is_empty()
133        {
134            // if the user requested a specific interface but it doesn't have any addresses,
135            // it won't return any payloads above. Crate an entry for it in the map anyway so that
136            // the user can use .get_only()
137            interfaces_by_index.insert(
138                if_index,
139                AddrGetInterface {
140                    if_name: if_indextoname(if_index)
141                        .map_err(|e| Error::IfIndexLookup {
142                            ifindex: if_index,
143                            source: e,
144                        })?
145                        .into_string()
146                        .ok(),
147                    addresses: vec![],
148                },
149            );
150        }
151
152        Ok(AddrGetResponse {
153            interfaces: interfaces_by_index,
154        })
155    }
156}