webrtc_util/ifaces/ffi/unix/
mod.rs1use crate::ifaces::{Interface, Kind, NextHop};
2
3use nix::sys::socket::{AddressFamily, SockaddrLike, SockaddrStorage};
4use std::io::Error;
5use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
6
7fn ss_to_netsa(ss: &SockaddrStorage) -> Option<SocketAddr> {
8 match ss.family() {
9 Some(AddressFamily::Inet) => ss.as_sockaddr_in().map(|sin| {
10 SocketAddr::V4(SocketAddrV4::new(
11 std::net::Ipv4Addr::from(sin.ip()),
12 sin.port(),
13 ))
14 }),
15 Some(AddressFamily::Inet6) => ss.as_sockaddr_in6().map(|sin6| {
16 SocketAddr::V6(SocketAddrV6::new(
17 sin6.ip(),
18 sin6.port(),
19 sin6.flowinfo(),
20 sin6.scope_id(),
21 ))
22 }),
23 _ => None,
24 }
25}
26
27pub fn ifaces() -> Result<Vec<Interface>, Error> {
29 let mut ret = Vec::new();
30 for ifa in nix::ifaddrs::getifaddrs()? {
31 if let Some(kind) = ifa
32 .address
33 .as_ref()
34 .and_then(SockaddrStorage::family)
35 .and_then(|af| match af {
36 AddressFamily::Inet => Some(Kind::Ipv4),
37 AddressFamily::Inet6 => Some(Kind::Ipv6),
38 #[cfg(any(
39 target_os = "android",
40 target_os = "linux",
41 target_os = "illumos",
42 target_os = "fuchsia",
43 target_os = "solaris"
44 ))]
45 AddressFamily::Packet => Some(Kind::Packet),
46 #[cfg(any(
47 target_os = "dragonfly",
48 target_os = "freebsd",
49 target_os = "ios",
50 target_os = "macos",
51 target_os = "illumos",
52 target_os = "netbsd",
53 target_os = "openbsd"
54 ))]
55 AddressFamily::Link => Some(Kind::Link),
56 _ => None,
57 })
58 {
59 let name = ifa.interface_name;
60 let dst = ifa.destination.as_ref().and_then(ss_to_netsa);
61 let broadcast = ifa.broadcast.as_ref().and_then(ss_to_netsa);
62 let hop = dst
63 .map(NextHop::Destination)
64 .or(broadcast.map(NextHop::Broadcast));
65 let addr = ifa.address.as_ref().and_then(ss_to_netsa);
66 let mask = ifa.netmask.as_ref().and_then(ss_to_netsa);
67
68 ret.push(Interface {
69 name,
70 kind,
71 addr,
72 mask,
73 hop,
74 });
75 }
76 }
77
78 Ok(ret)
79}