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 }
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 }
129 }
130
131 if let Some(if_index) = self.if_index
132 && interfaces_by_index.is_empty()
133 {
134 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}