network_interface/target/unix/
mod.rs1pub mod ffi;
2
3use std::collections::HashMap;
4
5use std::net::{Ipv4Addr, Ipv6Addr};
6use std::slice::from_raw_parts;
7
8use libc::{AF_INET, AF_INET6, sockaddr_in, sockaddr_in6, strlen, AF_LINK, if_nametoindex};
9
10use crate::target::ffi::lladdr;
11use crate::target::getifaddrs;
12use crate::{Error, NetworkInterface, NetworkInterfaceConfig, Result};
13use crate::utils::{ipv4_from_in_addr, ipv6_from_in6_addr, make_ipv4_netmask, make_ipv6_netmask};
14
15impl NetworkInterfaceConfig for NetworkInterface {
16 fn show() -> Result<Vec<NetworkInterface>> {
17 let mut network_interfaces: HashMap<String, NetworkInterface> = HashMap::new();
18
19 for netifa in getifaddrs()? {
20 let netifa_addr = netifa.ifa_addr;
21 let netifa_family = if netifa_addr.is_null() {
22 continue;
23 } else {
24 unsafe { (*netifa_addr).sa_family as i32 }
25 };
26
27 let mut network_interface = match netifa_family {
28 AF_LINK => {
29 let name = make_netifa_name(&netifa)?;
30 let mac = make_mac_addrs(&netifa);
31 let index = netifa_index(&netifa);
32 NetworkInterface {
33 name,
34 mac_addr: Some(mac),
35 addr: Vec::new(),
36 index,
37 }
38 }
39 AF_INET => {
40 let socket_addr = netifa_addr as *mut sockaddr_in;
41 let internet_address = unsafe { (*socket_addr).sin_addr };
42 let name = make_netifa_name(&netifa)?;
43 let index = netifa_index(&netifa);
44 let netmask = make_ipv4_netmask(&netifa);
45 let addr = ipv4_from_in_addr(&internet_address)?;
46 let broadcast = make_ipv4_broadcast_addr(&netifa)?;
47 NetworkInterface::new_afinet(name.as_str(), addr, netmask, broadcast, index)
48 }
49 AF_INET6 => {
50 let socket_addr = netifa_addr as *mut sockaddr_in6;
51 let internet_address = unsafe { (*socket_addr).sin6_addr };
52 let name = make_netifa_name(&netifa)?;
53 let index = netifa_index(&netifa);
54 let netmask = make_ipv6_netmask(&netifa);
55 let addr = ipv6_from_in6_addr(&internet_address)?;
56 let broadcast = make_ipv6_broadcast_addr(&netifa)?;
57 NetworkInterface::new_afinet6(name.as_str(), addr, netmask, broadcast, index)
58 }
59 _ => continue,
60 };
61
62 network_interfaces
63 .entry(network_interface.name.clone())
64 .and_modify(|old| old.addr.append(&mut network_interface.addr))
65 .or_insert(network_interface);
66 }
67
68 Ok(network_interfaces.into_values().collect())
69 }
70}
71
72fn make_netifa_name(netifa: &libc::ifaddrs) -> Result<String> {
74 let data = netifa.ifa_name as *mut u8;
75 let len = unsafe { strlen(data as *const _) };
76 let bytes_slice = unsafe { from_raw_parts(data, len) };
77 let string = String::from_utf8(bytes_slice.to_vec()).map_err(Error::from)?;
78
79 Ok(string)
80}
81
82fn make_ipv4_broadcast_addr(netifa: &libc::ifaddrs) -> Result<Option<Ipv4Addr>> {
89 let ifa_dstaddr = netifa.ifa_dstaddr;
90
91 if ifa_dstaddr.is_null() {
92 return Ok(None);
93 }
94
95 let socket_addr = ifa_dstaddr as *mut sockaddr_in;
96 let internet_address = unsafe { (*socket_addr).sin_addr };
97 let addr = ipv4_from_in_addr(&internet_address)?;
98
99 Ok(Some(addr))
100}
101
102fn make_ipv6_broadcast_addr(netifa: &libc::ifaddrs) -> Result<Option<Ipv6Addr>> {
109 let ifa_dstaddr = netifa.ifa_dstaddr;
110
111 if ifa_dstaddr.is_null() {
112 return Ok(None);
113 }
114
115 let socket_addr = ifa_dstaddr as *mut sockaddr_in6;
116 let internet_address = unsafe { (*socket_addr).sin6_addr };
117 let addr = ipv6_from_in6_addr(&internet_address)?;
118
119 Ok(Some(addr))
120}
121
122fn make_mac_addrs(netifa: &libc::ifaddrs) -> String {
123 let mut mac = [0; 6];
124 let mut ptr = unsafe { lladdr(netifa as *const libc::ifaddrs as *mut _) };
125
126 for el in &mut mac {
127 *el = unsafe { *ptr };
128 ptr = ((ptr as usize) + 1) as *const u8;
129 }
130
131 format!(
132 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
133 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
134 )
135}
136
137fn netifa_index(netifa: &libc::ifaddrs) -> u32 {
143 let name = netifa.ifa_name as *const libc::c_char;
144
145 unsafe { if_nametoindex(name) }
146}