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