@@ -5,6 +5,7 @@ use tokio::net::TcpStream;
55use tokio:: time:: timeout;
66use futures:: stream:: StreamExt ;
77use anyhow:: { Result , anyhow} ;
8+ use ipnetwork:: IpNetwork ;
89use indicatif:: { ProgressBar , ProgressStyle } ;
910use crate :: types:: ScanResult ;
1011use crate :: service_detection:: detect_service;
@@ -16,6 +17,7 @@ const RETRY_DELAY: u64 = 100;
1617const CHUNK_SIZE : usize = 1000 ;
1718const SUBNET_CHUNK_SIZE : usize = 100 ;
1819const MAX_CONCURRENCY : usize = 1000 ;
20+ const MAX_CIDR_HOSTS : u32 = 65536 ;
1921
2022pub struct Scanner {
2123 targets : Vec < String > ,
@@ -53,6 +55,45 @@ impl Scanner {
5355 return Ok ( ips) ;
5456 }
5557
58+ if target. contains ( '/' ) {
59+ match target. parse :: < IpNetwork > ( ) {
60+ Ok ( network) => {
61+ let host_count = match network {
62+ IpNetwork :: V4 ( net) => {
63+ let prefix_len = net. prefix ( ) ;
64+ if prefix_len > 31 {
65+ 1u64
66+ } else {
67+ 1u64 << ( 32 - prefix_len)
68+ }
69+ }
70+ IpNetwork :: V6 ( net) => {
71+ let prefix_len = net. prefix ( ) ;
72+ if prefix_len > 127 {
73+ 1u64
74+ } else if prefix_len < 64 {
75+ // very large IPv6 ranges
76+ u64:: MAX
77+ } else {
78+ 1u64 << ( 128 - prefix_len) . min ( 63 )
79+ }
80+ }
81+ } ;
82+
83+ if host_count > MAX_CIDR_HOSTS as u64 {
84+ return Err ( anyhow ! (
85+ "CIDR range {} too large ({} hosts). Max: {} (/16 for IPv4)" ,
86+ target, host_count, MAX_CIDR_HOSTS
87+ ) ) ;
88+ }
89+ return Ok ( network. iter ( ) . collect ( ) ) ;
90+ }
91+ Err ( e) => {
92+ return Err ( anyhow ! ( "Invalid CIDR notation '{}': {}" , target, e) ) ;
93+ }
94+ }
95+ }
96+
5697 let socket_addr = format ! ( "{}:80" , target) ;
5798 match socket_addr. to_socket_addrs ( ) {
5899 Ok ( addrs) => {
0 commit comments