pcap_async/
info.rs

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                            //not a type we care about
63                        }
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}