Compare commits

...
Author SHA1 Message Date
Dmitry SavintsevandBee f74cb456b1 socket_iterator: use itertools.iproducts for ip x ports set (#231)
Replace the current manual iterator-like implementation
with the call to the itertools.iproduct macro
to generate the cartesian product of the IPs and ports.

stdlib reference:
https://docs.rs/itertools/0.9.0/itertools/macro.iproduct.html

Co-authored-by: Bee <[email protected]>
2020-09-20 12:15:46 +01:00
Brandon 492d2fb3b3 fixed accessible issues 2020-09-20 01:25:41 +01:00
bergabmanandBee af53591ccb Added top ports, fixed accessibility. (#230)
* Refactored scanner struct for accessibility, fixed macros

Co-authored-by: Bee <[email protected]>
2020-09-19 18:24:08 +01:00
Bee 6405b43f5a Merge pull request #229 from dmitris/patch-1
fix typo
2020-09-19 00:54:24 +01:00
Dmitry Savintsev 9a71253697 fix typo 2020-09-18 22:13:33 +02:00
8 changed files with 192 additions and 129 deletions

No files matched your search

Generated
+16
View File
@@ -322,6 +322,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "env_logger"
version = "0.7.1"
@@ -514,6 +520,15 @@ dependencies = [
"quick-error",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
dependencies = [
"either",
]
[[package]]
name = "js-sys"
version = "0.3.44"
@@ -833,6 +848,7 @@ dependencies = [
"env_logger",
"futures",
"gcd",
"itertools",
"log",
"rand",
"rlimit",
+1
View File
@@ -34,6 +34,7 @@ toml = "0.5.6"
serde = "1.0.116"
serde_derive = "1.0.116"
cidr-utils = "0.5.0"
itertools = "0.9.0"
[package.metadata.deb]
depends = "$auto, nmap"
+1 -1
View File
@@ -11,7 +11,7 @@ RustScan has 2 major labels for GitHub issues you should look at:
These are issues for newcomers to open source!
[https://github.com/RustScan/RustScan/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22](https://github.com/RustScan/RustScan/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
* Help wanted
These are issues that aren't really for newcomers, but we could still do wiht help!
These are issues that aren't really for newcomers, but we could still do with help!
[https://github.com/RustScan/RustScan/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22+label%3A%22help+wanted%22](https://github.com/RustScan/RustScan/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22+label%3A%22help+wanted%22)
If you want to, solve the issue or comment on the issue for help.
+44 -45
View File
@@ -1,4 +1,5 @@
use serde_derive::Deserialize;
use std::collections::HashMap;
use std::fs;
use structopt::{clap::arg_enum, StructOpt};
@@ -70,9 +71,9 @@ pub struct Opts {
#[structopt(short, long)]
pub no_config: bool,
/// Quiet mode. Only output the ports. No Nmap. Useful for grep or outputting to a file.
/// Greppable mode. Only output the ports. No Nmap. Useful for grep or outputting to a file.
#[structopt(short, long)]
pub quiet: bool,
pub greppable: bool,
/// Accessible mode. Turns off features which negatively affect screen readers.
#[structopt(long)]
@@ -110,6 +111,10 @@ pub struct Opts {
/// For things like --script '(safe and vuln)' enclose it in quotations marks \"'(safe and vuln)'\"")
#[structopt(last = true)]
pub command: Vec<String>,
/// Use the top 1000 ports.
#[structopt(long)]
pub top: bool,
}
impl Opts {
@@ -146,7 +151,7 @@ impl Opts {
}
}
merge_required!(addresses, quiet, accessible, batch_size, timeout, scan_order, command);
merge_required!(addresses, greppable, accessible, batch_size, timeout, scan_order, command);
}
fn merge_optional(&mut self, config: &Config) {
@@ -160,7 +165,18 @@ impl Opts {
}
}
merge_optional!(ports, range, ulimit);
// Only use top ports when the user asks for them
if self.top {
if config.ports.is_some() {
let mut ports: Vec<u16> = Vec::with_capacity(config.ports.clone().unwrap().len());
for entry in config.ports.clone().unwrap().keys() {
ports.push(entry.parse().unwrap())
}
self.ports = Some(ports);
}
}
merge_optional!(range, ulimit);
}
}
@@ -170,9 +186,9 @@ impl Opts {
#[derive(Debug, Deserialize)]
pub struct Config {
addresses: Option<Vec<String>>,
ports: Option<Vec<u16>>,
ports: Option<HashMap<String, u16>>,
range: Option<PortRange>,
quiet: Option<bool>,
greppable: Option<bool>,
accessible: Option<bool>,
batch_size: Option<u16>,
timeout: Option<u32>,
@@ -194,40 +210,21 @@ impl Config {
/// scan_order: "Serial"
///
pub fn read() -> Self {
let mut paths = Vec::new();
paths.push(match dirs::home_dir() {
Some(mut path) => {
path.push(".rustscan.toml");
path
}
let mut home_dir = match dirs::home_dir() {
Some(dir) => dir,
None => panic!("Could not infer config file path."),
});
};
home_dir.push(".rustscan.toml");
paths.push(match dirs::config_dir() {
Some(mut path) => {
path.push("rustscan");
path.push("config.toml");
path
let mut content = String::new();
if home_dir.exists() {
content = match fs::read_to_string(home_dir) {
Ok(content) => content,
Err(_) => String::new(),
}
None => panic!("Could not infer config file path."),
});
let mut contents: Option<String> = None;
for path in paths.iter().rev() {
contents = match fs::read_to_string(path) {
Ok(content) => {
contents = Some(content);
break;
}
Err(_) => None,
};
}
if contents.is_none() {
contents = Some(String::new());
}
let config: Config = match toml::from_str(&contents.unwrap()) {
let config: Config = match toml::from_str(&content) {
Ok(config) => config,
Err(e) => {
println!("Found {} in configuration file.\nAborting scan.\n", e);
@@ -249,7 +246,7 @@ mod tests {
addresses: vec![],
ports: None,
range: None,
quiet: false,
greppable: false,
batch_size: 0,
timeout: 0,
ulimit: None,
@@ -258,13 +255,14 @@ mod tests {
no_nmap: false,
scan_order: ScanOrder::Serial,
no_config: true,
top: false,
};
let config = Config {
addresses: Some(vec!["127.0.0.1".to_owned()]),
ports: None,
range: None,
quiet: Some(true),
greppable: Some(true),
batch_size: Some(25_000),
timeout: Some(1_000),
ulimit: None,
@@ -277,7 +275,7 @@ mod tests {
opts.merge(&config);
assert_eq!(opts.addresses, vec![] as Vec<String>);
assert_eq!(opts.quiet, false);
assert_eq!(opts.greppable, false);
assert_eq!(opts.accessible, false);
assert_eq!(opts.timeout, 0);
assert_eq!(opts.command, vec![] as Vec<String>);
@@ -290,7 +288,7 @@ mod tests {
addresses: vec![],
ports: None,
range: None,
quiet: false,
greppable: false,
batch_size: 0,
timeout: 0,
ulimit: None,
@@ -299,6 +297,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_nmap: false,
no_config: false,
top: false,
};
let config = Config {
@@ -306,7 +305,7 @@ mod tests {
ports: None,
no_nmap: Some(false),
range: None,
quiet: Some(true),
greppable: Some(true),
batch_size: Some(25_000),
timeout: Some(1_000),
ulimit: None,
@@ -318,7 +317,7 @@ mod tests {
opts.merge_required(&config);
assert_eq!(opts.addresses, config.addresses.unwrap());
assert_eq!(opts.quiet, config.quiet.unwrap());
assert_eq!(opts.greppable, config.greppable.unwrap());
assert_eq!(opts.timeout, config.timeout.unwrap());
assert_eq!(opts.command, config.command.unwrap());
assert_eq!(opts.accessible, config.accessible.unwrap());
@@ -331,7 +330,7 @@ mod tests {
addresses: vec![],
ports: None,
range: None,
quiet: false,
greppable: false,
batch_size: 0,
timeout: 0,
ulimit: None,
@@ -340,16 +339,17 @@ mod tests {
scan_order: ScanOrder::Serial,
no_nmap: false,
no_config: false,
top: false,
};
let config = Config {
addresses: None,
ports: Some(vec![80, 403]),
ports: None,
range: Some(PortRange {
start: 1,
end: 1_000,
}),
quiet: None,
greppable: None,
batch_size: None,
timeout: None,
no_nmap: Some(false),
@@ -361,7 +361,6 @@ mod tests {
opts.merge_optional(&config);
assert_eq!(opts.ports, config.ports);
assert_eq!(opts.range, config.range);
assert_eq!(opts.ulimit, config.ulimit);
}
+70 -39
View File
@@ -50,14 +50,18 @@ fn main() {
debug!("Main() `opts` arguments are {:?}", opts);
if !opts.quiet && !opts.accessible {
print_opening();
if !opts.greppable && !opts.accessible {
print_opening(&opts);
}
let ips: Vec<IpAddr> = parse_addresses(&opts);
if ips.is_empty() {
warning!("No IPs could be resolved, aborting scan.", false);
warning!(
"No IPs could be resolved, aborting scan.",
opts.greppable,
opts.accessible
);
std::process::exit(1);
}
@@ -68,8 +72,9 @@ fn main() {
&ips,
batch_size,
Duration::from_millis(opts.timeout.into()),
opts.quiet,
opts.greppable,
PortStrategy::pick(opts.range, opts.ports, opts.scan_order),
opts.accessible,
);
debug!("Scanner finished building: {:?}", scanner);
@@ -101,33 +106,36 @@ fn main() {
ip,
opts.batch_size,
"'rustscan -b <batch_size> <ip address>'");
warning!(x, opts.quiet);
warning!(x, opts.greppable, opts.accessible);
}
let mut nmap_bench = NamedTimer::start("Nmap");
for (ip, ports) in ports_per_ip.iter_mut() {
let nmap_str_ports: Vec<String> = ports.into_iter().map(|port| port.to_string()).collect();
detail!("Starting Nmap", opts.quiet || opts.no_nmap);
// nmap port style is 80,443. Comma separated with no spaces.
let ports_str = nmap_str_ports.join(",");
// if quiet mode is on nmap should not be spawned
if opts.quiet || opts.no_nmap {
if opts.greppable || opts.no_nmap {
println!("{} -> [{}]", &ip, ports_str);
continue;
}
detail!("Starting Nmap", opts.greppable, opts.accessible);
let addr = ip.to_string();
let user_nmap_args =
shell_words::split(&opts.command.join(" ")).expect("failed to parse nmap arguments");
let nmap_args = build_nmap_arguments(&addr, &ports_str, &user_nmap_args, ip.is_ipv6());
output!(format!(
"The Nmap command to be run is nmap {}\n",
&nmap_args.join(" ")
));
output!(
format!(
"The Nmap command to be run is nmap {}\n",
&nmap_args.join(" ")
),
opts.greppable.clone(),
opts.accessible.clone()
);
// Runs the nmap command and spawns it as a process.
let mut child = Command::new("nmap")
@@ -148,7 +156,7 @@ fn main() {
}
/// Prints the opening title of RustScan
fn print_opening() {
fn print_opening(opts: &Opts) {
debug!("Printing opening");
let s = r#".----. .-. .-. .----..---. .----. .---. .--. .-. .-.
| {} }| { } |{ {__ {_ _}{ {__ / ___} / {} \ | `| |
@@ -163,19 +171,17 @@ Faster Nmap scanning with Rust."#;
println!("{}", info.gradient(Color::Yellow).bold());
funny_opening!();
let config_path = match dirs::config_dir() {
Some(mut path) => {
path.push("rustscan");
path.push("config.toml");
path
}
None => panic!("Couldn't find config dir."),
let mut home_dir = match dirs::home_dir() {
Some(dir) => dir,
None => panic!("Could not infer config file path."),
};
home_dir.push(".rustscan.toml");
detail!(format!(
"{} {:?}",
"The config file is expected to be at", config_path
));
detail!(
format!("The config file is expected to be at {:?}", home_dir),
opts.greppable,
opts.accessible
);
}
#[cfg(not(tarpaulin_include))]
fn build_nmap_arguments<'a>(
@@ -208,7 +214,7 @@ fn parse_addresses(opts: &Opts) -> Vec<IpAddr> {
Ok(mut iter) => ips.push(iter.nth(0).unwrap().ip()),
_ => {
let failed_to_resolve = format!("Host {:?} could not be resolved.", ip_or_host);
warning!(failed_to_resolve, opts.quiet);
warning!(failed_to_resolve, opts.greppable, opts.accessible);
}
},
}
@@ -225,7 +231,8 @@ fn adjust_ulimit_size(opts: &Opts) -> rlimit::rlim {
Ok(_) => {
detail!(
format!("Automatically increasing ulimit value to {}.", limit),
opts.quiet
opts.greppable,
opts.accessible
);
}
Err(_) => println!("{}", "ERROR. Failed to set ulimit value."),
@@ -243,7 +250,7 @@ fn infer_batch_size(opts: &Opts, ulimit: rlimit::rlim) -> u16 {
// Adjust the batch size when the ulimit value is lower than the desired batch size
if ulimit < batch_size {
warning!("File limit is lower than default batch size. Consider upping with --ulimit. May cause harm to sensitive servers",
opts.quiet
opts.greppable, opts.accessible
);
// When the OS supports high file limits like 8000, but the user
@@ -253,7 +260,7 @@ fn infer_batch_size(opts: &Opts, ulimit: rlimit::rlim) -> u16 {
// ulimit is smaller than aveage batch size
// user must have very small ulimit
// decrease batch size to half of ulimit
warning!("Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. ");
warning!("Your file limit is very small, which negatively impacts RustScan's speed. Use the Docker image, or up the Ulimit with '--ulimit 5000'. ", opts.greppable, opts.accessible);
info!("Halving batch_size because ulimit is smaller than average batch size");
batch_size = ulimit / 2
} else if ulimit > DEFAULT_FILE_DESCRIPTORS_LIMIT {
@@ -269,7 +276,7 @@ fn infer_batch_size(opts: &Opts, ulimit: rlimit::rlim) -> u16 {
detail!(format!(
"File limit higher than batch size. Can increase speed by increasing batch size '-b {}'.",
ulimit - 100
), opts.quiet);
), opts.greppable, opts.accessible);
}
batch_size as u16
@@ -288,7 +295,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
@@ -297,6 +304,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let batch_size = infer_batch_size(&opts, 120);
@@ -309,7 +317,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
@@ -318,6 +326,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let batch_size = infer_batch_size(&opts, 9_000);
@@ -331,7 +340,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
@@ -340,6 +349,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let batch_size = infer_batch_size(&opts, 5_000);
@@ -352,7 +362,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
@@ -361,6 +371,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let batch_size = adjust_ulimit_size(&opts);
@@ -368,8 +379,23 @@ mod tests {
}
#[test]
fn test_print_opening_no_panic() {
let opts = Opts {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
greppable: true,
batch_size: 50_000,
timeout: 1_000,
ulimit: Some(2_000),
command: Vec::new(),
accessible: false,
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
// print opening should not panic
print_opening();
print_opening(&opts);
assert!(1 == 1);
}
#[test]
@@ -378,7 +404,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned()],
ports: None,
range: None,
quiet: false,
greppable: false,
batch_size: 10,
timeout: 1_000,
ulimit: None,
@@ -387,6 +413,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
infer_batch_size(&opts, 1_000_000);
@@ -400,7 +427,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned(), "192.168.0.0/30".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
@@ -409,6 +436,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let ips = parse_addresses(&opts);
@@ -430,7 +458,7 @@ mod tests {
addresses: vec!["google.com".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
@@ -439,6 +467,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let ips = parse_addresses(&opts);
@@ -451,7 +480,7 @@ mod tests {
addresses: vec!["127.0.0.1".to_owned(), "im_wrong".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
@@ -460,6 +489,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let ips = parse_addresses(&opts);
@@ -472,7 +502,7 @@ mod tests {
addresses: vec!["im_wrong".to_owned(), "300.10.1.1".to_owned()],
ports: None,
range: None,
quiet: true,
greppable: true,
batch_size: 10,
timeout: 1_000,
ulimit: Some(2_000),
@@ -481,6 +511,7 @@ mod tests {
scan_order: ScanOrder::Serial,
no_config: false,
no_nmap: false,
top: false,
};
let ips = parse_addresses(&opts);
+13 -6
View File
@@ -28,6 +28,7 @@ pub struct Scanner {
timeout: Duration,
quiet: bool,
port_strategy: PortStrategy,
accessible: bool,
}
impl Scanner {
@@ -37,6 +38,7 @@ impl Scanner {
timeout: Duration,
quiet: bool,
port_strategy: PortStrategy,
accessible: bool,
) -> Self {
Self {
batch_size,
@@ -44,6 +46,7 @@ impl Scanner {
quiet,
port_strategy,
ips: ips.iter().map(|ip| ip.to_owned()).collect(),
accessible,
}
}
@@ -108,7 +111,11 @@ impl Scanner {
_ => {}
}
if !self.quiet {
println!("Open {}", socket.to_string().purple());
if self.accessible {
println!("Open {}", socket.to_string());
} else {
println!("Open {}", socket.to_string().purple());
}
}
Ok(socket)
@@ -167,7 +174,7 @@ mod tests {
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
assert_eq!(1, 1);
@@ -181,7 +188,7 @@ mod tests {
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
// if the scan fails, it wouldn't be able to assert_eq! as it panicked!
assert_eq!(1, 1);
@@ -194,7 +201,7 @@ mod tests {
end: 1_000,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
assert_eq!(1, 1);
}
@@ -206,7 +213,7 @@ mod tests {
end: 445,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
assert_eq!(1, 1);
}
@@ -221,7 +228,7 @@ mod tests {
end: 600,
};
let strategy = PortStrategy::pick(Some(range), None, ScanOrder::Random);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy);
let scanner = Scanner::new(&addrs, 10, Duration::from_millis(100), true, strategy, true);
block_on(scanner.run());
assert_eq!(1, 1);
}
+17 -25
View File
@@ -1,12 +1,17 @@
use itertools::{iproduct, Product};
use std::net::{IpAddr, SocketAddr};
pub struct SocketIterator<'s> {
ips: &'s [IpAddr],
ports: &'s [u16],
ip_idx: usize,
ip_len: usize,
port_idx: usize,
port_len: usize,
// product_it is a cartesian product iterator over
// the slices of ports and IP addresses.
//
// The IP/port order is intentionally reversed here since we want
// the itertools::iproduct! macro below to generate the pairs with
// all the IPs for one port before moving on to the next one
// ("hold the port, go through all the IPs, then advance the port...").
// See also the comments in the iterator implementation for an example.
product_it:
Product<Box<std::slice::Iter<'s, u16>>, Box<std::slice::Iter<'s, std::net::IpAddr>>>,
}
/// An iterator that receives a slice of IPs and ports and returns a Socket
@@ -16,13 +21,10 @@ pub struct SocketIterator<'s> {
/// generating a vector containing all these combinations.
impl<'s> SocketIterator<'s> {
pub fn new(ips: &'s [IpAddr], ports: &'s [u16]) -> Self {
let ports_it = Box::new(ports.into_iter());
let ips_it = Box::new(ips.into_iter());
Self {
ip_idx: 0,
ip_len: ips.len(),
port_idx: 0,
port_len: ports.len(),
ips,
ports,
product_it: iproduct!(ports_it, ips_it),
}
}
}
@@ -41,20 +43,10 @@ impl<'s> Iterator for SocketIterator<'s> {
/// it.next(); // 192.168.0.1:443
/// it.next(); // None
fn next(&mut self) -> Option<Self::Item> {
if self.port_idx == self.port_len {
return None;
match self.product_it.next() {
None => None,
Some((port, ip)) => Some(SocketAddr::new(*ip, *port)),
}
self.ip_idx = self.ip_idx % self.ip_len;
let socket = SocketAddr::new(self.ips[self.ip_idx], self.ports[self.port_idx]);
self.ip_idx += 1;
if self.ip_idx == self.ip_len {
self.port_idx += 1;
}
Some(socket)
}
}
+30 -13
View File
@@ -7,11 +7,16 @@ macro_rules! warning {
use ansi_term::Colour::Red;
println!("{} {}", Red.bold().paint("[!]"), $name);
};
// quiet mode
($name:expr, $quiet:expr) => {
($name:expr, $greppable:expr, $accessible:expr) => {
use ansi_term::Colour::Red;
if !$quiet {
println!("{} {}", Red.bold().paint("[!]"), $name);
// if not greppable then print, otherwise no else statement so do not print.
if !$greppable {
if $accessible {
// Don't print the ascii art
println!("{}", $name);
} else {
println!("{} {}", Red.bold().paint("[!]"), $name);
}
}
};
}
@@ -22,26 +27,38 @@ macro_rules! detail {
use ansi_term::Colour::Blue;
println!("{} {}", Blue.bold().paint("[~]"), $name);
};
($name:expr, $quiet:expr) => {
($name:expr, $greppable:expr, $accessible:expr) => {
use ansi_term::Colour::Blue;
if !$quiet {
println!("{} {}", Blue.bold().paint("[~]"), $name);
// if not greppable then print, otherwise no else statement so do not print.
if !$greppable {
if $accessible {
// Don't print the ascii art
println!("{}", $name);
} else {
println!("{} {}", Blue.bold().paint("[~]"), $name);
}
}
};
}
#[macro_export]
macro_rules! output {
($name:expr, $quiet:expr) => {
use ansi_term::Colour::RGB;
if !$quiet {
println!("{} {}", RGB(0, 255, 9).bold().paint("[>]"), $name);
}
};
($name:expr) => {
use ansi_term::Colour::RGB;
println!("{} {}", RGB(0, 255, 9).bold().paint("[>]"), $name);
};
($name:expr, $greppable:expr, $accessible:expr) => {
use ansi_term::Colour::RGB;
// if not greppable then print, otherwise no else statement so do not print.
if !$greppable {
if $accessible {
// Don't print the ascii art
println!("{}", $name);
} else {
println!("{} {}", RGB(0, 255, 9).bold().paint("[>]"), $name);
}
}
};
}
#[macro_export]