mirror of
				https://github.com/ktims/rs-aggregate.git
				synced 2025-11-03 19:04:02 -08:00 
			
		
		
		
	Refactoring & compatibility with aggregate6 options
This commit is contained in:
		
							
								
								
									
										23
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										23
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -16,9 +16,9 @@ checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "clap"
 | 
					name = "clap"
 | 
				
			||||||
version = "4.1.8"
 | 
					version = "4.1.10"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5"
 | 
					checksum = "ce38afc168d8665cfc75c7b1dd9672e50716a137f433f070991619744a67342a"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bitflags",
 | 
					 "bitflags",
 | 
				
			||||||
 "clap_derive",
 | 
					 "clap_derive",
 | 
				
			||||||
@@ -31,9 +31,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "clap_derive"
 | 
					name = "clap_derive"
 | 
				
			||||||
version = "4.1.8"
 | 
					version = "4.1.9"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0"
 | 
					checksum = "fddf67631444a3a3e3e5ac51c36a5e01335302de677bd78759eaa90ab1f46644"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "heck",
 | 
					 "heck",
 | 
				
			||||||
 "proc-macro-error",
 | 
					 "proc-macro-error",
 | 
				
			||||||
@@ -44,9 +44,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "clap_lex"
 | 
					name = "clap_lex"
 | 
				
			||||||
version = "0.3.2"
 | 
					version = "0.3.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09"
 | 
					checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "os_str_bytes",
 | 
					 "os_str_bytes",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -97,10 +97,11 @@ checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "io-lifetimes"
 | 
					name = "io-lifetimes"
 | 
				
			||||||
version = "1.0.6"
 | 
					version = "1.0.8"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3"
 | 
					checksum = "0dd6da19f25979c7270e70fa95ab371ec3b701cd0eefc47667a09785b3c59155"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "hermit-abi",
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "windows-sys 0.45.0",
 | 
					 "windows-sys 0.45.0",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -122,9 +123,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "is-terminal"
 | 
					name = "is-terminal"
 | 
				
			||||||
version = "0.4.4"
 | 
					version = "0.4.5"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
 | 
					checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "hermit-abi",
 | 
					 "hermit-abi",
 | 
				
			||||||
 "io-lifetimes",
 | 
					 "io-lifetimes",
 | 
				
			||||||
@@ -200,7 +201,7 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rs-aggregate"
 | 
					name = "rs-aggregate"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.2.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "clap",
 | 
					 "clap",
 | 
				
			||||||
 "clio",
 | 
					 "clio",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
[package]
 | 
					[package]
 | 
				
			||||||
name = "rs-aggregate"
 | 
					name = "rs-aggregate"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.2.0"
 | 
				
			||||||
