1use crate::{pcap_util, Error};
2use std::mem;
3use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
4
5#[derive(Clone, Debug)]
6pub struct Info {
7 pub name: String,
8 pub ips: Vec<IpAddr>,
9}
10
11impl Info {
12 pub fn all() -> Result<Vec<Info>, Error> {
13 let mut err_buf = vec![0 as std::os::raw::c_char; pcap_sys::PCAP_ERRBUF_SIZE as _];
14 let mut device_result: *mut pcap_sys::pcap_if_t = std::ptr::null_mut();
15
16 unsafe {
17 let buf = std::mem::transmute::<
18 &mut *mut pcap_sys::pcap_if_t,
19 *mut *mut pcap_sys::pcap_if_t,
20 >(&mut device_result);
21 if 0 != pcap_sys::pcap_findalldevs(buf, err_buf.as_mut_ptr()) {
22 let err: Vec<_> = err_buf.iter().map(|v| *v as u8).collect();
23 let err_str =
24 std::ffi::CStr::from_bytes_with_nul(err.as_ref()).map_err(Error::FfiNul)?;
25 let utf_str = err_str.to_str().map_err(Error::Utf8)?;
26 return Err(Error::LibPcapError(utf_str.to_owned()));
27 }
28 }
29
30 let mut result = vec![];
31
32 while device_result != std::ptr::null_mut() {
33 let device_name_ptr = unsafe { (*device_result).name };
34 let device_name = pcap_util::cstr_to_string(device_name_ptr)?;
35 let mut device_addrs = unsafe { (*device_result).addresses };
36 let mut addresses = vec![];
37 while device_addrs != std::ptr::null_mut() {
38 let addr = unsafe { (*device_addrs).addr };
39 if addr != std::ptr::null_mut() {
40 let sockaddr = addr as *mut libc::sockaddr;
41 match unsafe { (*sockaddr).sa_family } as i32 {
42 libc::AF_INET => {
43 let ip_addr = unsafe {
44 let sock = sockaddr as *mut libc::sockaddr_in;
45 let sockaddr = (*sock).sin_addr.s_addr;
46 let sockaddr = mem::transmute::<u32, [u8; 4]>(sockaddr);
47 let sockaddr = Ipv4Addr::from(sockaddr);
48 sockaddr
49 };
50 addresses.push(IpAddr::V4(ip_addr));
51 }
52 libc::AF_INET6 => {
53 let ip_addr = unsafe {
54 let sock = sockaddr as *mut libc::sockaddr_in6;
55 let sockaddr = (*sock).sin6_addr.s6_addr;
56 let sockaddr = Ipv6Addr::from(sockaddr);
57 sockaddr
58 };
59 addresses.push(IpAddr::V6(ip_addr));
60 }
61 _ => {
62 }
64 }
65 }
66 device_addrs = unsafe { (*device_addrs).next };
67 }
68 result.push(Info {
69 name: device_name,
70 ips: addresses,
71 });
72 device_result = unsafe { (*device_result).next };
73 }
74
75 return Ok(result);
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_info_all() {
85 let infos = Info::all().expect("Failed to list");
86
87 println!("Devices={:?}", infos);
88
89 assert!(infos.is_empty() == false);
90 }
91}