1use core::fmt;
2use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
3
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
9#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10pub enum IpNet {
11 V4(Ipv4Net),
12 V6(Ipv6Net),
13}
14
15impl IpNet {
16 pub fn new(ip: IpAddr, prefix_len: u8) -> IpNet {
18 match ip {
19 IpAddr::V4(addr) => Ipv4Net::new(addr, prefix_len).into(),
20 IpAddr::V6(addr) => Ipv6Net::new(addr, prefix_len).into(),
21 }
22 }
23 pub fn new_with_netmask(ip: IpAddr, netmask: IpAddr) -> IpNet {
25 let prefix = ip_netmask_to_prefix(netmask);
26 Self::new(ip, prefix)
27 }
28 pub fn addr(&self) -> IpAddr {
30 match *self {
31 IpNet::V4(ref a) => IpAddr::V4(a.addr),
32 IpNet::V6(ref a) => IpAddr::V6(a.addr),
33 }
34 }
35 pub fn prefix_len(&self) -> u8 {
37 match *self {
38 IpNet::V4(ref a) => a.prefix_len,
39 IpNet::V6(ref a) => a.prefix_len,
40 }
41 }
42 pub fn max_prefix_len(&self) -> u8 {
44 match *self {
45 IpNet::V4(ref a) => a.max_prefix_len(),
46 IpNet::V6(ref a) => a.max_prefix_len(),
47 }
48 }
49 pub fn netmask(&self) -> IpAddr {
51 match *self {
52 IpNet::V4(ref a) => IpAddr::V4(a.netmask()),
53 IpNet::V6(ref a) => IpAddr::V6(a.netmask()),
54 }
55 }
56 pub fn hostmask(&self) -> IpAddr {
58 match *self {
59 IpNet::V4(ref a) => IpAddr::V4(a.hostmask()),
60 IpNet::V6(ref a) => IpAddr::V6(a.hostmask()),
61 }
62 }
63 pub fn network(&self) -> IpAddr {
65 match *self {
66 IpNet::V4(ref a) => IpAddr::V4(a.network()),
67 IpNet::V6(ref a) => IpAddr::V6(a.network()),
68 }
69 }
70 pub fn broadcast(&self) -> IpAddr {
72 match *self {
73 IpNet::V4(ref a) => IpAddr::V4(a.broadcast()),
74 IpNet::V6(ref a) => IpAddr::V6(a.broadcast()),
75 }
76 }
77}
78
79impl From<Ipv4Net> for IpNet {
80 fn from(net: Ipv4Net) -> IpNet {
81 IpNet::V4(net)
82 }
83}
84
85impl From<Ipv6Net> for IpNet {
86 fn from(net: Ipv6Net) -> IpNet {
87 IpNet::V6(net)
88 }
89}
90
91impl From<IpAddr> for IpNet {
92 fn from(addr: IpAddr) -> IpNet {
93 match addr {
94 IpAddr::V4(addr) => IpNet::V4(addr.into()),
95 IpAddr::V6(addr) => IpNet::V6(addr.into()),
96 }
97 }
98}
99
100#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
103pub struct Ipv4Net {
104 pub addr: Ipv4Addr,
106 pub prefix_len: u8,
108 pub netmask: Ipv4Addr,
110}
111
112impl Ipv4Net {
113 pub fn new(ipv4_addr: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
115 Ipv4Net {
116 addr: ipv4_addr,
117 prefix_len: prefix_len,
118 netmask: prefix_to_ipv4_netmask(prefix_len),
119 }
120 }
121 pub fn new_with_netmask(ipv4_addr: Ipv4Addr, netmask: Ipv4Addr) -> Ipv4Net {
123 Ipv4Net {
124 addr: ipv4_addr,
125 prefix_len: ipv4_netmask_to_prefix(netmask),
126 netmask: netmask,
127 }
128 }
129 pub const fn max_prefix_len(&self) -> u8 {
131 32
132 }
133 pub fn netmask(&self) -> Ipv4Addr {
135 Ipv4Addr::from(self.netmask_u32())
136 }
137 fn netmask_u32(&self) -> u32 {
139 u32::max_value()
140 .checked_shl(32 - self.prefix_len as u32)
141 .unwrap_or(0)
142 }
143 pub fn hostmask(&self) -> Ipv4Addr {
145 Ipv4Addr::from(self.hostmask_u32())
146 }
147 fn hostmask_u32(&self) -> u32 {
149 u32::max_value()
150 .checked_shr(self.prefix_len as u32)
151 .unwrap_or(0)
152 }
153 pub fn network(&self) -> Ipv4Addr {
155 Ipv4Addr::from(u32::from(self.addr) & self.netmask_u32())
156 }
157 pub fn broadcast(&self) -> Ipv4Addr {
159 Ipv4Addr::from(u32::from(self.addr) | self.hostmask_u32())
160 }
161}
162
163impl fmt::Debug for Ipv4Net {
164 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
165 fmt::Display::fmt(self, fmt)
166 }
167}
168
169impl fmt::Display for Ipv4Net {
170 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
171 write!(fmt, "{}/{}", self.addr, self.prefix_len)
172 }
173}
174
175impl From<Ipv4Addr> for Ipv4Net {
176 fn from(addr: Ipv4Addr) -> Ipv4Net {
177 Ipv4Net {
178 addr,
179 prefix_len: 32,
180 netmask: prefix_to_ipv4_netmask(32),
181 }
182 }
183}
184
185#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
188pub struct Ipv6Net {
189 pub addr: Ipv6Addr,
191 pub prefix_len: u8,
193 pub netmask: Ipv6Addr,
195}
196
197impl Ipv6Net {
198 pub fn new(ipv6_addr: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
200 Ipv6Net {
201 addr: ipv6_addr,
202 prefix_len: prefix_len,
203 netmask: prefix_to_ipv6_netmask(prefix_len),
204 }
205 }
206 pub fn new_with_netmask(ipv6_addr: Ipv6Addr, netmask: Ipv6Addr) -> Ipv6Net {
208 Ipv6Net {
209 addr: ipv6_addr,
210 prefix_len: ipv6_netmask_to_prefix(netmask),
211 netmask: netmask,
212 }
213 }
214 pub const fn max_prefix_len(&self) -> u8 {
216 128
217 }
218 pub fn netmask(&self) -> Ipv6Addr {
220 self.netmask_u128().into()
221 }
222 fn netmask_u128(&self) -> u128 {
224 u128::max_value()
225 .checked_shl((128 - self.prefix_len) as u32)
226 .unwrap_or(u128::min_value())
227 }
228 pub fn hostmask(&self) -> Ipv6Addr {
230 self.hostmask_u128().into()
231 }
232 fn hostmask_u128(&self) -> u128 {
234 u128::max_value()
235 .checked_shr(self.prefix_len as u32)
236 .unwrap_or(u128::min_value())
237 }
238 pub fn network(&self) -> Ipv6Addr {
240 (u128::from(self.addr) & self.netmask_u128()).into()
241 }
242 pub fn broadcast(&self) -> Ipv6Addr {
244 (u128::from(self.addr) | self.hostmask_u128()).into()
245 }
246}
247
248impl fmt::Debug for Ipv6Net {
249 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
250 fmt::Display::fmt(self, fmt)
251 }
252}
253
254impl fmt::Display for Ipv6Net {
255 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
256 write!(fmt, "{}/{}", self.addr, self.prefix_len)
257 }
258}
259
260impl From<Ipv6Addr> for Ipv6Net {
261 fn from(addr: Ipv6Addr) -> Ipv6Net {
262 Ipv6Net {
263 addr,
264 prefix_len: 128,
265 netmask: prefix_to_ipv6_netmask(128),
266 }
267 }
268}
269
270fn ip_netmask_to_prefix(mask: IpAddr) -> u8 {
271 match mask {
272 IpAddr::V4(mask) => ipv4_netmask_to_prefix(mask),
273 IpAddr::V6(mask) => ipv6_netmask_to_prefix(mask),
274 }
275}
276
277fn ipv4_netmask_to_prefix(netmask: Ipv4Addr) -> u8 {
278 let netmask = u32::from(netmask);
279 let prefix = (!netmask).leading_zeros() as u8;
280 if (u64::from(netmask) << prefix) & 0xffff_ffff != 0 {
281 0
282 } else {
283 prefix
284 }
285}
286
287fn ipv6_netmask_to_prefix(netmask: Ipv6Addr) -> u8 {
288 let netmask = netmask.segments();
289 let mut mask_iter = netmask.iter();
290 let mut prefix = 0;
291 for &segment in &mut mask_iter {
292 if segment == 0xffff {
293 prefix += 16;
294 } else if segment == 0 {
295 break;
296 } else {
297 let prefix_bits = (!segment).leading_zeros() as u8;
298 if segment << prefix_bits != 0 {
299 return 0;
300 }
301 prefix += prefix_bits;
302 break;
303 }
304 }
305 for &segment in mask_iter {
306 if segment != 0 {
307 return 0;
308 }
309 }
310 prefix
311}
312
313fn prefix_to_ipv4_netmask(prefix_len: u8) -> Ipv4Addr {
314 let netmask_u32: u32 = u32::max_value()
315 .checked_shl(32 - prefix_len as u32)
316 .unwrap_or(0);
317 Ipv4Addr::from(netmask_u32)
318}
319
320fn prefix_to_ipv6_netmask(prefix_len: u8) -> Ipv6Addr {
321 let netmask_u128: u128 = u128::max_value()
322 .checked_shl((128 - prefix_len) as u32)
323 .unwrap_or(u128::min_value());
324 Ipv6Addr::from(netmask_u128)
325}