Skip to content

Commit 0f23a67

Browse files
authored
Merge pull request #789 from zombiepigdragon/permissive-cidr
Allow CIDR addresses with non-zero host bits
2 parents 1085a72 + 3bdac9c commit 0f23a67

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

src/address.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
66
use std::path::Path;
77
use std::str::FromStr;
88

9-
use cidr_utils::cidr::IpCidr;
9+
use cidr_utils::cidr::{IpCidr, IpInet};
1010
use hickory_resolver::{
1111
config::{NameServerConfig, Protocol, ResolverConfig, ResolverOpts},
1212
Resolver,
@@ -92,16 +92,21 @@ pub fn parse_addresses(input: &Opts) -> Vec<IpAddr> {
9292
/// let ips = parse_address("127.0.0.1", &Resolver::default().unwrap());
9393
/// ```
9494
pub fn parse_address(address: &str, resolver: &Resolver) -> Vec<IpAddr> {
95-
IpCidr::from_str(address)
96-
.map(|cidr| cidr.iter().map(|c| c.address()).collect())
97-
.ok()
98-
.or_else(|| {
99-
format!("{}:80", &address)
100-
.to_socket_addrs()
101-
.ok()
102-
.map(|mut iter| vec![iter.next().unwrap().ip()])
103-
})
104-
.unwrap_or_else(|| resolve_ips_from_host(address, resolver))
95+
if let Ok(addr) = IpAddr::from_str(address) {
96+
// `address` is an IP string
97+
vec![addr]
98+
} else if let Ok(net_addr) = IpInet::from_str(address) {
99+
// `address` is a CIDR string
100+
net_addr.network().into_iter().addresses().collect()
101+
} else {
102+
// `address` is a hostname or DNS name
103+
// attempt default DNS lookup
104+
match format!("{address}:80").to_socket_addrs() {
105+
Ok(mut iter) => vec![iter.next().unwrap().ip()],
106+
// default lookup didn't work, so try again with the dedicated resolver
107+
Err(_) => resolve_ips_from_host(address, resolver),
108+
}
109+
}
105110
}
106111

107112
/// Uses DNS to get the IPS associated with host
@@ -400,6 +405,19 @@ mod tests {
400405
assert_eq!(ips.len(), 2_048);
401406
}
402407

408+
#[test]
409+
fn parse_overspecific_cidr() {
410+
// a canonical CIDR string has 0 in all host bits, but we want to treat any CIDR-like string as CIDR
411+
let opts = Opts {
412+
addresses: vec!["192.128.1.1/24".to_owned()],
413+
..Default::default()
414+
};
415+
416+
let ips = parse_addresses(&opts);
417+
418+
assert_eq!(ips.len(), 256);
419+
}
420+
403421
#[test]
404422
fn resolver_default_cloudflare() {
405423
let opts = Opts::default();

0 commit comments

Comments
 (0)