use std::{net::Ipv4Addr, os::unix::process::ExitStatusExt};
use pnet::datalink;
use crate::error;
pub fn get_random_port() -> u16 {
fastrand::u16(1024..65535)
}
pub fn get_random_ip() -> Ipv4Addr {
Ipv4Addr::new(
fastrand::u8(0..255),
fastrand::u8(0..255),
fastrand::u8(0..255),
fastrand::u8(0..255),
)
}
pub fn get_interface(name: &str) -> Option<datalink::NetworkInterface> {
datalink::interfaces()
.into_iter()
.find(|interface| interface.name == name)
}
pub fn get_interfaces() -> Vec<datalink::NetworkInterface> {
datalink::interfaces()
}
pub fn get_default_interface() -> Option<datalink::NetworkInterface> {
datalink::interfaces().into_iter().find(|interface| {
interface
.ips
.iter()
.any(|ip| ip.is_ipv4() && ip.ip().is_loopback())
})
}
#[inline(always)]
fn is_root() -> bool {
nix::unistd::Uid::current().is_root()
}
pub fn rerun_if_not_root() -> crate::Result<()> {
if !is_root() {
let args: Vec<String> = std::env::args().collect();
let program = &args[0];
let rest_args = &args[1..];
let status = std::process::Command::new("sudo")
.arg(program)
.args(rest_args)
.status()?;
if !status.success() {
match status.signal() {
Some(nix::libc::SIGINT) => {
std::process::exit(130);
}
Some(signal) => {
return Err(error::Error::OsError(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
format!("Failed to grant root privileges: signal {}", signal),
)));
}
_ => {
return Err(error::Error::OsError(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
"Failed to grant root privileges",
)));
}
}
}
}
Ok(())
}
pub fn get_num_threads(rated_power: u8) -> crate::Result<usize> {
let available_parallelism = std::thread::available_parallelism()?.get();
Ok(match rated_power {
0 => available_parallelism,
1 => available_parallelism / 10,
2 => available_parallelism / 5,
3 => available_parallelism / 2,
4 => available_parallelism * 3 / 4,
_ => panic!(
"Invalid rated power {}, available ratings are 1 to 4",
rated_power
),
})
}