edition = "2021"
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
					# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										179
									
								
								src/iputils.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								src/iputils.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,179 @@
 | 
				
			|||||||
 | 
					use std::{
 | 
				
			||||||
 | 
					    error::Error,
 | 
				
			||||||
 | 
					    fmt::Display,
 | 
				
			||||||
 | 
					    net::{IpAddr, Ipv4Addr},
 | 
				
			||||||
 | 
					    str::FromStr,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use ipnet::{IpNet, Ipv4Net, Ipv6Net};
 | 
				
			||||||
 | 
					use iprange::{IpRange, IpRangeIter};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Default)]
 | 
				
			||||||
 | 
					pub struct IpBothRange {
 | 
				
			||||||
 | 
					    v4: IpRange<Ipv4Net>,
 | 
				
			||||||
 | 
					    v6: IpRange<Ipv6Net>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl IpBothRange {
 | 
				
			||||||
 | 
					    pub fn new() -> IpBothRange {
 | 
				
			||||||
 | 
					        IpBothRange::default()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn add(&mut self, net: IpOrNet) {
 | 
				
			||||||
 | 
					        match net {
 | 
				
			||||||
 | 
					            IpOrNet::IpNet(net) => match net {
 | 
				
			||||||
 | 
					                IpNet::V4(v4_net) => drop(self.v4.add(v4_net)),
 | 
				
			||||||
 | 
					                IpNet::V6(v6_net) => drop(self.v6.add(v6_net)),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            IpOrNet::IpAddr(addr) => match addr {
 | 
				
			||||||
 | 
					                IpAddr::V4(v4_addr) => drop(self.v4.add(v4_addr.into())),
 | 
				
			||||||
 | 
					                IpAddr::V6(v6_addr) => drop(self.v6.add(v6_addr.into())),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn simplify(&mut self) {
 | 
				
			||||||
 | 
					        self.v4.simplify();
 | 
				
			||||||
 | 
					        self.v6.simplify();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct IpBothRangeIter<'a> {
 | 
				
			||||||
 | 
					    v4_iter: IpRangeIter<'a, Ipv4Net>,
 | 
				
			||||||
 | 
					    v6_iter: IpRangeIter<'a, Ipv6Net>,
 | 
				
			||||||
 | 
					    _v4_done: bool,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a> Iterator for IpBothRangeIter<'a> {
 | 
				
			||||||
 | 
					    type Item = IpNet;
 | 
				
			||||||
 | 
					    fn next(&mut self) -> Option<Self::Item> {
 | 
				
			||||||
 | 
					        if self._v4_done {
 | 
				
			||||||
 | 
					            match self.v6_iter.next() {
 | 
				
			||||||
 | 
					                Some(net) => return Some(net.into()),
 | 
				
			||||||
 | 
					                None => return None,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        match self.v4_iter.next() {
 | 
				
			||||||
 | 
					            Some(net) => Some(net.into()),
 | 
				
			||||||
 | 
					            None => {
 | 
				
			||||||
 | 
					                self._v4_done = true;
 | 
				
			||||||
 | 
					                match self.v6_iter.next() {
 | 
				
			||||||
 | 
					                    Some(net) => Some(net.into()),
 | 
				
			||||||
 | 
					                    None => None,
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<'a> IntoIterator for &'a IpBothRange {
 | 
				
			||||||
 | 
					    type Item = IpNet;
 | 
				
			||||||
 | 
					    type IntoIter = IpBothRangeIter<'a>;
 | 
				
			||||||
 | 
					    fn into_iter(self) -> Self::IntoIter {
 | 
				
			||||||
 | 
					        IpBothRangeIter {
 | 
				
			||||||
 | 
					            v4_iter: self.v4.iter(),
 | 
				
			||||||
 | 
					            v6_iter: self.v6.iter(),
 | 
				
			||||||
 | 
					            _v4_done: false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum IpOrNet {
 | 
				
			||||||
 | 
					    IpNet(IpNet),
 | 
				
			||||||
 | 
					    IpAddr(IpAddr),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Clone)]
 | 
				
			||||||
 | 
					pub struct NetParseError {
 | 
				
			||||||
 | 
					    #[allow(dead_code)]
 | 
				
			||||||
 | 
					    msg: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Display for NetParseError {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
 | 
					        f.write_str("Unable to parse address")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Error for NetParseError {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl IpOrNet {
 | 
				
			||||||
 | 
					    // Accepted formats:
 | 
				
			||||||
 | 
					    //   netmask - 1.1.1.0/255.255.255.0
 | 
				
			||||||
 | 
					    //   wildcard mask - 1.1.1.0/0.0.0.255
 | 
				
			||||||
 | 
					    fn parse_mask(p: &str) -> Result<u8, Box<dyn Error>> {
 | 
				
			||||||
 | 
					        let mask = p.parse::<Ipv4Addr>();
 | 
				
			||||||
 | 
					        match mask {
 | 
				
			||||||
 | 
					            Ok(mask) => {
 | 
				
			||||||
 | 
					                let intrep: u32 = mask.into();
 | 
				
			||||||
 | 
					                let lead_ones = intrep.leading_ones();
 | 
				
			||||||
 | 
					                if lead_ones > 0 {
 | 
				
			||||||
 | 
					                    if lead_ones + intrep.trailing_zeros() == 32 {
 | 
				
			||||||
 | 
					                        Ok(lead_ones.try_into()?)
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        Err(Box::new(NetParseError {
 | 
				
			||||||
 | 
					                            msg: "Invalid subnet mask".to_owned(),
 | 
				
			||||||
 | 
					                        }))
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    let lead_zeros = intrep.leading_zeros();
 | 
				
			||||||
 | 
					                    if lead_zeros + intrep.trailing_ones() == 32 {
 | 
				
			||||||
 | 
					                        Ok(lead_zeros.try_into()?)
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        Err(Box::new(NetParseError {
 | 
				
			||||||
 | 
					                            msg: "Invalid wildcard mask".to_owned(),
 | 
				
			||||||
 | 
					                        }))
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Err(e) => Err(Box::new(e)),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fn from_parts(ip: &str, pfxlen: &str) -> Result<Self, Box<dyn Error>> {
 | 
				
			||||||
 | 
					        let ip = ip.parse::<IpAddr>()?;
 | 
				
			||||||
 | 
					        let pfxlenp = pfxlen.parse::<u8>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        match pfxlenp {
 | 
				
			||||||
 | 
					            Ok(pfxlen) => Ok(IpNet::new(ip, pfxlen)?.into()),
 | 
				
			||||||
 | 
					            Err(_) => {
 | 
				
			||||||
 | 
					                if ip.is_ipv4() {
 | 
				
			||||||
 | 
					                    Ok(IpNet::new(ip, IpOrNet::parse_mask(pfxlen)?)?.into())
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    Err(Box::new(NetParseError {
 | 
				
			||||||
 | 
					                        msg: "Mask form is not valid for IPv6 address".to_owned(),
 | 
				
			||||||
 | 
					                    }))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    pub fn prefix_len(&self) -> u8 {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            Self::IpNet(net) => net.prefix_len(),
 | 
				
			||||||
 | 
					            Self::IpAddr(addr) => match addr {
 | 
				
			||||||
 | 
					                IpAddr::V4(_) => 32,
 | 
				
			||||||
 | 
					                IpAddr::V6(_) => 128,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl FromStr for IpOrNet {
 | 
				
			||||||
 | 
					    type Err = Box<dyn Error>;
 | 
				
			||||||
 | 
					    fn from_str(s: &str) -> Result<Self, Self::Err> {
 | 
				
			||||||
 | 
					        let parts = s.split_once('/');
 | 
				
			||||||
 | 
					        match parts {
 | 
				
			||||||
 | 
					            Some((ip, pfxlen)) => IpOrNet::from_parts(ip, pfxlen),
 | 
				
			||||||
 | 
					            None => Ok(s.parse::<IpAddr>()?.into()),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<IpNet> for IpOrNet {
 | 
				
			||||||
 | 
					    fn from(net: IpNet) -> Self {
 | 
				
			||||||
 | 
					        IpOrNet::IpNet(net)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<IpAddr> for IpOrNet {
 | 
				
			||||||
 | 
					    fn from(addr: IpAddr) -> Self {
 | 
				
			||||||
 | 
					        IpOrNet::IpAddr(addr)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										139
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -1,10 +1,11 @@
 | 
				
			|||||||
extern crate ipnet;
 | 
					extern crate ipnet;
 | 
				
			||||||
extern crate iprange;
 | 
					extern crate iprange;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod iputils;
 | 
				
			||||||
 | 
					use iputils::{IpBothRange, IpOrNet};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use clio::*;
 | 
					use clio::*;
 | 
				
			||||||
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
 | 
					use std::io::BufRead;
 | 
				
			||||||
use iprange::IpRange;
 | 
					 | 
				
			||||||
use std::{io::BufRead, net::IpAddr};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use clap::Parser;
 | 
					use clap::Parser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -13,80 +14,98 @@ use clap::Parser;
 | 
				
			|||||||
struct Args {
 | 
					struct Args {
 | 
				
			||||||
    #[clap(value_parser, default_value = "-")]
 | 
					    #[clap(value_parser, default_value = "-")]
 | 
				
			||||||
    input: Input,
 | 
					    input: Input,
 | 
				
			||||||
 | 
					    #[arg(
 | 
				
			||||||
 | 
					        short,
 | 
				
			||||||
 | 
					        long,
 | 
				
			||||||
 | 
					        default_value = "128",
 | 
				
			||||||
 | 
					        help = "Sets the maximum prefix length for entries read. Longer prefixes will be discarded prior to processing."
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    max_prefixlen: u8,
 | 
				
			||||||
 | 
					    #[arg(short, long, help = "truncate IP/mask to network/mask (else ignore)")]
 | 
				
			||||||
 | 
					    truncate: bool,
 | 
				
			||||||
 | 
					    #[arg(id="4", short, help = "Only output IPv4 prefixes", conflicts_with("6"))]
 | 
				
			||||||
 | 
					    only_v4: bool,
 | 
				
			||||||
 | 
					    #[arg(id="6", short, help = "Only output IPv6 prefixes", conflicts_with("4"))]
 | 
				
			||||||
 | 
					    only_v6: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Default for Args {
 | 
				
			||||||
 | 
					    fn default() -> Self {
 | 
				
			||||||
 | 
					        Args {
 | 
				
			||||||
 | 
					            input: clio::Input::default(),
 | 
				
			||||||
 | 
					            max_prefixlen: 128,
 | 
				
			||||||
 | 
					            truncate: false,
 | 
				
			||||||
 | 
					            only_v4: false,
 | 
				
			||||||
 | 
					            only_v6: false,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Parser)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct IpParseError {
 | 
					struct IpParseError {
 | 
				
			||||||
    ip: String,
 | 
					    ip: String,
 | 
				
			||||||
    problem: String,
 | 
					    problem: String,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct IpBothRange {
 | 
					 | 
				
			||||||
    v4: IpRange<Ipv4Net>,
 | 
					 | 
				
			||||||
    v6: IpRange<Ipv6Net>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Errors = Vec<IpParseError>;
 | 
					type Errors = Vec<IpParseError>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn simplify_input(mut input: Input) -> (IpBothRange, Errors) {
 | 
					#[derive(Default)]
 | 
				
			||||||
    let mut res = IpBothRange {
 | 
					struct App {
 | 
				
			||||||
        v4: IpRange::new(),
 | 
					    args: Args,
 | 
				
			||||||
        v6: IpRange::new(),
 | 
					    prefixes: IpBothRange,
 | 
				
			||||||
    };
 | 
					    errors: Errors,
 | 
				
			||||||
    let mut errors = Errors::new();
 | 
					}
 | 
				
			||||||
    for line in input.lock().lines() {
 | 
					
 | 
				
			||||||
        for net in line.unwrap().split_whitespace().to_owned() {
 | 
					impl App {
 | 
				
			||||||
            match net.parse() {
 | 
					    fn add_prefix(&mut self, pfx: IpOrNet) {
 | 
				
			||||||
                Ok(ipnet) => match ipnet {
 | 
					        // Parser accepts host bits set, so detect that case and error if not truncate mode
 | 
				
			||||||
                    IpNet::V4(v4_net) => {
 | 
					        if !self.args.truncate {
 | 
				
			||||||
                        res.v4.add(v4_net.trunc());
 | 
					            match pfx {
 | 
				
			||||||
                        ()
 | 
					                IpOrNet::IpNet(net) => {
 | 
				
			||||||
 | 
					                    if net.addr() != net.network() {
 | 
				
			||||||
 | 
					                        eprintln!("ERROR: '{}' is not a valid IP network, ignoring.", net);
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    IpNet::V6(v6_net) => {
 | 
					                }
 | 
				
			||||||
                        res.v6.add(v6_net.trunc());
 | 
					                IpOrNet::IpAddr(_) => (),
 | 
				
			||||||
                        ()
 | 
					            }
 | 
				
			||||||
                    }
 | 
					        }
 | 
				
			||||||
                },
 | 
					        if pfx.prefix_len() <= self.args.max_prefixlen {
 | 
				
			||||||
                Err(_) => {
 | 
					            self.prefixes.add(pfx);
 | 
				
			||||||
                    // First try to add it as a bare IP
 | 
					        }
 | 
				
			||||||
                    match net.parse() {
 | 
					    }
 | 
				
			||||||
                        Ok(ip) => match ip {
 | 
					    fn simplify_input(&mut self) {
 | 
				
			||||||
                            IpAddr::V4(v4_ip) => {
 | 
					        for line in self.args.input.to_owned().lock().lines() {
 | 
				
			||||||
                                res.v4.add(Ipv4Net::new(v4_ip, 32).unwrap());
 | 
					            for net in line.unwrap().split_whitespace().to_owned() {
 | 
				
			||||||
                                ()
 | 
					                let pnet = net.parse::<IpOrNet>();
 | 
				
			||||||
                            }
 | 
					                match pnet {
 | 
				
			||||||
                            IpAddr::V6(v6_ip) => {
 | 
					                    Ok(pnet) => self.add_prefix(pnet),
 | 
				
			||||||
                                res.v6.add(Ipv6Net::new(v6_ip, 128).unwrap());
 | 
					                    Err(e) => {
 | 
				
			||||||
                                ()
 | 
					                        self.errors.push(IpParseError {
 | 
				
			||||||
                            }
 | 
					                            ip: net.to_string(),
 | 
				
			||||||
                        },
 | 
					                            problem: e.to_string(),
 | 
				
			||||||
                        Err(error) => {
 | 
					                        });
 | 
				
			||||||
                            eprintln!("ERROR: {} - {}, ignoring.", net, error.to_string());
 | 
					                        eprintln!("ERROR: '{}' is not a valid IP network, ignoring.", net);
 | 
				
			||||||
                            errors.push(IpParseError {
 | 
					 | 
				
			||||||
                                ip: net.to_string(),
 | 
					 | 
				
			||||||
                                problem: error.to_string(),
 | 
					 | 
				
			||||||
                            });
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        self.prefixes.simplify();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    res.v4.simplify();
 | 
					 | 
				
			||||||
    res.v6.simplify();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (res, errors)
 | 
					    fn main(&mut self) {
 | 
				
			||||||
 | 
					        self.args = Args::parse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.simplify_input();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for net in &self.prefixes {
 | 
				
			||||||
 | 
					            println!("{}", net);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
    let args = Args::parse();
 | 
					    let mut app = App::default();
 | 
				
			||||||
    let input = args.input;
 | 
					    app.main();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    let (res, _) = simplify_input(input);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for net in &res.v4 {
 | 
					 | 
				
			||||||
        println!("{}", net);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    for net in &res.v6 {
 | 
					 | 
				
			||||||
        println!("{}", net);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user