Add cmdline args

This commit is contained in:
Michael Mikovsky
2025-04-30 13:25:14 -06:00
parent b262f9fdea
commit bbbd52a494
9 changed files with 328074 additions and 123 deletions
+1
View File
@@ -21,3 +21,4 @@ sha256 = "1.6.0"
rayon = "1.10.0"
futures = "0.3.31"
chrono = "0.4.40"
clap = { version = "4.5.37", features = ["derive"] }
+327837
View File
File diff suppressed because one or more lines are too long
-2
View File
@@ -790,8 +790,6 @@ pub fn search_parallel(
}
}
println!("{:?}", version_queries);
fn loop_queries(
db: &DB,
cf: &ColumnFamily,
+104 -104
View File
File diff suppressed because one or more lines are too long
+9 -6
View File
@@ -15,11 +15,14 @@ use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
static TIMEOUT: Duration = Duration::from_secs(3);
// static MAX_PINGS_PER_SECOND: u64 = 10000;
static SEND_DELAY_NANOS: Duration = Duration::from_micros(10);
// static SEND_DELAY_NANOS: Duration = Duration::from_micros(10);
pub fn ping_scan(hosts: Vec<IpAddr>) -> Result<Vec<IpAddr>, Box<dyn std::error::Error>> {
pub fn ping_scan(
hosts: Vec<IpAddr>,
timeout: Duration,
ping_delay: Duration,
) -> Result<Vec<IpAddr>, Box<dyn std::error::Error>> {
let results = Arc::new(Mutex::new(Vec::<IpAddr>::new()));
// Create a receiver channel for ICMP packets
@@ -50,7 +53,7 @@ pub fn ping_scan(hosts: Vec<IpAddr>) -> Result<Vec<IpAddr>, Box<dyn std::error::
if finish_sending_time.is_some() {
let delay = finish_sending_time.unwrap().elapsed();
// pb.as_ref().unwrap().set_position(delay.as_millis() as u64);
if delay >= TIMEOUT {
if delay >= timeout {
// pb.unwrap().finish_and_clear();
break;
}
@@ -59,7 +62,7 @@ pub fn ping_scan(hosts: Vec<IpAddr>) -> Result<Vec<IpAddr>, Box<dyn std::error::
{
finish_sending_time = Some(Instant::now());
// pb = Some(ProgressBar::new(TIMEOUT.as_millis() as u64));
println!("Waiting {} seconds for timeout...", TIMEOUT.as_secs())
println!("Waiting {} seconds for timeout...", timeout.as_secs_f32())
}
// if time.is_some() {
// println!("{}", time.unwrap().elapsed().as_millis())
@@ -126,7 +129,7 @@ pub fn ping_scan(hosts: Vec<IpAddr>) -> Result<Vec<IpAddr>, Box<dyn std::error::
if (i % 16) == 0 {
pb.inc(16);
}
thread::sleep(SEND_DELAY_NANOS);
thread::sleep(ping_delay);
}
pb.finish_and_clear();
+8 -3
View File
@@ -21,7 +21,12 @@ fn std_to_pnet_ipv4(previous: &IpAddr) -> Ipv4Addr {
}
// Main scanning function
pub fn tcp_scan(targets: Vec<IpAddr>, ports: Vec<i32>, timeout: Duration) -> Vec<PortScanResult> {
pub fn tcp_scan(
targets: Vec<IpAddr>,
ports: Vec<i32>,
timeout: Duration,
tcp_delay: Duration,
) -> Vec<PortScanResult> {
// Search for VPN connection and fall back to regular
let interface = datalink::interfaces()
.into_iter()
@@ -89,7 +94,7 @@ pub fn tcp_scan(targets: Vec<IpAddr>, ports: Vec<i32>, timeout: Duration) -> Vec
{
finish_sending_time = Some(Instant::now());
// pb = Some(ProgressBar::new(TIMEOUT.as_millis() as u64));
println!("Waiting {} seconds for timeout...", timeout.as_secs())
println!("Waiting {} seconds for timeout...", timeout.as_secs_f32())
}
// println!("loop");
@@ -185,7 +190,7 @@ pub fn tcp_scan(targets: Vec<IpAddr>, ports: Vec<i32>, timeout: Duration) -> Vec
));
pb.inc(1);
thread::sleep(Duration::from_micros(100));
thread::sleep(tcp_delay);
}
}
+5 -7
View File
@@ -21,23 +21,21 @@ fn try_parse_host(query: &str) -> Option<QueryDataType> {
None
}
pub fn search(query: String) -> Result<Vec<QueryDataType>, Box<dyn std::error::Error>> {
if let Some(host) = try_parse_host(&query) {
pub fn search(query: Vec<String>) -> Result<Vec<QueryDataType>, Box<dyn std::error::Error>> {
if let Some(host) = try_parse_host(&query.join("")) {
return Ok(vec![host]);
}
let split = query.split(" ");
let delim = Regex::new("(?:!=|<=|>=|[=:+-><])")?;
let mut results = Vec::new();
for query in split {
if let Some(host) = try_parse_host(query) {
for query in query {
if let Some(host) = try_parse_host(&query) {
return Ok(vec![host]);
}
if let Some(m) = delim.find(query) {
if let Some(m) = delim.find(&query) {
let tag = query[0..m.start()].to_string().to_lowercase();
let delim = query[m.start()..m.end()].to_string();
let data = query[m.end()..query.len()].to_string();
+7 -1
View File
@@ -187,7 +187,13 @@ fn split_ips_into_chunks(ips: Vec<PortScanResult>, num_chunks: usize) -> Vec<Vec
}
// Connect to an IP:port and send a probe
fn try_connect(ip: IpAddr, port: &i32, timeout: Duration, probe: &[u8]) -> Option<Vec<u8>> {
fn try_connect(
ip: IpAddr,
port: &i32,
timeout: Duration,
probe: &[u8],
delay: u64,
) -> Option<Vec<u8>> {
let addr = SocketAddr::new(ip, *port as u16);
match TcpStream::connect_timeout(&addr, timeout) {
+103
View File
@@ -0,0 +1,103 @@
use craftping::sync::ping;
use serde_json::json;
use sha256::digest;
use std::{
net::{IpAddr, SocketAddr, TcpStream},
time::{Duration, SystemTime, UNIX_EPOCH},
};
use crate::database::{DatabaseResult, EPOCH_2025};
pub fn scan(
ip: IpAddr,
port: &i32,
timeout: Duration,
) -> Result<DatabaseResult, Box<dyn std::error::Error>> {
let port = *port as u16;
let socket = SocketAddr::new(ip, port);
let ip = ip.to_string();
let mut stream = TcpStream::connect_timeout(&socket, timeout)?;
stream.set_read_timeout(Some(timeout))?;
stream.set_write_timeout(Some(timeout))?;
let pong = ping(&mut stream, &ip, port)?;
let icon_hash = match pong.favicon {
Some(icon) => digest(icon),
None => "None".to_string(),
};
Ok(DatabaseResult {
ip: ip.to_string(),
port: port as u16,
time_scanned: (SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
- EPOCH_2025 as u64) as u32,
version: pong.version,
protocol: pong.protocol as u32,
max_players: pong.max_players as u32,
online_players: pong.online_players as u32,
players_list: if let Some(sample) = pong.sample {
Some(
sample
.iter()
.map(|a| (a.id.clone(), a.name.clone()))
.collect(),
)
} else {
None
},
description: pong.description.unwrap_or(json!("")).to_string(),
icon_hash: icon_hash,
mod_info: if let Some(mod_info) = pong.mod_info {
Some((
mod_info.mod_type,
mod_info
.mod_list
.iter()
.map(|a| (a.mod_id.clone(), a.version.clone()))
.collect(),
))
} else {
None
},
forge_data: if let Some(forge_data) = pong.forge_data {
Some((
forge_data
.channels
.iter()
.map(|a| (a.version.clone(), a.res.clone(), a.required))
.collect(),
forge_data
.mods
.iter()
.map(|a| (a.mod_marker.clone(), a.mod_id.clone()))
.collect(),
forge_data.fml_network_version,
))
} else {
None
},
enforces_secure_chat: pong.enforces_secure_chat,
previews_chat: pong.previews_chat,
})
// Ok(serde_json::to_string(&json!({
// "version": pong.version,
// "protocol": pong.protocol,
// "max_players": pong.max_players,
// "online_players": pong.online_players,
// "players_list": pong.sample,
// "description": pong.description,
// "icon": icon_hash,
// "mod_info": pong.mod_info,
// "forge_data": pong.forge_data,
// "enforces_secure_chat": pong.enforces_secure_chat,
// "previews_chat": pong.previews_chat
// }))?)
}