@@ -6,7 +6,7 @@ use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
66use std:: path:: Path ;
77use std:: str:: FromStr ;
88
9- use cidr_utils:: cidr:: IpCidr ;
9+ use cidr_utils:: cidr:: { IpCidr , IpInet } ;
1010use 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/// ```
9494pub 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