1use crate::addr::is_global;
6use std::net::IpAddr;
7
8pub fn interfaces() -> Vec<IpAddr> {
14 let mut out: Vec<IpAddr> = Vec::new();
15 let Ok(addrs) = if_addrs::get_if_addrs() else {
16 return out;
17 };
18 for a in addrs {
19 let ip = a.ip();
20 if a.is_loopback() || ip.is_multicast() {
21 continue;
22 }
23 let keep = match ip {
24 IpAddr::V4(v4) => !v4.is_link_local() && !v4.is_unspecified(),
25 IpAddr::V6(v6) => is_global(IpAddr::V6(v6)),
26 };
27 if keep && !out.contains(&ip) {
28 out.push(ip);
29 }
30 }
31 out
32}
33
34#[cfg(test)]
35mod tests {
36 #[test]
37 fn no_loopback_or_link_local() {
38 for ip in super::interfaces() {
39 assert!(!ip.is_loopback());
40 if let std::net::IpAddr::V6(v6) = ip {
41 assert_ne!(v6.segments()[0] & 0xffc0, 0xfe80);
42 }
43 }
44 }
45}