1 | use alloc::vec::Vec; |
2 | use core::cmp::{min, max}; |
3 | use core::cmp::Ordering::{Less, Equal}; |
4 | use core::convert::From; |
5 | use core::fmt; |
6 | use core::iter::FusedIterator; |
7 | use core::option::Option::{Some, None}; |
8 | #[cfg (not(feature = "std" ))] |
9 | use core::error::Error; |
10 | #[cfg (feature = "std" )] |
11 | use std::error::Error; |
12 | #[cfg (not(feature = "std" ))] |
13 | use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
14 | #[cfg (feature = "std" )] |
15 | use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
16 | |
17 | use crate::ipext::{IpAdd, IpSub, IpStep, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange}; |
18 | use crate::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix}; |
19 | |
20 | /// An IP network address, either IPv4 or IPv6. |
21 | /// |
22 | /// This enum can contain either an [`Ipv4Net`] or an [`Ipv6Net`]. A |
23 | /// [`From`] implementation is provided to convert these into an |
24 | /// `IpNet`. |
25 | /// |
26 | /// # Textual representation |
27 | /// |
28 | /// `IpNet` provides a [`FromStr`] implementation for parsing network |
29 | /// addresses represented in CIDR notation. See [IETF RFC 4632] for the |
30 | /// CIDR notation. |
31 | /// |
32 | /// [`Ipv4Net`]: struct.Ipv4Net.html |
33 | /// [`Ipv6Net`]: struct.Ipv6Net.html |
34 | /// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html |
35 | /// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html |
36 | /// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632 |
37 | /// |
38 | /// # Examples |
39 | /// |
40 | /// ``` |
41 | /// use std::net::IpAddr; |
42 | /// use ipnet::IpNet; |
43 | /// |
44 | /// let net: IpNet = "10.1.1.0/24" .parse().unwrap(); |
45 | /// assert_eq!(Ok(net.network()), "10.1.1.0" .parse()); |
46 | /// |
47 | /// let net: IpNet = "fd00::/32" .parse().unwrap(); |
48 | /// assert_eq!(Ok(net.network()), "fd00::" .parse()); |
49 | /// ``` |
50 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] |
51 | pub enum IpNet { |
52 | V4(Ipv4Net), |
53 | V6(Ipv6Net), |
54 | } |
55 | |
56 | /// An IPv4 network address. |
57 | /// |
58 | /// See [`IpNet`] for a type encompassing both IPv4 and IPv6 network |
59 | /// addresses. |
60 | /// |
61 | /// # Textual representation |
62 | /// |
63 | /// `Ipv4Net` provides a [`FromStr`] implementation for parsing network |
64 | /// addresses represented in CIDR notation. See [IETF RFC 4632] for the |
65 | /// CIDR notation. |
66 | /// |
67 | /// [`IpNet`]: enum.IpNet.html |
68 | /// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html |
69 | /// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632 |
70 | /// |
71 | /// # Examples |
72 | /// |
73 | /// ``` |
74 | /// # #[cfg (feature = "std" )] |
75 | /// # use std::net::Ipv6Addr; |
76 | /// # #[cfg (not(feature = "std" ))] |
77 | /// # use core::net::Ipv6Addr; |
78 | /// use ipnet::Ipv4Net; |
79 | /// |
80 | /// let net: Ipv4Net = "10.1.1.0/24" .parse().unwrap(); |
81 | /// assert_eq!(Ok(net.network()), "10.1.1.0" .parse()); |
82 | /// ``` |
83 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] |
84 | pub struct Ipv4Net { |
85 | addr: Ipv4Addr, |
86 | prefix_len: u8, |
87 | } |
88 | |
89 | /// An IPv6 network address. |
90 | /// |
91 | /// See [`IpNet`] for a type encompassing both IPv4 and IPv6 network |
92 | /// addresses. |
93 | /// |
94 | /// # Textual representation |
95 | /// |
96 | /// `Ipv6Net` provides a [`FromStr`] implementation for parsing network |
97 | /// addresses represented in CIDR notation. See [IETF RFC 4632] for the |
98 | /// CIDR notation. |
99 | /// |
100 | /// [`IpNet`]: enum.IpNet.html |
101 | /// [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html |
102 | /// [IETF RFC 4632]: https://tools.ietf.org/html/rfc4632 |
103 | /// |
104 | /// # Examples |
105 | /// |
106 | /// ``` |
107 | /// use std::net::Ipv6Addr; |
108 | /// use ipnet::Ipv6Net; |
109 | /// |
110 | /// let net: Ipv6Net = "fd00::/32" .parse().unwrap(); |
111 | /// assert_eq!(Ok(net.network()), "fd00::" .parse()); |
112 | /// ``` |
113 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] |
114 | pub struct Ipv6Net { |
115 | addr: Ipv6Addr, |
116 | prefix_len: u8, |
117 | } |
118 | |
119 | /// An error which can be returned when the prefix length is invalid. |
120 | /// |
121 | /// Valid prefix lengths are 0 to 32 for IPv4 and 0 to 128 for IPv6. |
122 | #[derive (Debug, Clone, PartialEq, Eq)] |
123 | pub struct PrefixLenError; |
124 | |
125 | impl fmt::Display for PrefixLenError { |
126 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
127 | fmt.write_str(data:"invalid IP prefix length" ) |
128 | } |
129 | } |
130 | |
131 | impl Error for PrefixLenError {} |
132 | |
133 | impl IpNet { |
134 | /// Creates a new IP network address from an `IpAddr` and prefix |
135 | /// length. |
136 | /// |
137 | /// # Examples |
138 | /// |
139 | /// ``` |
140 | /// use std::net::Ipv6Addr; |
141 | /// use ipnet::{IpNet, PrefixLenError}; |
142 | /// |
143 | /// let net = IpNet::new(Ipv6Addr::LOCALHOST.into(), 48); |
144 | /// assert!(net.is_ok()); |
145 | /// |
146 | /// let bad_prefix_len = IpNet::new(Ipv6Addr::LOCALHOST.into(), 129); |
147 | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
148 | /// ``` |
149 | pub fn new(ip: IpAddr, prefix_len: u8) -> Result<IpNet, PrefixLenError> { |
150 | Ok(match ip { |
151 | IpAddr::V4(a) => Ipv4Net::new(a, prefix_len)?.into(), |
152 | IpAddr::V6(a) => Ipv6Net::new(a, prefix_len)?.into(), |
153 | }) |
154 | } |
155 | |
156 | /// Creates a new IP network address from an `IpAddr` and prefix |
157 | /// length. If called from a const context it will verify prefix length |
158 | /// at compile time. Otherwise it will panic at runtime if prefix length |
159 | /// is incorrect for a given IpAddr type. |
160 | /// |
161 | /// # Examples |
162 | /// |
163 | /// ``` |
164 | /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
165 | /// use ipnet::{IpNet}; |
166 | /// |
167 | /// // This code is verified at compile time: |
168 | /// const NET: IpNet = IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(10, 1, 1, 0)), 24); |
169 | /// assert_eq!(NET.prefix_len(), 24); |
170 | /// |
171 | /// // This code is verified at runtime: |
172 | /// let net = IpNet::new_assert(Ipv6Addr::LOCALHOST.into(), 24); |
173 | /// assert_eq!(net.prefix_len(), 24); |
174 | /// |
175 | /// // This code does not compile: |
176 | /// // const BAD_PREFIX_LEN: IpNet = IpNet::new_assert(IpAddr::V4(Ipv4Addr::new(10, 1, 1, 0)), 33); |
177 | /// |
178 | /// // This code panics at runtime: |
179 | /// // let bad_prefix_len = IpNet::new_assert(Ipv6Addr::LOCALHOST.into(), 129); |
180 | /// ``` |
181 | pub const fn new_assert(ip: IpAddr, prefix_len: u8) -> IpNet { |
182 | match ip { |
183 | IpAddr::V4(a) => IpNet::V4(Ipv4Net::new_assert(a, prefix_len)), |
184 | IpAddr::V6(a) => IpNet::V6(Ipv6Net::new_assert(a, prefix_len)), |
185 | } |
186 | } |
187 | |
188 | /// Creates a new IP network address from an `IpAddr` and netmask. |
189 | /// |
190 | /// # Examples |
191 | /// |
192 | /// ``` |
193 | /// use std::net::Ipv6Addr; |
194 | /// use ipnet::{IpNet, PrefixLenError}; |
195 | /// |
196 | /// let net = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0000_0000_0000_0000).into()); |
197 | /// assert!(net.is_ok()); |
198 | /// |
199 | /// let bad_prefix_len = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0001_0000_0000_0000).into()); |
200 | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
201 | /// ``` |
202 | pub fn with_netmask(ip: IpAddr, netmask: IpAddr) -> Result<IpNet, PrefixLenError> { |
203 | let prefix = ip_mask_to_prefix(netmask)?; |
204 | Self::new(ip, prefix) |
205 | } |
206 | |
207 | /// Returns a copy of the network with the address truncated to the |
208 | /// prefix length. |
209 | /// |
210 | /// # Examples |
211 | /// |
212 | /// ``` |
213 | /// # use ipnet::IpNet; |
214 | /// # |
215 | /// assert_eq!( |
216 | /// "192.168.12.34/16" .parse::<IpNet>().unwrap().trunc(), |
217 | /// "192.168.0.0/16" .parse().unwrap() |
218 | /// ); |
219 | /// |
220 | /// assert_eq!( |
221 | /// "fd00::1:2:3:4/16" .parse::<IpNet>().unwrap().trunc(), |
222 | /// "fd00::/16" .parse().unwrap() |
223 | /// ); |
224 | /// ``` |
225 | pub fn trunc(&self) -> IpNet { |
226 | match *self { |
227 | IpNet::V4(ref a) => IpNet::V4(a.trunc()), |
228 | IpNet::V6(ref a) => IpNet::V6(a.trunc()), |
229 | } |
230 | } |
231 | |
232 | /// Returns the address. |
233 | pub fn addr(&self) -> IpAddr { |
234 | match *self { |
235 | IpNet::V4(ref a) => IpAddr::V4(a.addr), |
236 | IpNet::V6(ref a) => IpAddr::V6(a.addr), |
237 | } |
238 | } |
239 | |
240 | /// Returns the prefix length. |
241 | pub fn prefix_len(&self) -> u8 { |
242 | match *self { |
243 | IpNet::V4(ref a) => a.prefix_len(), |
244 | IpNet::V6(ref a) => a.prefix_len(), |
245 | } |
246 | } |
247 | |
248 | /// Returns the maximum valid prefix length. |
249 | pub fn max_prefix_len(&self) -> u8 { |
250 | match *self { |
251 | IpNet::V4(ref a) => a.max_prefix_len(), |
252 | IpNet::V6(ref a) => a.max_prefix_len(), |
253 | } |
254 | } |
255 | |
256 | /// Returns the network mask. |
257 | /// |
258 | /// # Examples |
259 | /// |
260 | /// ``` |
261 | /// # use std::net::IpAddr; |
262 | /// # use ipnet::IpNet; |
263 | /// # |
264 | /// let net: IpNet = "10.1.0.0/20" .parse().unwrap(); |
265 | /// assert_eq!(Ok(net.netmask()), "255.255.240.0" .parse()); |
266 | /// |
267 | /// let net: IpNet = "fd00::/24" .parse().unwrap(); |
268 | /// assert_eq!(Ok(net.netmask()), "ffff:ff00::" .parse()); |
269 | /// ``` |
270 | pub fn netmask(&self) -> IpAddr { |
271 | match *self { |
272 | IpNet::V4(ref a) => IpAddr::V4(a.netmask()), |
273 | IpNet::V6(ref a) => IpAddr::V6(a.netmask()), |
274 | } |
275 | } |
276 | |
277 | /// Returns the host mask. |
278 | /// |
279 | /// # Examples |
280 | /// |
281 | /// ``` |
282 | /// # use std::net::IpAddr; |
283 | /// # use ipnet::IpNet; |
284 | /// # |
285 | /// let net: IpNet = "10.1.0.0/20" .parse().unwrap(); |
286 | /// assert_eq!(Ok(net.hostmask()), "0.0.15.255" .parse()); |
287 | /// |
288 | /// let net: IpNet = "fd00::/24" .parse().unwrap(); |
289 | /// assert_eq!(Ok(net.hostmask()), "::ff:ffff:ffff:ffff:ffff:ffff:ffff" .parse()); |
290 | /// ``` |
291 | pub fn hostmask(&self) -> IpAddr { |
292 | match *self { |
293 | IpNet::V4(ref a) => IpAddr::V4(a.hostmask()), |
294 | IpNet::V6(ref a) => IpAddr::V6(a.hostmask()), |
295 | } |
296 | } |
297 | |
298 | /// Returns the network address. |
299 | /// |
300 | /// # Examples |
301 | /// |
302 | /// ``` |
303 | /// # use std::net::IpAddr; |
304 | /// # use ipnet::IpNet; |
305 | /// # |
306 | /// let net: IpNet = "172.16.123.123/16" .parse().unwrap(); |
307 | /// assert_eq!(Ok(net.network()), "172.16.0.0" .parse()); |
308 | /// |
309 | /// let net: IpNet = "fd00:1234:5678::/24" .parse().unwrap(); |
310 | /// assert_eq!(Ok(net.network()), "fd00:1200::" .parse()); |
311 | /// ``` |
312 | pub fn network(&self) -> IpAddr { |
313 | match *self { |
314 | IpNet::V4(ref a) => IpAddr::V4(a.network()), |
315 | IpNet::V6(ref a) => IpAddr::V6(a.network()), |
316 | } |
317 | } |
318 | |
319 | /// Returns the broadcast address. |
320 | /// |
321 | /// # Examples |
322 | /// |
323 | /// ``` |
324 | /// # use std::net::IpAddr; |
325 | /// # use ipnet::IpNet; |
326 | /// # |
327 | /// let net: IpNet = "172.16.0.0/22" .parse().unwrap(); |
328 | /// assert_eq!(Ok(net.broadcast()), "172.16.3.255" .parse()); |
329 | /// |
330 | /// let net: IpNet = "fd00:1234:5678::/24" .parse().unwrap(); |
331 | /// assert_eq!(Ok(net.broadcast()), "fd00:12ff:ffff:ffff:ffff:ffff:ffff:ffff" .parse()); |
332 | /// ``` |
333 | pub fn broadcast(&self) -> IpAddr { |
334 | match *self { |
335 | IpNet::V4(ref a) => IpAddr::V4(a.broadcast()), |
336 | IpNet::V6(ref a) => IpAddr::V6(a.broadcast()), |
337 | } |
338 | } |
339 | |
340 | /// Returns the `IpNet` that contains this one. |
341 | /// |
342 | /// # Examples |
343 | /// |
344 | /// ``` |
345 | /// # use ipnet::IpNet; |
346 | /// # |
347 | /// let n1: IpNet = "172.16.1.0/24" .parse().unwrap(); |
348 | /// let n2: IpNet = "172.16.0.0/23" .parse().unwrap(); |
349 | /// let n3: IpNet = "172.16.0.0/0" .parse().unwrap(); |
350 | /// |
351 | /// assert_eq!(n1.supernet().unwrap(), n2); |
352 | /// assert_eq!(n3.supernet(), None); |
353 | /// |
354 | /// let n1: IpNet = "fd00:ff00::/24" .parse().unwrap(); |
355 | /// let n2: IpNet = "fd00:fe00::/23" .parse().unwrap(); |
356 | /// let n3: IpNet = "fd00:fe00::/0" .parse().unwrap(); |
357 | /// |
358 | /// assert_eq!(n1.supernet().unwrap(), n2); |
359 | /// assert_eq!(n3.supernet(), None); |
360 | /// ``` |
361 | pub fn supernet(&self) -> Option<IpNet> { |
362 | match *self { |
363 | IpNet::V4(ref a) => a.supernet().map(IpNet::V4), |
364 | IpNet::V6(ref a) => a.supernet().map(IpNet::V6), |
365 | } |
366 | } |
367 | |
368 | /// Returns `true` if this network and the given network are |
369 | /// children of the same supernet. |
370 | /// |
371 | /// # Examples |
372 | /// |
373 | /// ``` |
374 | /// # use ipnet::IpNet; |
375 | /// # |
376 | /// let n4_1: IpNet = "10.1.0.0/24" .parse().unwrap(); |
377 | /// let n4_2: IpNet = "10.1.1.0/24" .parse().unwrap(); |
378 | /// let n4_3: IpNet = "10.1.2.0/24" .parse().unwrap(); |
379 | /// let n6_1: IpNet = "fd00::/18" .parse().unwrap(); |
380 | /// let n6_2: IpNet = "fd00:4000::/18" .parse().unwrap(); |
381 | /// let n6_3: IpNet = "fd00:8000::/18" .parse().unwrap(); |
382 | /// |
383 | /// assert!( n4_1.is_sibling(&n4_2)); |
384 | /// assert!(!n4_2.is_sibling(&n4_3)); |
385 | /// assert!( n6_1.is_sibling(&n6_2)); |
386 | /// assert!(!n6_2.is_sibling(&n6_3)); |
387 | /// assert!(!n4_1.is_sibling(&n6_2)); |
388 | /// ``` |
389 | pub fn is_sibling(&self, other: &IpNet) -> bool { |
390 | match (*self, *other) { |
391 | (IpNet::V4(ref a), IpNet::V4(ref b)) => a.is_sibling(b), |
392 | (IpNet::V6(ref a), IpNet::V6(ref b)) => a.is_sibling(b), |
393 | _ => false, |
394 | } |
395 | } |
396 | |
397 | /// Return an `Iterator` over the host addresses in this network. |
398 | /// |
399 | /// # Examples |
400 | /// |
401 | /// ``` |
402 | /// # use std::net::IpAddr; |
403 | /// # use ipnet::IpNet; |
404 | /// # |
405 | /// let net: IpNet = "10.0.0.0/30" .parse().unwrap(); |
406 | /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![ |
407 | /// "10.0.0.1" .parse::<IpAddr>().unwrap(), |
408 | /// "10.0.0.2" .parse().unwrap(), |
409 | /// ]); |
410 | /// |
411 | /// let net: IpNet = "10.0.0.0/31" .parse().unwrap(); |
412 | /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![ |
413 | /// "10.0.0.0" .parse::<IpAddr>().unwrap(), |
414 | /// "10.0.0.1" .parse().unwrap(), |
415 | /// ]); |
416 | /// |
417 | /// let net: IpNet = "fd00::/126" .parse().unwrap(); |
418 | /// assert_eq!(net.hosts().collect::<Vec<IpAddr>>(), vec![ |
419 | /// "fd00::" .parse::<IpAddr>().unwrap(), |
420 | /// "fd00::1" .parse().unwrap(), |
421 | /// "fd00::2" .parse().unwrap(), |
422 | /// "fd00::3" .parse().unwrap(), |
423 | /// ]); |
424 | /// ``` |
425 | pub fn hosts(&self) -> IpAddrRange { |
426 | match *self { |
427 | IpNet::V4(ref a) => IpAddrRange::V4(a.hosts()), |
428 | IpNet::V6(ref a) => IpAddrRange::V6(a.hosts()), |
429 | } |
430 | } |
431 | |
432 | /// Returns an `Iterator` over the subnets of this network with the |
433 | /// given prefix length. |
434 | /// |
435 | /// # Examples |
436 | /// |
437 | /// ``` |
438 | /// # use ipnet::{IpNet, PrefixLenError}; |
439 | /// # |
440 | /// let net: IpNet = "10.0.0.0/24" .parse().unwrap(); |
441 | /// assert_eq!(net.subnets(26).unwrap().collect::<Vec<IpNet>>(), vec![ |
442 | /// "10.0.0.0/26" .parse::<IpNet>().unwrap(), |
443 | /// "10.0.0.64/26" .parse().unwrap(), |
444 | /// "10.0.0.128/26" .parse().unwrap(), |
445 | /// "10.0.0.192/26" .parse().unwrap(), |
446 | /// ]); |
447 | /// |
448 | /// let net: IpNet = "fd00::/16" .parse().unwrap(); |
449 | /// assert_eq!(net.subnets(18).unwrap().collect::<Vec<IpNet>>(), vec![ |
450 | /// "fd00::/18" .parse::<IpNet>().unwrap(), |
451 | /// "fd00:4000::/18" .parse().unwrap(), |
452 | /// "fd00:8000::/18" .parse().unwrap(), |
453 | /// "fd00:c000::/18" .parse().unwrap(), |
454 | /// ]); |
455 | /// |
456 | /// let net: IpNet = "10.0.0.0/24" .parse().unwrap(); |
457 | /// assert_eq!(net.subnets(23), Err(PrefixLenError)); |
458 | /// |
459 | /// let net: IpNet = "10.0.0.0/24" .parse().unwrap(); |
460 | /// assert_eq!(net.subnets(33), Err(PrefixLenError)); |
461 | /// |
462 | /// let net: IpNet = "fd00::/16" .parse().unwrap(); |
463 | /// assert_eq!(net.subnets(15), Err(PrefixLenError)); |
464 | /// |
465 | /// let net: IpNet = "fd00::/16" .parse().unwrap(); |
466 | /// assert_eq!(net.subnets(129), Err(PrefixLenError)); |
467 | /// ``` |
468 | pub fn subnets(&self, new_prefix_len: u8) -> Result<IpSubnets, PrefixLenError> { |
469 | match *self { |
470 | IpNet::V4(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V4), |
471 | IpNet::V6(ref a) => a.subnets(new_prefix_len).map(IpSubnets::V6), |
472 | } |
473 | } |
474 | |
475 | /// Test if a network address contains either another network |
476 | /// address or an IP address. |
477 | /// |
478 | /// # Examples |
479 | /// |
480 | /// ``` |
481 | /// # use std::net::IpAddr; |
482 | /// # use ipnet::IpNet; |
483 | /// # |
484 | /// let net4: IpNet = "192.168.0.0/24" .parse().unwrap(); |
485 | /// let net4_yes: IpNet = "192.168.0.0/25" .parse().unwrap(); |
486 | /// let net4_no: IpNet = "192.168.0.0/23" .parse().unwrap(); |
487 | /// let ip4_yes: IpAddr = "192.168.0.1" .parse().unwrap(); |
488 | /// let ip4_no: IpAddr = "192.168.1.0" .parse().unwrap(); |
489 | /// |
490 | /// assert!(net4.contains(&net4)); |
491 | /// assert!(net4.contains(&net4_yes)); |
492 | /// assert!(!net4.contains(&net4_no)); |
493 | /// assert!(net4.contains(&ip4_yes)); |
494 | /// assert!(!net4.contains(&ip4_no)); |
495 | /// |
496 | /// |
497 | /// let net6: IpNet = "fd00::/16" .parse().unwrap(); |
498 | /// let net6_yes: IpNet = "fd00::/17" .parse().unwrap(); |
499 | /// let net6_no: IpNet = "fd00::/15" .parse().unwrap(); |
500 | /// let ip6_yes: IpAddr = "fd00::1" .parse().unwrap(); |
501 | /// let ip6_no: IpAddr = "fd01::" .parse().unwrap(); |
502 | /// |
503 | /// assert!(net6.contains(&net6)); |
504 | /// assert!(net6.contains(&net6_yes)); |
505 | /// assert!(!net6.contains(&net6_no)); |
506 | /// assert!(net6.contains(&ip6_yes)); |
507 | /// assert!(!net6.contains(&ip6_no)); |
508 | /// |
509 | /// assert!(!net4.contains(&net6)); |
510 | /// assert!(!net6.contains(&net4)); |
511 | /// assert!(!net4.contains(&ip6_no)); |
512 | /// assert!(!net6.contains(&ip4_no)); |
513 | /// ``` |
514 | pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> { |
515 | Contains::contains(self, other) |
516 | } |
517 | |
518 | /// Aggregate a `Vec` of `IpNet`s and return the result as a new |
519 | /// `Vec`. |
520 | /// |
521 | /// # Examples |
522 | /// |
523 | /// ``` |
524 | /// # use ipnet::IpNet; |
525 | /// # |
526 | /// let nets = vec![ |
527 | /// "10.0.0.0/24" .parse::<IpNet>().unwrap(), |
528 | /// "10.0.1.0/24" .parse().unwrap(), |
529 | /// "10.0.2.0/24" .parse().unwrap(), |
530 | /// "fd00::/18" .parse().unwrap(), |
531 | /// "fd00:4000::/18" .parse().unwrap(), |
532 | /// "fd00:8000::/18" .parse().unwrap(), |
533 | /// ]; |
534 | /// |
535 | /// assert_eq!(IpNet::aggregate(&nets), vec![ |
536 | /// "10.0.0.0/23" .parse::<IpNet>().unwrap(), |
537 | /// "10.0.2.0/24" .parse().unwrap(), |
538 | /// "fd00::/17" .parse().unwrap(), |
539 | /// "fd00:8000::/18" .parse().unwrap(), |
540 | /// ]); |
541 | /// ``` |
542 | pub fn aggregate(networks: &Vec<IpNet>) -> Vec<IpNet> { |
543 | // It's 2.5x faster to split the input up and run them using the |
544 | // specific IPv4 and IPV6 implementations. merge_intervals() and |
545 | // the comparisons are much faster running over integers. |
546 | let mut ipv4nets: Vec<Ipv4Net> = Vec::new(); |
547 | let mut ipv6nets: Vec<Ipv6Net> = Vec::new(); |
548 | |
549 | for n in networks { |
550 | match *n { |
551 | IpNet::V4(x) => ipv4nets.push(x), |
552 | IpNet::V6(x) => ipv6nets.push(x), |
553 | } |
554 | } |
555 | |
556 | let mut res: Vec<IpNet> = Vec::new(); |
557 | let ipv4aggs = Ipv4Net::aggregate(&ipv4nets); |
558 | let ipv6aggs = Ipv6Net::aggregate(&ipv6nets); |
559 | res.extend::<Vec<IpNet>>(ipv4aggs.into_iter().map(IpNet::V4).collect::<Vec<IpNet>>()); |
560 | res.extend::<Vec<IpNet>>(ipv6aggs.into_iter().map(IpNet::V6).collect::<Vec<IpNet>>()); |
561 | res |
562 | } |
563 | } |
564 | |
565 | impl Default for IpNet { |
566 | fn default() -> Self { |
567 | Self::V4(Ipv4Net::default()) |
568 | } |
569 | } |
570 | |
571 | impl fmt::Debug for IpNet { |
572 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
573 | fmt::Display::fmt(self, f:fmt) |
574 | } |
575 | } |
576 | |
577 | impl fmt::Display for IpNet { |
578 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
579 | match *self { |
580 | IpNet::V4(ref a: &Ipv4Net) => a.fmt(fmt), |
581 | IpNet::V6(ref a: &Ipv6Net) => a.fmt(fmt), |
582 | } |
583 | } |
584 | } |
585 | |
586 | impl From<Ipv4Net> for IpNet { |
587 | fn from(net: Ipv4Net) -> IpNet { |
588 | IpNet::V4(net) |
589 | } |
590 | } |
591 | |
592 | impl From<Ipv6Net> for IpNet { |
593 | fn from(net: Ipv6Net) -> IpNet { |
594 | IpNet::V6(net) |
595 | } |
596 | } |
597 | |
598 | impl From<IpAddr> for IpNet { |
599 | fn from(addr: IpAddr) -> IpNet { |
600 | match addr { |
601 | IpAddr::V4(a: Ipv4Addr) => IpNet::V4(a.into()), |
602 | IpAddr::V6(a: Ipv6Addr) => IpNet::V6(a.into()), |
603 | } |
604 | } |
605 | } |
606 | |
607 | impl Ipv4Net { |
608 | /// Creates a new IPv4 network address from an `Ipv4Addr` and prefix |
609 | /// length. |
610 | /// |
611 | /// # Examples |
612 | /// |
613 | /// ``` |
614 | /// use std::net::Ipv4Addr; |
615 | /// use ipnet::{Ipv4Net, PrefixLenError}; |
616 | /// |
617 | /// let net = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 24); |
618 | /// assert!(net.is_ok()); |
619 | /// |
620 | /// let bad_prefix_len = Ipv4Net::new(Ipv4Addr::new(10, 1, 1, 0), 33); |
621 | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
622 | /// ``` |
623 | #[inline ] |
624 | pub const fn new(ip: Ipv4Addr, prefix_len: u8) -> Result<Ipv4Net, PrefixLenError> { |
625 | if prefix_len > 32 { |
626 | return Err(PrefixLenError); |
627 | } |
628 | Ok(Ipv4Net { addr: ip, prefix_len: prefix_len }) |
629 | } |
630 | |
631 | /// Creates a new IPv4 network address from an `Ipv4Addr` and prefix |
632 | /// length. If called from a const context it will verify prefix length |
633 | /// at compile time. Otherwise it will panic at runtime if prefix length |
634 | /// is not less then or equal to 32. |
635 | /// |
636 | /// # Examples |
637 | /// |
638 | /// ``` |
639 | /// use std::net::Ipv4Addr; |
640 | /// use ipnet::{Ipv4Net}; |
641 | /// |
642 | /// // This code is verified at compile time: |
643 | /// const NET: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 1, 0), 24); |
644 | /// assert_eq!(NET.prefix_len(), 24); |
645 | /// |
646 | /// // This code is verified at runtime: |
647 | /// let net = Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 1, 0), 24); |
648 | /// assert_eq!(NET.prefix_len(), 24); |
649 | /// |
650 | /// // This code does not compile: |
651 | /// // const BAD_PREFIX_LEN: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 1, 0), 33); |
652 | /// |
653 | /// // This code panics at runtime: |
654 | /// // let bad_prefix_len = Ipv4Net::new_assert(Ipv4Addr::new(10, 1, 1, 0), 33); |
655 | /// ``` |
656 | #[inline ] |
657 | pub const fn new_assert(ip: Ipv4Addr, prefix_len: u8) -> Ipv4Net { |
658 | assert!(prefix_len <= 32, "PREFIX_LEN must be less then or equal to 32 for Ipv4Net" ); |
659 | Ipv4Net { addr: ip, prefix_len: prefix_len } |
660 | } |
661 | |
662 | /// Creates a new IPv4 network address from an `Ipv4Addr` and netmask. |
663 | /// |
664 | /// # Examples |
665 | /// |
666 | /// ``` |
667 | /// use std::net::Ipv4Addr; |
668 | /// use ipnet::{Ipv4Net, PrefixLenError}; |
669 | /// |
670 | /// let net = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 255, 0)); |
671 | /// assert!(net.is_ok()); |
672 | /// |
673 | /// let bad_prefix_len = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 0, 1)); |
674 | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
675 | /// ``` |
676 | pub fn with_netmask(ip: Ipv4Addr, netmask: Ipv4Addr) -> Result<Ipv4Net, PrefixLenError> { |
677 | let prefix = ipv4_mask_to_prefix(netmask)?; |
678 | Self::new(ip, prefix) |
679 | } |
680 | |
681 | /// Returns a copy of the network with the address truncated to the |
682 | /// prefix length. |
683 | /// |
684 | /// # Examples |
685 | /// |
686 | /// ``` |
687 | /// # use ipnet::Ipv4Net; |
688 | /// # |
689 | /// assert_eq!( |
690 | /// "192.168.12.34/16" .parse::<Ipv4Net>().unwrap().trunc(), |
691 | /// "192.168.0.0/16" .parse().unwrap() |
692 | /// ); |
693 | /// ``` |
694 | pub fn trunc(&self) -> Ipv4Net { |
695 | Ipv4Net::new(self.network(), self.prefix_len).unwrap() |
696 | } |
697 | |
698 | /// Returns the address. |
699 | #[inline ] |
700 | pub const fn addr(&self) -> Ipv4Addr { |
701 | self.addr |
702 | } |
703 | |
704 | /// Returns the prefix length. |
705 | #[inline ] |
706 | pub const fn prefix_len(&self) -> u8 { |
707 | self.prefix_len |
708 | } |
709 | |
710 | /// Returns the maximum valid prefix length. |
711 | #[inline ] |
712 | pub const fn max_prefix_len(&self) -> u8 { |
713 | 32 |
714 | } |
715 | |
716 | /// Returns the network mask. |
717 | /// |
718 | /// # Examples |
719 | /// |
720 | /// ``` |
721 | /// # use std::net::Ipv4Addr; |
722 | /// # use ipnet::Ipv4Net; |
723 | /// # |
724 | /// let net: Ipv4Net = "10.1.0.0/20" .parse().unwrap(); |
725 | /// assert_eq!(Ok(net.netmask()), "255.255.240.0" .parse()); |
726 | /// ``` |
727 | pub fn netmask(&self) -> Ipv4Addr { |
728 | Ipv4Addr::from(self.netmask_u32()) |
729 | } |
730 | |
731 | fn netmask_u32(&self) -> u32 { |
732 | u32::max_value().checked_shl(32 - self.prefix_len as u32).unwrap_or(0) |
733 | } |
734 | |
735 | /// Returns the host mask. |
736 | /// |
737 | /// # Examples |
738 | /// |
739 | /// ``` |
740 | /// # use std::net::Ipv4Addr; |
741 | /// # use ipnet::Ipv4Net; |
742 | /// # |
743 | /// let net: Ipv4Net = "10.1.0.0/20" .parse().unwrap(); |
744 | /// assert_eq!(Ok(net.hostmask()), "0.0.15.255" .parse()); |
745 | /// ``` |
746 | pub fn hostmask(&self) -> Ipv4Addr { |
747 | Ipv4Addr::from(self.hostmask_u32()) |
748 | } |
749 | |
750 | fn hostmask_u32(&self) -> u32 { |
751 | u32::max_value().checked_shr(self.prefix_len as u32).unwrap_or(0) |
752 | } |
753 | |
754 | /// Returns the network address. |
755 | /// |
756 | /// # Examples |
757 | /// |
758 | /// ``` |
759 | /// # use std::net::Ipv4Addr; |
760 | /// # use ipnet::Ipv4Net; |
761 | /// # |
762 | /// let net: Ipv4Net = "172.16.123.123/16" .parse().unwrap(); |
763 | /// assert_eq!(Ok(net.network()), "172.16.0.0" .parse()); |
764 | /// ``` |
765 | pub fn network(&self) -> Ipv4Addr { |
766 | Ipv4Addr::from(u32::from(self.addr) & self.netmask_u32()) |
767 | } |
768 | |
769 | /// Returns the broadcast address. |
770 | /// |
771 | /// # Examples |
772 | /// |
773 | /// ``` |
774 | /// # use std::net::Ipv4Addr; |
775 | /// # use ipnet::Ipv4Net; |
776 | /// # |
777 | /// let net: Ipv4Net = "172.16.0.0/22" .parse().unwrap(); |
778 | /// assert_eq!(Ok(net.broadcast()), "172.16.3.255" .parse()); |
779 | /// ``` |
780 | pub fn broadcast(&self) -> Ipv4Addr { |
781 | Ipv4Addr::from(u32::from(self.addr) | self.hostmask_u32()) |
782 | } |
783 | |
784 | /// Returns the `Ipv4Net` that contains this one. |
785 | /// |
786 | /// # Examples |
787 | /// |
788 | /// ``` |
789 | /// # use ipnet::Ipv4Net; |
790 | /// # |
791 | /// let n1: Ipv4Net = "172.16.1.0/24" .parse().unwrap(); |
792 | /// let n2: Ipv4Net = "172.16.0.0/23" .parse().unwrap(); |
793 | /// let n3: Ipv4Net = "172.16.0.0/0" .parse().unwrap(); |
794 | /// |
795 | /// assert_eq!(n1.supernet().unwrap(), n2); |
796 | /// assert_eq!(n3.supernet(), None); |
797 | /// ``` |
798 | pub fn supernet(&self) -> Option<Ipv4Net> { |
799 | Ipv4Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok() |
800 | } |
801 | |
802 | /// Returns `true` if this network and the given network are |
803 | /// children of the same supernet. |
804 | /// |
805 | /// # Examples |
806 | /// |
807 | /// ``` |
808 | /// # use ipnet::Ipv4Net; |
809 | /// # |
810 | /// let n1: Ipv4Net = "10.1.0.0/24" .parse().unwrap(); |
811 | /// let n2: Ipv4Net = "10.1.1.0/24" .parse().unwrap(); |
812 | /// let n3: Ipv4Net = "10.1.2.0/24" .parse().unwrap(); |
813 | /// |
814 | /// assert!(n1.is_sibling(&n2)); |
815 | /// assert!(!n2.is_sibling(&n3)); |
816 | /// ``` |
817 | pub fn is_sibling(&self, other: &Ipv4Net) -> bool { |
818 | self.prefix_len > 0 && |
819 | self.prefix_len == other.prefix_len && |
820 | self.supernet().unwrap().contains(other) |
821 | } |
822 | |
823 | /// Return an `Iterator` over the host addresses in this network. |
824 | /// |
825 | /// If the prefix length is less than 31 both the network address |
826 | /// and broadcast address are excluded. These are only valid host |
827 | /// addresses when the prefix length is 31. |
828 | /// |
829 | /// # Examples |
830 | /// |
831 | /// ``` |
832 | /// # use std::net::Ipv4Addr; |
833 | /// # use ipnet::Ipv4Net; |
834 | /// # |
835 | /// let net: Ipv4Net = "10.0.0.0/30" .parse().unwrap(); |
836 | /// assert_eq!(net.hosts().collect::<Vec<Ipv4Addr>>(), vec![ |
837 | /// "10.0.0.1" .parse::<Ipv4Addr>().unwrap(), |
838 | /// "10.0.0.2" .parse().unwrap(), |
839 | /// ]); |
840 | /// |
841 | /// let net: Ipv4Net = "10.0.0.0/31" .parse().unwrap(); |
842 | /// assert_eq!(net.hosts().collect::<Vec<Ipv4Addr>>(), vec![ |
843 | /// "10.0.0.0" .parse::<Ipv4Addr>().unwrap(), |
844 | /// "10.0.0.1" .parse().unwrap(), |
845 | /// ]); |
846 | /// ``` |
847 | pub fn hosts(&self) -> Ipv4AddrRange { |
848 | let mut start = self.network(); |
849 | let mut end = self.broadcast(); |
850 | |
851 | if self.prefix_len < 31 { |
852 | start = start.saturating_add(1); |
853 | end = end.saturating_sub(1); |
854 | } |
855 | |
856 | Ipv4AddrRange::new(start, end) |
857 | } |
858 | |
859 | /// Returns an `Iterator` over the subnets of this network with the |
860 | /// given prefix length. |
861 | /// |
862 | /// # Examples |
863 | /// |
864 | /// ``` |
865 | /// # use ipnet::{Ipv4Net, PrefixLenError}; |
866 | /// # |
867 | /// let net: Ipv4Net = "10.0.0.0/24" .parse().unwrap(); |
868 | /// assert_eq!(net.subnets(26).unwrap().collect::<Vec<Ipv4Net>>(), vec![ |
869 | /// "10.0.0.0/26" .parse::<Ipv4Net>().unwrap(), |
870 | /// "10.0.0.64/26" .parse().unwrap(), |
871 | /// "10.0.0.128/26" .parse().unwrap(), |
872 | /// "10.0.0.192/26" .parse().unwrap(), |
873 | /// ]); |
874 | /// |
875 | /// let net: Ipv4Net = "10.0.0.0/30" .parse().unwrap(); |
876 | /// assert_eq!(net.subnets(32).unwrap().collect::<Vec<Ipv4Net>>(), vec![ |
877 | /// "10.0.0.0/32" .parse::<Ipv4Net>().unwrap(), |
878 | /// "10.0.0.1/32" .parse().unwrap(), |
879 | /// "10.0.0.2/32" .parse().unwrap(), |
880 | /// "10.0.0.3/32" .parse().unwrap(), |
881 | /// ]); |
882 | /// |
883 | /// let net: Ipv4Net = "10.0.0.0/24" .parse().unwrap(); |
884 | /// assert_eq!(net.subnets(23), Err(PrefixLenError)); |
885 | /// |
886 | /// let net: Ipv4Net = "10.0.0.0/24" .parse().unwrap(); |
887 | /// assert_eq!(net.subnets(33), Err(PrefixLenError)); |
888 | /// ``` |
889 | pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv4Subnets, PrefixLenError> { |
890 | if self.prefix_len > new_prefix_len || new_prefix_len > 32 { |
891 | return Err(PrefixLenError); |
892 | } |
893 | |
894 | Ok(Ipv4Subnets::new( |
895 | self.network(), |
896 | self.broadcast(), |
897 | new_prefix_len, |
898 | )) |
899 | } |
900 | |
901 | /// Test if a network address contains either another network |
902 | /// address or an IP address. |
903 | /// |
904 | /// # Examples |
905 | /// |
906 | /// ``` |
907 | /// # use std::net::Ipv4Addr; |
908 | /// # use ipnet::Ipv4Net; |
909 | /// # |
910 | /// let net: Ipv4Net = "192.168.0.0/24" .parse().unwrap(); |
911 | /// let net_yes: Ipv4Net = "192.168.0.0/25" .parse().unwrap(); |
912 | /// let net_no: Ipv4Net = "192.168.0.0/23" .parse().unwrap(); |
913 | /// let ip_yes: Ipv4Addr = "192.168.0.1" .parse().unwrap(); |
914 | /// let ip_no: Ipv4Addr = "192.168.1.0" .parse().unwrap(); |
915 | /// |
916 | /// assert!(net.contains(&net)); |
917 | /// assert!(net.contains(&net_yes)); |
918 | /// assert!(!net.contains(&net_no)); |
919 | /// assert!(net.contains(&ip_yes)); |
920 | /// assert!(!net.contains(&ip_no)); |
921 | /// ``` |
922 | pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> { |
923 | Contains::contains(self, other) |
924 | } |
925 | |
926 | // It is significantly faster to work on u32 than Ipv4Addr. |
927 | fn interval(&self) -> (u32, u32) { |
928 | ( |
929 | u32::from(self.network()), |
930 | u32::from(self.broadcast()).saturating_add(1), |
931 | ) |
932 | } |
933 | |
934 | /// Aggregate a `Vec` of `Ipv4Net`s and return the result as a new |
935 | /// `Vec`. |
936 | /// |
937 | /// # Examples |
938 | /// |
939 | /// ``` |
940 | /// # use ipnet::Ipv4Net; |
941 | /// # |
942 | /// let nets = vec![ |
943 | /// "10.0.0.0/24" .parse::<Ipv4Net>().unwrap(), |
944 | /// "10.0.1.0/24" .parse().unwrap(), |
945 | /// "10.0.2.0/24" .parse().unwrap(), |
946 | /// ]; |
947 | /// |
948 | /// assert_eq!(Ipv4Net::aggregate(&nets), vec![ |
949 | /// "10.0.0.0/23" .parse::<Ipv4Net>().unwrap(), |
950 | /// "10.0.2.0/24" .parse().unwrap(), |
951 | /// ]); |
952 | pub fn aggregate(networks: &Vec<Ipv4Net>) -> Vec<Ipv4Net> { |
953 | let mut intervals: Vec<(_, _)> = networks.iter().map(|n| n.interval()).collect(); |
954 | intervals = merge_intervals(intervals); |
955 | let mut res: Vec<Ipv4Net> = Vec::new(); |
956 | |
957 | for (start, mut end) in intervals { |
958 | if end != core::u32::MAX { |
959 | end = end.saturating_sub(1) |
960 | } |
961 | let iter = Ipv4Subnets::new(start.into(), end.into(), 0); |
962 | res.extend(iter); |
963 | } |
964 | res |
965 | } |
966 | } |
967 | |
968 | impl Default for Ipv4Net { |
969 | fn default() -> Self { |
970 | Self { |
971 | addr: Ipv4Addr::from(0), |
972 | prefix_len: 0, |
973 | } |
974 | } |
975 | } |
976 | |
977 | impl fmt::Debug for Ipv4Net { |
978 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
979 | fmt::Display::fmt(self, f:fmt) |
980 | } |
981 | } |
982 | |
983 | impl fmt::Display for Ipv4Net { |
984 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
985 | write!(fmt, " {}/ {}" , self.addr, self.prefix_len) |
986 | } |
987 | } |
988 | |
989 | impl From<Ipv4Addr> for Ipv4Net { |
990 | fn from(addr: Ipv4Addr) -> Ipv4Net { |
991 | Ipv4Net { addr, prefix_len: 32 } |
992 | } |
993 | } |
994 | |
995 | impl Ipv6Net { |
996 | /// Creates a new IPv6 network address from an `Ipv6Addr` and prefix |
997 | /// length. |
998 | /// |
999 | /// # Examples |
1000 | /// |
1001 | /// ``` |
1002 | /// use std::net::Ipv6Addr; |
1003 | /// use ipnet::{Ipv6Net, PrefixLenError}; |
1004 | /// |
1005 | /// let net = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24); |
1006 | /// assert!(net.is_ok()); |
1007 | /// |
1008 | /// let bad_prefix_len = Ipv6Net::new(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 129); |
1009 | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
1010 | /// ``` |
1011 | #[inline ] |
1012 | pub const fn new(ip: Ipv6Addr, prefix_len: u8) -> Result<Ipv6Net, PrefixLenError> { |
1013 | if prefix_len > 128 { |
1014 | return Err(PrefixLenError); |
1015 | } |
1016 | Ok(Ipv6Net { addr: ip, prefix_len: prefix_len }) |
1017 | } |
1018 | |
1019 | /// Creates a new IPv6 network address from an `Ipv6Addr` and prefix |
1020 | /// length. If called from a const context it will verify prefix length |
1021 | /// at compile time. Otherwise it will panic at runtime if prefix length |
1022 | /// is not less then or equal to 128. |
1023 | /// |
1024 | /// # Examples |
1025 | /// |
1026 | /// ``` |
1027 | /// use std::net::Ipv6Addr; |
1028 | /// use ipnet::{Ipv6Net}; |
1029 | /// |
1030 | /// // This code is verified at compile time: |
1031 | /// const NET: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24); |
1032 | /// assert_eq!(NET.prefix_len(), 24); |
1033 | /// |
1034 | /// // This code is verified at runtime: |
1035 | /// let net = Ipv6Net::new_assert(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 24); |
1036 | /// assert_eq!(net.prefix_len(), 24); |
1037 | /// |
1038 | /// // This code does not compile: |
1039 | /// // const BAD_PREFIX_LEN: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 129); |
1040 | /// |
1041 | /// // This code panics at runtime: |
1042 | /// // let bad_prefix_len = Ipv6Addr::new_assert(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), 129); |
1043 | /// ``` |
1044 | #[inline ] |
1045 | pub const fn new_assert(ip: Ipv6Addr, prefix_len: u8) -> Ipv6Net { |
1046 | assert!(prefix_len <= 128, "PREFIX_LEN must be less then or equal to 128 for Ipv6Net" ); |
1047 | Ipv6Net { addr: ip, prefix_len: prefix_len } |
1048 | } |
1049 | |
1050 | /// Creates a new IPv6 network address from an `Ipv6Addr` and netmask. |
1051 | /// |
1052 | /// # Examples |
1053 | /// |
1054 | /// ``` |
1055 | /// use std::net::Ipv6Addr; |
1056 | /// use ipnet::{Ipv6Net, PrefixLenError}; |
1057 | /// |
1058 | /// let net = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0000_0000_0000_0000)); |
1059 | /// assert!(net.is_ok()); |
1060 | /// |
1061 | /// let bad_prefix_len = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0001_0000_0000_0000)); |
1062 | /// assert_eq!(bad_prefix_len, Err(PrefixLenError)); |
1063 | /// ``` |
1064 | pub fn with_netmask(ip: Ipv6Addr, netmask: Ipv6Addr) -> Result<Ipv6Net, PrefixLenError> { |
1065 | let prefix = ipv6_mask_to_prefix(netmask)?; |
1066 | Self::new(ip, prefix) |
1067 | } |
1068 | |
1069 | /// Returns a copy of the network with the address truncated to the |
1070 | /// prefix length. |
1071 | /// |
1072 | /// # Examples |
1073 | /// |
1074 | /// ``` |
1075 | /// # use ipnet::Ipv6Net; |
1076 | /// # |
1077 | /// assert_eq!( |
1078 | /// "fd00::1:2:3:4/16" .parse::<Ipv6Net>().unwrap().trunc(), |
1079 | /// "fd00::/16" .parse().unwrap() |
1080 | /// ); |
1081 | /// ``` |
1082 | pub fn trunc(&self) -> Ipv6Net { |
1083 | Ipv6Net::new(self.network(), self.prefix_len).unwrap() |
1084 | } |
1085 | |
1086 | /// Returns the address. |
1087 | #[inline ] |
1088 | pub const fn addr(&self) -> Ipv6Addr { |
1089 | self.addr |
1090 | } |
1091 | |
1092 | /// Returns the prefix length. |
1093 | #[inline ] |
1094 | pub const fn prefix_len(&self) -> u8 { |
1095 | self.prefix_len |
1096 | } |
1097 | |
1098 | /// Returns the maximum valid prefix length. |
1099 | #[inline ] |
1100 | pub const fn max_prefix_len(&self) -> u8 { |
1101 | 128 |
1102 | } |
1103 | |
1104 | /// Returns the network mask. |
1105 | /// |
1106 | /// # Examples |
1107 | /// |
1108 | /// ``` |
1109 | /// # use std::net::Ipv6Addr; |
1110 | /// # use ipnet::Ipv6Net; |
1111 | /// # |
1112 | /// let net: Ipv6Net = "fd00::/24" .parse().unwrap(); |
1113 | /// assert_eq!(Ok(net.netmask()), "ffff:ff00::" .parse()); |
1114 | /// ``` |
1115 | pub fn netmask(&self) -> Ipv6Addr { |
1116 | self.netmask_u128().into() |
1117 | } |
1118 | |
1119 | fn netmask_u128(&self) -> u128 { |
1120 | u128::max_value().checked_shl((128 - self.prefix_len) as u32).unwrap_or(u128::min_value()) |
1121 | } |
1122 | |
1123 | /// Returns the host mask. |
1124 | /// |
1125 | /// # Examples |
1126 | /// |
1127 | /// ``` |
1128 | /// # use std::net::Ipv6Addr; |
1129 | /// # use ipnet::Ipv6Net; |
1130 | /// # |
1131 | /// let net: Ipv6Net = "fd00::/24" .parse().unwrap(); |
1132 | /// assert_eq!(Ok(net.hostmask()), "::ff:ffff:ffff:ffff:ffff:ffff:ffff" .parse()); |
1133 | /// ``` |
1134 | pub fn hostmask(&self) -> Ipv6Addr { |
1135 | self.hostmask_u128().into() |
1136 | } |
1137 | |
1138 | fn hostmask_u128(&self) -> u128 { |
1139 | u128::max_value().checked_shr(self.prefix_len as u32).unwrap_or(u128::min_value()) |
1140 | } |
1141 | |
1142 | /// Returns the network address. |
1143 | /// |
1144 | /// # Examples |
1145 | /// |
1146 | /// ``` |
1147 | /// # use std::net::Ipv6Addr; |
1148 | /// # use ipnet::Ipv6Net; |
1149 | /// # |
1150 | /// let net: Ipv6Net = "fd00:1234:5678::/24" .parse().unwrap(); |
1151 | /// assert_eq!(Ok(net.network()), "fd00:1200::" .parse()); |
1152 | /// ``` |
1153 | pub fn network(&self) -> Ipv6Addr { |
1154 | (u128::from(self.addr) & self.netmask_u128()).into() |
1155 | } |
1156 | |
1157 | /// Returns the last address. |
1158 | /// |
1159 | /// Technically there is no such thing as a broadcast address for |
1160 | /// IPv6. The name is used for consistency with colloquial usage. |
1161 | /// |
1162 | /// # Examples |
1163 | /// |
1164 | /// ``` |
1165 | /// # use std::net::Ipv6Addr; |
1166 | /// # use ipnet::Ipv6Net; |
1167 | /// # |
1168 | /// let net: Ipv6Net = "fd00:1234:5678::/24" .parse().unwrap(); |
1169 | /// assert_eq!(Ok(net.broadcast()), "fd00:12ff:ffff:ffff:ffff:ffff:ffff:ffff" .parse()); |
1170 | /// ``` |
1171 | pub fn broadcast(&self) -> Ipv6Addr { |
1172 | (u128::from(self.addr) | self.hostmask_u128()).into() |
1173 | } |
1174 | |
1175 | /// Returns the `Ipv6Net` that contains this one. |
1176 | /// |
1177 | /// # Examples |
1178 | /// |
1179 | /// ``` |
1180 | /// # use std::str::FromStr; |
1181 | /// # use ipnet::Ipv6Net; |
1182 | /// # |
1183 | /// let n1: Ipv6Net = "fd00:ff00::/24" .parse().unwrap(); |
1184 | /// let n2: Ipv6Net = "fd00:fe00::/23" .parse().unwrap(); |
1185 | /// let n3: Ipv6Net = "fd00:fe00::/0" .parse().unwrap(); |
1186 | /// |
1187 | /// assert_eq!(n1.supernet().unwrap(), n2); |
1188 | /// assert_eq!(n3.supernet(), None); |
1189 | /// ``` |
1190 | pub fn supernet(&self) -> Option<Ipv6Net> { |
1191 | Ipv6Net::new(self.addr, self.prefix_len.wrapping_sub(1)).map(|n| n.trunc()).ok() |
1192 | } |
1193 | |
1194 | /// Returns `true` if this network and the given network are |
1195 | /// children of the same supernet. |
1196 | /// |
1197 | /// # Examples |
1198 | /// |
1199 | /// ``` |
1200 | /// # use ipnet::Ipv6Net; |
1201 | /// # |
1202 | /// let n1: Ipv6Net = "fd00::/18" .parse().unwrap(); |
1203 | /// let n2: Ipv6Net = "fd00:4000::/18" .parse().unwrap(); |
1204 | /// let n3: Ipv6Net = "fd00:8000::/18" .parse().unwrap(); |
1205 | /// |
1206 | /// assert!(n1.is_sibling(&n2)); |
1207 | /// assert!(!n2.is_sibling(&n3)); |
1208 | /// ``` |
1209 | pub fn is_sibling(&self, other: &Ipv6Net) -> bool { |
1210 | self.prefix_len > 0 && |
1211 | self.prefix_len == other.prefix_len && |
1212 | self.supernet().unwrap().contains(other) |
1213 | } |
1214 | |
1215 | /// Return an `Iterator` over the host addresses in this network. |
1216 | /// |
1217 | /// # Examples |
1218 | /// |
1219 | /// ``` |
1220 | /// # use std::net::Ipv6Addr; |
1221 | /// # use ipnet::Ipv6Net; |
1222 | /// # |
1223 | /// let net: Ipv6Net = "fd00::/126" .parse().unwrap(); |
1224 | /// assert_eq!(net.hosts().collect::<Vec<Ipv6Addr>>(), vec![ |
1225 | /// "fd00::" .parse::<Ipv6Addr>().unwrap(), |
1226 | /// "fd00::1" .parse().unwrap(), |
1227 | /// "fd00::2" .parse().unwrap(), |
1228 | /// "fd00::3" .parse().unwrap(), |
1229 | /// ]); |
1230 | /// ``` |
1231 | pub fn hosts(&self) -> Ipv6AddrRange { |
1232 | Ipv6AddrRange::new(self.network(), self.broadcast()) |
1233 | } |
1234 | |
1235 | /// Returns an `Iterator` over the subnets of this network with the |
1236 | /// given prefix length. |
1237 | /// |
1238 | /// # Examples |
1239 | /// |
1240 | /// ``` |
1241 | /// # use ipnet::{Ipv6Net, PrefixLenError}; |
1242 | /// # |
1243 | /// let net: Ipv6Net = "fd00::/16" .parse().unwrap(); |
1244 | /// assert_eq!(net.subnets(18).unwrap().collect::<Vec<Ipv6Net>>(), vec![ |
1245 | /// "fd00::/18" .parse::<Ipv6Net>().unwrap(), |
1246 | /// "fd00:4000::/18" .parse().unwrap(), |
1247 | /// "fd00:8000::/18" .parse().unwrap(), |
1248 | /// "fd00:c000::/18" .parse().unwrap(), |
1249 | /// ]); |
1250 | /// |
1251 | /// let net: Ipv6Net = "fd00::/126" .parse().unwrap(); |
1252 | /// assert_eq!(net.subnets(128).unwrap().collect::<Vec<Ipv6Net>>(), vec![ |
1253 | /// "fd00::/128" .parse::<Ipv6Net>().unwrap(), |
1254 | /// "fd00::1/128" .parse().unwrap(), |
1255 | /// "fd00::2/128" .parse().unwrap(), |
1256 | /// "fd00::3/128" .parse().unwrap(), |
1257 | /// ]); |
1258 | /// |
1259 | /// let net: Ipv6Net = "fd00::/16" .parse().unwrap(); |
1260 | /// assert_eq!(net.subnets(15), Err(PrefixLenError)); |
1261 | /// |
1262 | /// let net: Ipv6Net = "fd00::/16" .parse().unwrap(); |
1263 | /// assert_eq!(net.subnets(129), Err(PrefixLenError)); |
1264 | /// ``` |
1265 | pub fn subnets(&self, new_prefix_len: u8) -> Result<Ipv6Subnets, PrefixLenError> { |
1266 | if self.prefix_len > new_prefix_len || new_prefix_len > 128 { |
1267 | return Err(PrefixLenError); |
1268 | } |
1269 | |
1270 | Ok(Ipv6Subnets::new( |
1271 | self.network(), |
1272 | self.broadcast(), |
1273 | new_prefix_len, |
1274 | )) |
1275 | } |
1276 | |
1277 | /// Test if a network address contains either another network |
1278 | /// address or an IP address. |
1279 | /// |
1280 | /// # Examples |
1281 | /// |
1282 | /// ``` |
1283 | /// # use std::net::Ipv6Addr; |
1284 | /// # use ipnet::Ipv6Net; |
1285 | /// # |
1286 | /// let net: Ipv6Net = "fd00::/16" .parse().unwrap(); |
1287 | /// let net_yes: Ipv6Net = "fd00::/17" .parse().unwrap(); |
1288 | /// let net_no: Ipv6Net = "fd00::/15" .parse().unwrap(); |
1289 | /// let ip_yes: Ipv6Addr = "fd00::1" .parse().unwrap(); |
1290 | /// let ip_no: Ipv6Addr = "fd01::" .parse().unwrap(); |
1291 | /// |
1292 | /// assert!(net.contains(&net)); |
1293 | /// assert!(net.contains(&net_yes)); |
1294 | /// assert!(!net.contains(&net_no)); |
1295 | /// assert!(net.contains(&ip_yes)); |
1296 | /// assert!(!net.contains(&ip_no)); |
1297 | /// ``` |
1298 | pub fn contains<T>(&self, other: T) -> bool where Self: Contains<T> { |
1299 | Contains::contains(self, other) |
1300 | } |
1301 | |
1302 | // It is significantly faster to work on u128 that Ipv6Addr. |
1303 | fn interval(&self) -> (u128, u128) { |
1304 | ( |
1305 | u128::from(self.network()), |
1306 | u128::from(self.broadcast()).saturating_add(1), |
1307 | ) |
1308 | } |
1309 | |
1310 | /// Aggregate a `Vec` of `Ipv6Net`s and return the result as a new |
1311 | /// `Vec`. |
1312 | /// |
1313 | /// # Examples |
1314 | /// |
1315 | /// ``` |
1316 | /// # use ipnet::Ipv6Net; |
1317 | /// # |
1318 | /// let nets = vec![ |
1319 | /// "fd00::/18" .parse::<Ipv6Net>().unwrap(), |
1320 | /// "fd00:4000::/18" .parse().unwrap(), |
1321 | /// "fd00:8000::/18" .parse().unwrap(), |
1322 | /// ]; |
1323 | /// assert_eq!(Ipv6Net::aggregate(&nets), vec![ |
1324 | /// "fd00::/17" .parse::<Ipv6Net>().unwrap(), |
1325 | /// "fd00:8000::/18" .parse().unwrap(), |
1326 | /// ]); |
1327 | /// ``` |
1328 | pub fn aggregate(networks: &Vec<Ipv6Net>) -> Vec<Ipv6Net> { |
1329 | let mut intervals: Vec<(_, _)> = networks.iter().map(|n| n.interval()).collect(); |
1330 | intervals = merge_intervals(intervals); |
1331 | let mut res: Vec<Ipv6Net> = Vec::new(); |
1332 | |
1333 | for (start, mut end) in intervals { |
1334 | if end != core::u128::MAX { |
1335 | end = end.saturating_sub(1) |
1336 | } |
1337 | let iter = Ipv6Subnets::new(start.into(), end.into(), 0); |
1338 | res.extend(iter); |
1339 | } |
1340 | res |
1341 | } |
1342 | } |
1343 | |
1344 | impl Default for Ipv6Net { |
1345 | fn default() -> Self { |
1346 | Self { |
1347 | addr: Ipv6Addr::from(0), |
1348 | prefix_len: 0, |
1349 | } |
1350 | } |
1351 | } |
1352 | |
1353 | impl fmt::Debug for Ipv6Net { |
1354 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
1355 | fmt::Display::fmt(self, f:fmt) |
1356 | } |
1357 | } |
1358 | |
1359 | impl fmt::Display for Ipv6Net { |
1360 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
1361 | write!(fmt, " {}/ {}" , self.addr, self.prefix_len) |
1362 | } |
1363 | } |
1364 | |
1365 | impl From<Ipv6Addr> for Ipv6Net { |
1366 | fn from(addr: Ipv6Addr) -> Ipv6Net { |
1367 | Ipv6Net { addr, prefix_len: 128 } |
1368 | } |
1369 | } |
1370 | |
1371 | /// Provides a method to test if a network address contains either |
1372 | /// another network address or an IP address. |
1373 | /// |
1374 | /// # Examples |
1375 | /// |
1376 | /// ``` |
1377 | /// # use std::net::IpAddr; |
1378 | /// # use ipnet::IpNet; |
1379 | /// # |
1380 | /// let n4_1: IpNet = "10.1.1.0/24" .parse().unwrap(); |
1381 | /// let n4_2: IpNet = "10.1.1.0/26" .parse().unwrap(); |
1382 | /// let n4_3: IpNet = "10.1.2.0/26" .parse().unwrap(); |
1383 | /// let ip4_1: IpAddr = "10.1.1.1" .parse().unwrap(); |
1384 | /// let ip4_2: IpAddr = "10.1.2.1" .parse().unwrap(); |
1385 | /// |
1386 | /// let n6_1: IpNet = "fd00::/16" .parse().unwrap(); |
1387 | /// let n6_2: IpNet = "fd00::/17" .parse().unwrap(); |
1388 | /// let n6_3: IpNet = "fd01::/17" .parse().unwrap(); |
1389 | /// let ip6_1: IpAddr = "fd00::1" .parse().unwrap(); |
1390 | /// let ip6_2: IpAddr = "fd01::1" .parse().unwrap(); |
1391 | /// |
1392 | /// assert!(n4_1.contains(&n4_2)); |
1393 | /// assert!(!n4_1.contains(&n4_3)); |
1394 | /// assert!(n4_1.contains(&ip4_1)); |
1395 | /// assert!(!n4_1.contains(&ip4_2)); |
1396 | /// |
1397 | /// assert!(n6_1.contains(&n6_2)); |
1398 | /// assert!(!n6_1.contains(&n6_3)); |
1399 | /// assert!(n6_1.contains(&ip6_1)); |
1400 | /// assert!(!n6_1.contains(&ip6_2)); |
1401 | /// |
1402 | /// assert!(!n4_1.contains(&n6_1) && !n6_1.contains(&n4_1)); |
1403 | /// assert!(!n4_1.contains(&ip6_1) && !n6_1.contains(&ip4_1)); |
1404 | /// ``` |
1405 | pub trait Contains<T> { |
1406 | fn contains(&self, other: T) -> bool; |
1407 | } |
1408 | |
1409 | impl<'a> Contains<&'a IpNet> for IpNet { |
1410 | fn contains(&self, other: &IpNet) -> bool { |
1411 | match (*self, *other) { |
1412 | (IpNet::V4(ref a: &Ipv4Net), IpNet::V4(ref b: &Ipv4Net)) => a.contains(b), |
1413 | (IpNet::V6(ref a: &Ipv6Net), IpNet::V6(ref b: &Ipv6Net)) => a.contains(b), |
1414 | _ => false, |
1415 | } |
1416 | } |
1417 | } |
1418 | |
1419 | impl<'a> Contains<&'a IpAddr> for IpNet { |
1420 | fn contains(&self, other: &IpAddr) -> bool { |
1421 | match (*self, *other) { |
1422 | (IpNet::V4(ref a: &Ipv4Net), IpAddr::V4(ref b: &Ipv4Addr)) => a.contains(b), |
1423 | (IpNet::V6(ref a: &Ipv6Net), IpAddr::V6(ref b: &Ipv6Addr)) => a.contains(b), |
1424 | _ => false, |
1425 | } |
1426 | } |
1427 | } |
1428 | |
1429 | impl<'a> Contains<&'a Ipv4Net> for Ipv4Net { |
1430 | fn contains(&self, other: &'a Ipv4Net) -> bool { |
1431 | self.network() <= other.network() && other.broadcast() <= self.broadcast() |
1432 | } |
1433 | } |
1434 | |
1435 | impl<'a> Contains<&'a Ipv4Addr> for Ipv4Net { |
1436 | fn contains(&self, other: &'a Ipv4Addr) -> bool { |
1437 | self.network() <= *other && *other <= self.broadcast() |
1438 | } |
1439 | } |
1440 | |
1441 | impl<'a> Contains<&'a Ipv6Net> for Ipv6Net { |
1442 | fn contains(&self, other: &'a Ipv6Net) -> bool { |
1443 | self.network() <= other.network() && other.broadcast() <= self.broadcast() |
1444 | } |
1445 | } |
1446 | |
1447 | impl<'a> Contains<&'a Ipv6Addr> for Ipv6Net { |
1448 | fn contains(&self, other: &'a Ipv6Addr) -> bool { |
1449 | self.network() <= *other && *other <= self.broadcast() |
1450 | } |
1451 | } |
1452 | |
1453 | /// An `Iterator` that generates IP network addresses, either IPv4 or |
1454 | /// IPv6. |
1455 | /// |
1456 | /// Generates the subnets between the provided `start` and `end` IP |
1457 | /// addresses inclusive of `end`. Each iteration generates the next |
1458 | /// network address of the largest valid size it can, while using a |
1459 | /// prefix length not less than `min_prefix_len`. |
1460 | /// |
1461 | /// # Examples |
1462 | /// |
1463 | /// ``` |
1464 | /// # use std::net::{Ipv4Addr, Ipv6Addr}; |
1465 | /// # use std::str::FromStr; |
1466 | /// # use ipnet::{IpNet, IpSubnets, Ipv4Subnets, Ipv6Subnets}; |
1467 | /// let subnets = IpSubnets::from(Ipv4Subnets::new( |
1468 | /// "10.0.0.0" .parse().unwrap(), |
1469 | /// "10.0.0.239" .parse().unwrap(), |
1470 | /// 26, |
1471 | /// )); |
1472 | /// |
1473 | /// assert_eq!(subnets.collect::<Vec<IpNet>>(), vec![ |
1474 | /// "10.0.0.0/26" .parse().unwrap(), |
1475 | /// "10.0.0.64/26" .parse().unwrap(), |
1476 | /// "10.0.0.128/26" .parse().unwrap(), |
1477 | /// "10.0.0.192/27" .parse().unwrap(), |
1478 | /// "10.0.0.224/28" .parse().unwrap(), |
1479 | /// ]); |
1480 | /// |
1481 | /// let subnets = IpSubnets::from(Ipv6Subnets::new( |
1482 | /// "fd00::" .parse().unwrap(), |
1483 | /// "fd00:ef:ffff:ffff:ffff:ffff:ffff:ffff" .parse().unwrap(), |
1484 | /// 26, |
1485 | /// )); |
1486 | /// |
1487 | /// assert_eq!(subnets.collect::<Vec<IpNet>>(), vec![ |
1488 | /// "fd00::/26" .parse().unwrap(), |
1489 | /// "fd00:40::/26" .parse().unwrap(), |
1490 | /// "fd00:80::/26" .parse().unwrap(), |
1491 | /// "fd00:c0::/27" .parse().unwrap(), |
1492 | /// "fd00:e0::/28" .parse().unwrap(), |
1493 | /// ]); |
1494 | /// ``` |
1495 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
1496 | pub enum IpSubnets { |
1497 | V4(Ipv4Subnets), |
1498 | V6(Ipv6Subnets), |
1499 | } |
1500 | |
1501 | /// An `Iterator` that generates IPv4 network addresses. |
1502 | /// |
1503 | /// Generates the subnets between the provided `start` and `end` IP |
1504 | /// addresses inclusive of `end`. Each iteration generates the next |
1505 | /// network address of the largest valid size it can, while using a |
1506 | /// prefix length not less than `min_prefix_len`. |
1507 | /// |
1508 | /// # Examples |
1509 | /// |
1510 | /// ``` |
1511 | /// # use std::net::Ipv4Addr; |
1512 | /// # use std::str::FromStr; |
1513 | /// # use ipnet::{Ipv4Net, Ipv4Subnets}; |
1514 | /// let subnets = Ipv4Subnets::new( |
1515 | /// "10.0.0.0" .parse().unwrap(), |
1516 | /// "10.0.0.239" .parse().unwrap(), |
1517 | /// 26, |
1518 | /// ); |
1519 | /// |
1520 | /// assert_eq!(subnets.collect::<Vec<Ipv4Net>>(), vec![ |
1521 | /// "10.0.0.0/26" .parse().unwrap(), |
1522 | /// "10.0.0.64/26" .parse().unwrap(), |
1523 | /// "10.0.0.128/26" .parse().unwrap(), |
1524 | /// "10.0.0.192/27" .parse().unwrap(), |
1525 | /// "10.0.0.224/28" .parse().unwrap(), |
1526 | /// ]); |
1527 | /// ``` |
1528 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
1529 | pub struct Ipv4Subnets { |
1530 | start: Ipv4Addr, |
1531 | end: Ipv4Addr, // end is inclusive |
1532 | min_prefix_len: u8, |
1533 | } |
1534 | |
1535 | /// An `Iterator` that generates IPv6 network addresses. |
1536 | /// |
1537 | /// Generates the subnets between the provided `start` and `end` IP |
1538 | /// addresses inclusive of `end`. Each iteration generates the next |
1539 | /// network address of the largest valid size it can, while using a |
1540 | /// prefix length not less than `min_prefix_len`. |
1541 | /// |
1542 | /// # Examples |
1543 | /// |
1544 | /// ``` |
1545 | /// # use std::net::Ipv6Addr; |
1546 | /// # use std::str::FromStr; |
1547 | /// # use ipnet::{Ipv6Net, Ipv6Subnets}; |
1548 | /// let subnets = Ipv6Subnets::new( |
1549 | /// "fd00::" .parse().unwrap(), |
1550 | /// "fd00:ef:ffff:ffff:ffff:ffff:ffff:ffff" .parse().unwrap(), |
1551 | /// 26, |
1552 | /// ); |
1553 | /// |
1554 | /// assert_eq!(subnets.collect::<Vec<Ipv6Net>>(), vec![ |
1555 | /// "fd00::/26" .parse().unwrap(), |
1556 | /// "fd00:40::/26" .parse().unwrap(), |
1557 | /// "fd00:80::/26" .parse().unwrap(), |
1558 | /// "fd00:c0::/27" .parse().unwrap(), |
1559 | /// "fd00:e0::/28" .parse().unwrap(), |
1560 | /// ]); |
1561 | /// ``` |
1562 | #[derive (Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] |
1563 | pub struct Ipv6Subnets { |
1564 | start: Ipv6Addr, |
1565 | end: Ipv6Addr, // end is inclusive |
1566 | min_prefix_len: u8, |
1567 | } |
1568 | |
1569 | impl Ipv4Subnets { |
1570 | pub fn new(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Self { |
1571 | Ipv4Subnets { |
1572 | start: start, |
1573 | end: end, |
1574 | min_prefix_len: min_prefix_len, |
1575 | } |
1576 | } |
1577 | } |
1578 | |
1579 | impl Ipv6Subnets { |
1580 | pub fn new(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Self { |
1581 | Ipv6Subnets { |
1582 | start: start, |
1583 | end: end, |
1584 | min_prefix_len: min_prefix_len, |
1585 | } |
1586 | } |
1587 | } |
1588 | |
1589 | impl From<Ipv4Subnets> for IpSubnets { |
1590 | fn from(i: Ipv4Subnets) -> IpSubnets { |
1591 | IpSubnets::V4(i) |
1592 | } |
1593 | } |
1594 | |
1595 | impl From<Ipv6Subnets> for IpSubnets { |
1596 | fn from(i: Ipv6Subnets) -> IpSubnets { |
1597 | IpSubnets::V6(i) |
1598 | } |
1599 | } |
1600 | |
1601 | impl Iterator for IpSubnets { |
1602 | type Item = IpNet; |
1603 | |
1604 | fn next(&mut self) -> Option<Self::Item> { |
1605 | match *self { |
1606 | IpSubnets::V4(ref mut a: &mut Ipv4Subnets) => a.next().map(IpNet::V4), |
1607 | IpSubnets::V6(ref mut a: &mut Ipv6Subnets) => a.next().map(IpNet::V6), |
1608 | } |
1609 | } |
1610 | } |
1611 | |
1612 | fn next_ipv4_subnet(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Ipv4Net { |
1613 | let range: u32 = end.saturating_sub(start).saturating_add(1); |
1614 | if range == core::u32::MAX && min_prefix_len == 0 { |
1615 | Ipv4Net::new(ip:start, min_prefix_len).unwrap() |
1616 | } |
1617 | else { |
1618 | let range_bits: u32 = 32u32.saturating_sub(range.leading_zeros()).saturating_sub(1); |
1619 | let start_tz: u32 = u32::from(start).trailing_zeros(); |
1620 | let new_prefix_len: u32 = 32 - min(v1:range_bits, v2:start_tz); |
1621 | let next_prefix_len: u8 = max(v1:new_prefix_len as u8, v2:min_prefix_len); |
1622 | Ipv4Net::new(ip:start, next_prefix_len).unwrap() |
1623 | } |
1624 | } |
1625 | |
1626 | fn next_ipv6_subnet(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Ipv6Net { |
1627 | let range: u128 = end.saturating_sub(start).saturating_add(1); |
1628 | if range == core::u128::MAX && min_prefix_len == 0 { |
1629 | Ipv6Net::new(ip:start, min_prefix_len).unwrap() |
1630 | } |
1631 | else { |
1632 | let range: u128 = end.saturating_sub(start).saturating_add(1); |
1633 | let range_bits: u32 = 128u32.saturating_sub(range.leading_zeros()).saturating_sub(1); |
1634 | let start_tz: u32 = u128::from(start).trailing_zeros(); |
1635 | let new_prefix_len: u32 = 128 - min(v1:range_bits, v2:start_tz); |
1636 | let next_prefix_len: u8 = max(v1:new_prefix_len as u8, v2:min_prefix_len); |
1637 | Ipv6Net::new(ip:start, next_prefix_len).unwrap() |
1638 | } |
1639 | } |
1640 | |
1641 | impl Iterator for Ipv4Subnets { |
1642 | type Item = Ipv4Net; |
1643 | |
1644 | fn next(&mut self) -> Option<Self::Item> { |
1645 | match self.start.partial_cmp(&self.end) { |
1646 | Some(Less) => { |
1647 | let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len); |
1648 | self.start = next.broadcast().saturating_add(1); |
1649 | |
1650 | // Stop the iterator if we saturated self.start. This |
1651 | // check worsens performance slightly but overall this |
1652 | // approach of operating on Ipv4Addr types is faster |
1653 | // than what we were doing before using Ipv4Net. |
1654 | if self.start == next.broadcast() { |
1655 | self.end.replace_zero(); |
1656 | } |
1657 | Some(next) |
1658 | }, |
1659 | Some(Equal) => { |
1660 | let next = next_ipv4_subnet(self.start, self.end, self.min_prefix_len); |
1661 | self.start = next.broadcast().saturating_add(1); |
1662 | self.end.replace_zero(); |
1663 | Some(next) |
1664 | }, |
1665 | _ => None, |
1666 | } |
1667 | } |
1668 | } |
1669 | |
1670 | impl Iterator for Ipv6Subnets { |
1671 | type Item = Ipv6Net; |
1672 | |
1673 | fn next(&mut self) -> Option<Self::Item> { |
1674 | match self.start.partial_cmp(&self.end) { |
1675 | Some(Less) => { |
1676 | let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len); |
1677 | self.start = next.broadcast().saturating_add(1); |
1678 | |
1679 | // Stop the iterator if we saturated self.start. This |
1680 | // check worsens performance slightly but overall this |
1681 | // approach of operating on Ipv6Addr types is faster |
1682 | // than what we were doing before using Ipv6Net. |
1683 | if self.start == next.broadcast() { |
1684 | self.end.replace_zero(); |
1685 | } |
1686 | Some(next) |
1687 | }, |
1688 | Some(Equal) => { |
1689 | let next = next_ipv6_subnet(self.start, self.end, self.min_prefix_len); |
1690 | self.start = next.broadcast().saturating_add(1); |
1691 | self.end.replace_zero(); |
1692 | Some(next) |
1693 | }, |
1694 | _ => None, |
1695 | } |
1696 | } |
1697 | } |
1698 | |
1699 | impl FusedIterator for IpSubnets {} |
1700 | impl FusedIterator for Ipv4Subnets {} |
1701 | impl FusedIterator for Ipv6Subnets {} |
1702 | |
1703 | // Generic function for merging a vector of intervals. |
1704 | fn merge_intervals<T: Copy + Ord>(mut intervals: Vec<(T, T)>) -> Vec<(T, T)> { |
1705 | if intervals.len() == 0 { |
1706 | return intervals; |
1707 | } |
1708 | |
1709 | intervals.sort(); |
1710 | let mut res: Vec<(T, T)> = Vec::new(); |
1711 | let (mut start, mut end) = intervals[0]; |
1712 | |
1713 | let mut i = 1; |
1714 | let len = intervals.len(); |
1715 | while i < len { |
1716 | let (next_start, next_end) = intervals[i]; |
1717 | if end >= next_start { |
1718 | start = min(start, next_start); |
1719 | end = max(end, next_end); |
1720 | } |
1721 | else { |
1722 | res.push((start, end)); |
1723 | start = next_start; |
1724 | end = next_end; |
1725 | } |
1726 | i += 1; |
1727 | } |
1728 | |
1729 | res.push((start, end)); |
1730 | res |
1731 | } |
1732 | |
1733 | #[cfg (test)] |
1734 | mod tests { |
1735 | use super::*; |
1736 | |
1737 | macro_rules! make_ipnet_vec { |
1738 | ($($x:expr),*) => ( vec![$($x.parse::<IpNet>().unwrap(),)*] ); |
1739 | ($($x:expr,)*) => ( make_ipnet_vec![$($x),*] ); |
1740 | } |
1741 | |
1742 | #[test ] |
1743 | fn test_make_ipnet_vec() { |
1744 | assert_eq!( |
1745 | make_ipnet_vec![ |
1746 | "10.1.1.1/32" , "10.2.2.2/24" , "10.3.3.3/16" , |
1747 | "fd00::1/128" , "fd00::2/127" , "fd00::3/126" , |
1748 | ], |
1749 | vec![ |
1750 | "10.1.1.1/32" .parse().unwrap(), |
1751 | "10.2.2.2/24" .parse().unwrap(), |
1752 | "10.3.3.3/16" .parse().unwrap(), |
1753 | "fd00::1/128" .parse().unwrap(), |
1754 | "fd00::2/127" .parse().unwrap(), |
1755 | "fd00::3/126" .parse().unwrap(), |
1756 | ] |
1757 | ); |
1758 | } |
1759 | |
1760 | #[test ] |
1761 | fn test_merge_intervals() { |
1762 | let v = vec![ |
1763 | (0, 1), (1, 2), (2, 3), |
1764 | (11, 12), (13, 14), (10, 15), (11, 13), |
1765 | (20, 25), (24, 29), |
1766 | ]; |
1767 | |
1768 | let v_ok = vec![ |
1769 | (0, 3), |
1770 | (10, 15), |
1771 | (20, 29), |
1772 | ]; |
1773 | |
1774 | let vv = vec![ |
1775 | ([0, 1], [0, 2]), ([0, 2], [0, 3]), ([0, 0], [0, 1]), |
1776 | ([10, 15], [11, 0]), ([10, 0], [10, 16]), |
1777 | ]; |
1778 | |
1779 | let vv_ok = vec![ |
1780 | ([0, 0], [0, 3]), |
1781 | ([10, 0], [11, 0]), |
1782 | ]; |
1783 | |
1784 | assert_eq!(merge_intervals(v), v_ok); |
1785 | assert_eq!(merge_intervals(vv), vv_ok); |
1786 | } |
1787 | |
1788 | macro_rules! make_ipv4_subnets_test { |
1789 | ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => ( |
1790 | #[test] |
1791 | fn $name() { |
1792 | let subnets = IpSubnets::from(Ipv4Subnets::new( |
1793 | $start.parse().unwrap(), |
1794 | $end.parse().unwrap(), |
1795 | $min_prefix_len, |
1796 | )); |
1797 | let results = make_ipnet_vec![$($x),*]; |
1798 | assert_eq!(subnets.collect::<Vec<IpNet>>(), results); |
1799 | } |
1800 | ); |
1801 | ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => ( |
1802 | make_ipv4_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*); |
1803 | ); |
1804 | } |
1805 | |
1806 | macro_rules! make_ipv6_subnets_test { |
1807 | ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr),*) => ( |
1808 | #[test] |
1809 | fn $name() { |
1810 | let subnets = IpSubnets::from(Ipv6Subnets::new( |
1811 | $start.parse().unwrap(), |
1812 | $end.parse().unwrap(), |
1813 | $min_prefix_len, |
1814 | )); |
1815 | let results = make_ipnet_vec![$($x),*]; |
1816 | assert_eq!(subnets.collect::<Vec<IpNet>>(), results); |
1817 | } |
1818 | ); |
1819 | ($name:ident, $start:expr, $end:expr, $min_prefix_len:expr, $($x:expr,)*) => ( |
1820 | make_ipv6_subnets_test!($name, $start, $end, $min_prefix_len, $($x),*); |
1821 | ); |
1822 | } |
1823 | |
1824 | make_ipv4_subnets_test!( |
1825 | test_ipv4_subnets_zero_zero, |
1826 | "0.0.0.0" , "0.0.0.0" , 0, |
1827 | "0.0.0.0/32" , |
1828 | ); |
1829 | |
1830 | make_ipv4_subnets_test!( |
1831 | test_ipv4_subnets_zero_max, |
1832 | "0.0.0.0" , "255.255.255.255" , 0, |
1833 | "0.0.0.0/0" , |
1834 | ); |
1835 | |
1836 | make_ipv4_subnets_test!( |
1837 | test_ipv4_subnets_max_max, |
1838 | "255.255.255.255" , "255.255.255.255" , 0, |
1839 | "255.255.255.255/32" , |
1840 | ); |
1841 | |
1842 | make_ipv4_subnets_test!( |
1843 | test_ipv4_subnets_none, |
1844 | "0.0.0.1" , "0.0.0.0" , 0, |
1845 | ); |
1846 | |
1847 | make_ipv4_subnets_test!( |
1848 | test_ipv4_subnets_one, |
1849 | "0.0.0.0" , "0.0.0.1" , 0, |
1850 | "0.0.0.0/31" , |
1851 | ); |
1852 | |
1853 | make_ipv4_subnets_test!( |
1854 | test_ipv4_subnets_two, |
1855 | "0.0.0.0" , "0.0.0.2" , 0, |
1856 | "0.0.0.0/31" , |
1857 | "0.0.0.2/32" , |
1858 | ); |
1859 | |
1860 | make_ipv4_subnets_test!( |
1861 | test_ipv4_subnets_taper, |
1862 | "0.0.0.0" , "0.0.0.10" , 30, |
1863 | "0.0.0.0/30" , |
1864 | "0.0.0.4/30" , |
1865 | "0.0.0.8/31" , |
1866 | "0.0.0.10/32" , |
1867 | ); |
1868 | |
1869 | make_ipv6_subnets_test!( |
1870 | test_ipv6_subnets_zero_zero, |
1871 | "::" , "::" , 0, |
1872 | "::/128" , |
1873 | ); |
1874 | |
1875 | make_ipv6_subnets_test!( |
1876 | test_ipv6_subnets_zero_max, |
1877 | "::" , "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" , 0, |
1878 | "::/0" , |
1879 | ); |
1880 | |
1881 | make_ipv6_subnets_test!( |
1882 | test_ipv6_subnets_max_max, |
1883 | "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" , "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" , 0, |
1884 | "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" , |
1885 | ); |
1886 | |
1887 | make_ipv6_subnets_test!( |
1888 | test_ipv6_subnets_none, |
1889 | "::1" , "::" , 0, |
1890 | ); |
1891 | |
1892 | make_ipv6_subnets_test!( |
1893 | test_ipv6_subnets_one, |
1894 | "::" , "::1" , 0, |
1895 | "::/127" , |
1896 | ); |
1897 | |
1898 | make_ipv6_subnets_test!( |
1899 | test_ipv6_subnets_two, |
1900 | "::" , "::2" , 0, |
1901 | "::/127" , |
1902 | "::2/128" , |
1903 | ); |
1904 | |
1905 | make_ipv6_subnets_test!( |
1906 | test_ipv6_subnets_taper, |
1907 | "::" , "::a" , 126, |
1908 | "::/126" , |
1909 | "::4/126" , |
1910 | "::8/127" , |
1911 | "::a/128" , |
1912 | ); |
1913 | |
1914 | #[test ] |
1915 | fn test_aggregate() { |
1916 | let ip_nets = make_ipnet_vec![ |
1917 | "10.0.0.0/24" , "10.0.1.0/24" , "10.0.1.1/24" , "10.0.1.2/24" , |
1918 | "10.0.2.0/24" , |
1919 | "10.1.0.0/24" , "10.1.1.0/24" , |
1920 | "192.168.0.0/24" , "192.168.1.0/24" , "192.168.2.0/24" , "192.168.3.0/24" , |
1921 | "fd00::/32" , "fd00:1::/32" , |
1922 | "fd00:2::/32" , |
1923 | ]; |
1924 | |
1925 | let ip_aggs = make_ipnet_vec![ |
1926 | "10.0.0.0/23" , |
1927 | "10.0.2.0/24" , |
1928 | "10.1.0.0/23" , |
1929 | "192.168.0.0/22" , |
1930 | "fd00::/31" , |
1931 | "fd00:2::/32" , |
1932 | ]; |
1933 | |
1934 | let ipv4_nets: Vec<Ipv4Net> = ip_nets.iter().filter_map(|p| if let IpNet::V4(x) = *p { Some(x) } else { None }).collect(); |
1935 | let ipv4_aggs: Vec<Ipv4Net> = ip_aggs.iter().filter_map(|p| if let IpNet::V4(x) = *p { Some(x) } else { None }).collect(); |
1936 | let ipv6_nets: Vec<Ipv6Net> = ip_nets.iter().filter_map(|p| if let IpNet::V6(x) = *p { Some(x) } else { None }).collect(); |
1937 | let ipv6_aggs: Vec<Ipv6Net> = ip_aggs.iter().filter_map(|p| if let IpNet::V6(x) = *p { Some(x) } else { None }).collect(); |
1938 | |
1939 | assert_eq!(IpNet::aggregate(&ip_nets), ip_aggs); |
1940 | assert_eq!(Ipv4Net::aggregate(&ipv4_nets), ipv4_aggs); |
1941 | assert_eq!(Ipv6Net::aggregate(&ipv6_nets), ipv6_aggs); |
1942 | } |
1943 | |
1944 | #[test ] |
1945 | fn test_aggregate_issue44() { |
1946 | let nets: Vec<Ipv4Net> = vec!["128.0.0.0/1" .parse().unwrap()]; |
1947 | assert_eq!(Ipv4Net::aggregate(&nets), nets); |
1948 | |
1949 | let nets: Vec<Ipv4Net> = vec!["0.0.0.0/1" .parse().unwrap(), "128.0.0.0/1" .parse().unwrap()]; |
1950 | assert_eq!(Ipv4Net::aggregate(&nets), vec!["0.0.0.0/0" .parse().unwrap()]); |
1951 | |
1952 | let nets: Vec<Ipv6Net> = vec!["8000::/1" .parse().unwrap()]; |
1953 | assert_eq!(Ipv6Net::aggregate(&nets), nets); |
1954 | |
1955 | let nets: Vec<Ipv6Net> = vec!["::/1" .parse().unwrap(), "8000::/1" .parse().unwrap()]; |
1956 | assert_eq!(Ipv6Net::aggregate(&nets), vec!["::/0" .parse().unwrap()]); |
1957 | } |
1958 | |
1959 | #[test ] |
1960 | fn ipnet_default() { |
1961 | let ipnet: IpNet = "0.0.0.0/0" .parse().unwrap(); |
1962 | assert_eq!(ipnet, IpNet::default()); |
1963 | } |
1964 | |
1965 | #[test ] |
1966 | fn ipv4net_default() { |
1967 | let ipnet: Ipv4Net = "0.0.0.0/0" .parse().unwrap(); |
1968 | assert_eq!(ipnet, Ipv4Net::default()); |
1969 | } |
1970 | |
1971 | #[test ] |
1972 | fn ipv6net_default() { |
1973 | let ipnet: Ipv6Net = "::/0" .parse().unwrap(); |
1974 | assert_eq!(ipnet, Ipv6Net::default()); |
1975 | } |
1976 | |
1977 | #[test ] |
1978 | fn new_assert() { |
1979 | const _: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 0); |
1980 | const _: Ipv4Net = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 32); |
1981 | const _: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0); |
1982 | const _: Ipv6Net = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128); |
1983 | |
1984 | let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 0); |
1985 | let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 32); |
1986 | let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 0); |
1987 | let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128); |
1988 | } |
1989 | |
1990 | #[test ] |
1991 | #[should_panic ] |
1992 | fn ipv4net_new_assert_panics() { |
1993 | let _ = Ipv4Net::new_assert(Ipv4Addr::new(0, 0, 0, 0), 33); |
1994 | } |
1995 | |
1996 | #[test ] |
1997 | #[should_panic ] |
1998 | fn ipv6net_new_assert_panics() { |
1999 | let _ = Ipv6Net::new_assert(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 129); |
2000 | } |
2001 | } |
2002 | |