use anyhow::Result; use wireguard::WireGuard; #[tokio::main] async fn main() -> Result<()> { let mut wireguard = WireGuard::new().await?; let devices = wireguard.view_devices().await?; if devices.is_empty() { println!("no wireguard devices found"); return Ok(()); } for device in devices { println!("device: {}", device.name); println!(" ifindex: {}", device.ifindex); println!(" private_key: {}", format_optional_key(device.private_key)); println!(" public_key: {}", format_optional_key(device.public_key)); println!(" listen_port: {}", device.listen_port); println!(" fwmark: {}", device.fwmark); println!(" peers: {}", device.peers.len()); for (index, peer) in device.peers.iter().enumerate() { println!(" peer {}:", index + 1); println!(" public_key: {}", peer.public_key); println!( " preshared_key: {}", format_optional_key(peer.preshared_key) ); println!( " endpoint: {}", peer.endpoint .map(|endpoint| endpoint.to_string()) .unwrap_or_else(|| "none".to_string()) ); println!( " persistent_keepalive: {}", peer.persistent_keepalive .map(|keepalive| keepalive.to_string()) .unwrap_or_else(|| "none".to_string()) ); println!( " last_handshake: {}", format_duration(peer.last_handshake) ); println!(" rx_bytes: {}", peer.rx_bytes); println!(" tx_bytes: {}", peer.tx_bytes); if peer.allowed_ips.is_empty() { println!(" allowed_ips: none"); } else { let allowed_ips = peer .allowed_ips .iter() .map(|ip| ip.to_string()) .collect::>() .join(", "); println!(" allowed_ips: {}", allowed_ips); } } println!(); } Ok(()) } fn format_optional_key(key: Option) -> String { key.map(|value| value.to_string()) .unwrap_or_else(|| "none".to_string()) } fn format_duration(time: Option) -> String { match time { Some(time) => match time.duration_since(std::time::UNIX_EPOCH) { Ok(duration) => format!("{}.{}", duration.as_secs(), duration.subsec_nanos()), Err(_) => "before-epoch".to_string(), }, None => "none".to_string(), } }