Skip to content

Commit 0f012fd

Browse files
feat(cidr): add CIDR support
1 parent 9f01d89 commit 0f012fd

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

src/scanner.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use tokio::net::TcpStream;
55
use tokio::time::timeout;
66
use futures::stream::StreamExt;
77
use anyhow::{Result, anyhow};
8+
use ipnetwork::IpNetwork;
89
use indicatif::{ProgressBar, ProgressStyle};
910
use crate::types::ScanResult;
1011
use crate::service_detection::detect_service;
@@ -16,6 +17,7 @@ const RETRY_DELAY: u64 = 100;
1617
const CHUNK_SIZE: usize = 1000;
1718
const SUBNET_CHUNK_SIZE: usize = 100;
1819
const MAX_CONCURRENCY: usize = 1000;
20+
const MAX_CIDR_HOSTS: u32 = 65536;
1921

2022
pub 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

Comments
 (0)