pub mod addr;
pub mod netinfo;
pub mod packet;
pub mod raw;
pub mod socket;
pub mod udp;
pub use nix;
pub use nix::sys::socket::sockopt::*;
#[derive(Clone, Copy, Debug)]
pub struct Ipv4Subnet {
pub addr: std::net::Ipv4Addr,
pub prefixlen: u8,
}
#[derive(Debug)]
pub enum Error {
InvalidSubnet,
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidSubnet => write!(f, "Invalid Subnet"),
}
}
}
impl std::fmt::Display for Ipv4Subnet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}/{}", self.addr, self.prefixlen)
}
}
impl Ipv4Subnet {
pub fn new(addr: std::net::Ipv4Addr, prefixlen: u8) -> Result<Self, Error> {
let ret = Self { addr, prefixlen };
if u32::from(ret.addr) & !u32::from(ret.netmask()) != 0 {
Err(Error::InvalidSubnet)
} else {
Ok(ret)
}
}
pub fn network(&self) -> std::net::Ipv4Addr {
(u32::from(self.addr) & u32::from(self.netmask())).into()
}
pub fn netmask(&self) -> std::net::Ipv4Addr {
(!(0xffff_ffff_u64 >> self.prefixlen) as u32).into()
}
pub fn contains(&self, ip: std::net::Ipv4Addr) -> bool {
u32::from(ip) & u32::from(self.netmask()) == u32::from(self.addr)
}
pub fn broadcast(&self) -> std::net::Ipv4Addr {
(u32::from(self.network()) | !u32::from(self.netmask())).into()
}
}
#[test]
fn test_netmask() -> Result<(), Error> {
assert_eq!(
Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 0)?.netmask(),
"0.0.0.0".parse::<std::net::Ipv4Addr>().unwrap()
);
assert_eq!(
Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 8)?.netmask(),
"255.0.0.0".parse::<std::net::Ipv4Addr>().unwrap()
);
assert_eq!(
Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 16)?.netmask(),
"255.255.0.0".parse::<std::net::Ipv4Addr>().unwrap()
);
assert_eq!(
Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 24)?.netmask(),
"255.255.255.0".parse::<std::net::Ipv4Addr>().unwrap()
);
assert_eq!(
Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 25)?.netmask(),
"255.255.255.128".parse::<std::net::Ipv4Addr>().unwrap()
);
assert_eq!(
Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 32)?.netmask(),
"255.255.255.255".parse::<std::net::Ipv4Addr>().unwrap()
);
Ok(())
}
#[test]
fn test_prefix() {
let subnet = Ipv4Subnet::new("192.0.2.112".parse().unwrap(), 28).unwrap();
assert_eq!(
subnet.broadcast(),
"192.0.2.127".parse::<std::net::Ipv4Addr>().unwrap()
);
assert_eq!(
subnet.netmask(),
"255.255.255.240".parse::<std::net::Ipv4Addr>().unwrap()
);
}
#[test]
fn test_contains() {
assert!(
Ipv4Subnet::new("192.168.0.128".parse().unwrap(), 25)
.unwrap()
.contains("192.168.0.200".parse().unwrap())
);
assert!(
!Ipv4Subnet::new("192.168.0.128".parse().unwrap(), 25)
.unwrap()
.contains("192.168.0.100".parse().unwrap())
);
}