1use tracing::info;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum IsolationTier {
12 EnvProxy,
14 #[cfg(all(target_os = "linux", feature = "netns"))]
16 NetNamespace,
17}
18
19#[cfg(all(target_os = "linux", feature = "netns"))]
24fn has_cap_net_admin() -> bool {
25 let Ok(status) = std::fs::read_to_string("/proc/self/status") else {
26 return false;
27 };
28 for line in status.lines() {
29 if let Some(hex) = line.strip_prefix("CapEff:\t") {
30 let Ok(caps) = u64::from_str_radix(hex.trim(), 16) else {
31 return false;
32 };
33 return caps & (1 << 12) != 0;
35 }
36 }
37 false
38}
39
40pub fn detect_and_log() -> IsolationTier {
42 #[cfg(all(target_os = "linux", feature = "netns"))]
43 {
44 if has_cap_net_admin() {
45 info!("proxy: network namespace isolation (linux/netns)");
46 return IsolationTier::NetNamespace;
47 }
48 info!("proxy: env var mode (netns unavailable: missing CAP_NET_ADMIN)");
49 return IsolationTier::EnvProxy;
50 }
51
52 #[cfg(not(all(target_os = "linux", feature = "netns")))]
53 {
54 #[cfg(target_os = "linux")]
55 info!("proxy: env var mode (netns feature not compiled)");
56 #[cfg(not(target_os = "linux"))]
57 info!("proxy: env var mode (not linux)");
58 IsolationTier::EnvProxy
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn detect_returns_valid_tier() {
68 let tier = detect_and_log();
69 #[cfg(not(all(target_os = "linux", feature = "netns")))]
70 assert_eq!(tier, IsolationTier::EnvProxy);
71 let _ = tier; }
73}