1use std::fmt::Debug;
2
3#[allow(dead_code)]
4pub fn index_to_name(index: InterfaceId) -> Result<String, std::io::Error> {
5 let index = if let Some(index) = index.inner() {
6 index
7 } else {
8 return Err(std::io::Error::new(
9 std::io::ErrorKind::InvalidInput,
10 "interface index is unspecified",
11 ));
12 };
13 let ifname_buf = [0u8; libc::IFNAMSIZ];
14 let ret = unsafe { libc::if_indextoname(index, ifname_buf.as_ptr() as *mut libc::c_char) };
15 if ret.is_null() {
16 return Err(std::io::Error::last_os_error());
17 }
18
19 let name = unsafe { std::ffi::CStr::from_ptr(ret) }
20 .to_str()
21 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?
22 .to_owned();
23 Ok(name)
24}
25
26pub fn name_to_index(name: &str) -> Result<InterfaceId, std::io::Error> {
27 let name = std::ffi::CString::new(name)
28 .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?;
29 let index = unsafe { libc::if_nametoindex(name.as_ptr() as *const libc::c_char) };
30 if index == 0 {
31 return Err(std::io::Error::last_os_error());
32 }
33 Ok(InterfaceId::new(index))
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq)]
37pub struct InterfaceId {
38 if_index: libc::c_uint,
39}
40
41#[allow(dead_code)]
42impl InterfaceId {
43 pub const UNSPECIFIED: Self = Self { if_index: 0 };
44
45 pub(crate) fn new(if_index: libc::c_uint) -> Self {
46 Self { if_index }
47 }
48
49 pub(crate) fn inner_unchecked(&self) -> libc::c_uint {
50 self.if_index
51 }
52
53 pub(crate) fn inner(&self) -> Option<libc::c_uint> {
54 if self.if_index == 0 {
55 None
56 } else {
57 Some(self.if_index)
58 }
59 }
60
61 pub fn is_unspecified(&self) -> bool {
62 self.if_index == 0
63 }
64}
65
66#[derive(Debug, Clone, PartialEq)]
67pub struct Interface {
68 pub if_id: InterfaceId,
69 pub if_name: String,
70}