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