1pub mod addr;
18pub mod netinfo;
19pub mod packet;
20pub mod raw;
21pub mod socket;
22pub mod udp;
23
24pub use nix;
28pub use nix::sys::socket::sockopt::*;
29
30#[derive(Clone, Copy, Debug)]
32pub struct Ipv4Subnet {
33 pub addr: std::net::Ipv4Addr,
34 pub prefixlen: u8,
35}
36
37#[derive(Debug)]
38pub enum Error {
39 InvalidSubnet,
40}
41
42impl std::fmt::Display for Error {
43 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
44 match self {
45 Self::InvalidSubnet => write!(f, "Invalid Subnet"),
46 }
47 }
48}
49
50impl std::fmt::Display for Ipv4Subnet {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "{}/{}", self.addr, self.prefixlen)
53 }
54}
55
56impl Ipv4Subnet {
57 pub fn new(addr: std::net::Ipv4Addr, prefixlen: u8) -> Result<Self, Error> {
58 let ret = Self { addr, prefixlen };
59 if u32::from(ret.addr) & !u32::from(ret.netmask()) != 0 {
61 Err(Error::InvalidSubnet)
62 } else {
63 Ok(ret)
64 }
65 }
66 pub fn network(&self) -> std::net::Ipv4Addr {
67 (u32::from(self.addr) & u32::from(self.netmask())).into()
68 }
69 pub fn netmask(&self) -> std::net::Ipv4Addr {
70 (!(0xffff_ffff_u64 >> self.prefixlen) as u32).into()
71 }
72 pub fn contains(&self, ip: std::net::Ipv4Addr) -> bool {
73 u32::from(ip) & u32::from(self.netmask()) == u32::from(self.addr)
74 }
75 pub fn broadcast(&self) -> std::net::Ipv4Addr {
76 (u32::from(self.network()) | !u32::from(self.netmask())).into()
77 }
78}
79
80#[test]
81fn test_netmask() -> Result<(), Error> {
82 assert_eq!(
83 Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 0)?.netmask(),
84 "0.0.0.0".parse::<std::net::Ipv4Addr>().unwrap()
85 );
86 assert_eq!(
87 Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 8)?.netmask(),
88 "255.0.0.0".parse::<std::net::Ipv4Addr>().unwrap()
89 );
90 assert_eq!(
91 Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 16)?.netmask(),
92 "255.255.0.0".parse::<std::net::Ipv4Addr>().unwrap()
93 );
94 assert_eq!(
95 Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 24)?.netmask(),
96 "255.255.255.0".parse::<std::net::Ipv4Addr>().unwrap()
97 );
98 assert_eq!(
99 Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 25)?.netmask(),
100 "255.255.255.128".parse::<std::net::Ipv4Addr>().unwrap()
101 );
102 assert_eq!(
103 Ipv4Subnet::new("0.0.0.0".parse().unwrap(), 32)?.netmask(),
104 "255.255.255.255".parse::<std::net::Ipv4Addr>().unwrap()
105 );
106 Ok(())
107}
108
109#[test]
110fn test_prefix() {
111 let subnet = Ipv4Subnet::new("192.0.2.112".parse().unwrap(), 28).unwrap();
112 assert_eq!(
113 subnet.broadcast(),
114 "192.0.2.127".parse::<std::net::Ipv4Addr>().unwrap()
115 );
116 assert_eq!(
117 subnet.netmask(),
118 "255.255.255.240".parse::<std::net::Ipv4Addr>().unwrap()
119 );
120}
121
122#[test]
123fn test_contains() {
124 assert_eq!(
125 Ipv4Subnet::new("192.168.0.128".parse().unwrap(), 25)
126 .unwrap()
127 .contains("192.168.0.200".parse().unwrap()),
128 true
129 );
130 assert_eq!(
131 Ipv4Subnet::new("192.168.0.128".parse().unwrap(), 25)
132 .unwrap()
133 .contains("192.168.0.100".parse().unwrap()),
134 false
135 );
136}