#[cfg(target_os = "linux")]
#[must_use]
pub fn probe_has_cap_net_admin() -> bool {
const CAP_NET_ADMIN_BIT: u64 = 1 << 12;
let Ok(status) = std::fs::read_to_string("/proc/self/status") else {
return false;
};
for line in status.lines() {
if let Some(hex) = line.strip_prefix("CapEff:") {
let trimmed = hex.trim();
if let Ok(eff) = u64::from_str_radix(trimmed, 16) {
return eff & CAP_NET_ADMIN_BIT != 0;
}
return false;
}
}
false
}
#[cfg(not(target_os = "linux"))]
#[must_use]
pub fn probe_has_cap_net_admin() -> bool {
false
}
#[cfg(target_os = "linux")]
#[must_use]
pub fn probe_tun_device_available() -> bool {
use std::os::unix::fs::OpenOptionsExt;
std::fs::OpenOptions::new()
.read(true)
.write(true)
.custom_flags(libc::O_NONBLOCK)
.open("/dev/net/tun")
.is_ok()
}
#[cfg(not(target_os = "linux"))]
#[must_use]
pub fn probe_tun_device_available() -> bool {
false
}
#[cfg(test)]
mod tests {
#[test]
fn tun_probe_is_total_and_does_not_panic() {
let _ = super::probe_tun_device_available();
}
#[test]
fn cap_net_admin_probe_is_total_and_does_not_panic() {
let _ = super::probe_has_cap_net_admin();
}
#[cfg(target_os = "linux")]
#[test]
fn probe_has_cap_net_admin_matches_cap_eff() {
let status = std::fs::read_to_string("/proc/self/status").unwrap();
let cap_eff_line = status
.lines()
.find(|l| l.starts_with("CapEff:"))
.expect("CapEff: present in /proc/self/status");
let hex = cap_eff_line.trim_start_matches("CapEff:").trim();
let eff: u64 = u64::from_str_radix(hex, 16).unwrap();
let expected = (eff & (1u64 << 12)) != 0;
assert_eq!(super::probe_has_cap_net_admin(), expected);
}
}