summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToby Vincent <tobyv@tobyvin.dev>2024-04-21 15:13:11 -0500
committerToby Vincent <tobyv@tobyvin.dev>2024-04-21 15:13:11 -0500
commite8cddad2374f8a440c8dbc688a5827af8a938c5b (patch)
tree6b1fec08640e93db5b8b4b6d2cc5abb3fe51c786
parentc34b0b3704499279aa675ff920479d84d8131ded (diff)
feat: add ICMP fallback and handle unspecified netnetlink
-rw-r--r--Cargo.lock267
-rw-r--r--Cargo.toml1
-rw-r--r--src/config.rs14
-rw-r--r--src/error.rs6
-rw-r--r--src/main.rs8
-rw-r--r--src/netlink.rs3
-rw-r--r--src/scanner.rs8
7 files changed, 294 insertions, 13 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e8ea21b..d0b1231 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,6 +18,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "anstream"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -94,6 +103,12 @@ dependencies = [
[[package]]
name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
@@ -279,12 +294,29 @@ dependencies = [
]
[[package]]
+name = "getrandom"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -297,6 +329,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+[[package]]
name = "ipnet"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -321,6 +359,16 @@ dependencies = [
]
[[package]]
+name = "lock_api"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -448,12 +496,18 @@ version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
dependencies = [
- "bitflags",
+ "bitflags 2.4.2",
"cfg-if",
"libc",
]
[[package]]
+name = "no-std-net"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
+
+[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -473,6 +527,35 @@ dependencies = [
]
[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -491,6 +574,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
+name = "pnet_base"
+version = "0.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c"
+dependencies = [
+ "no-std-net",
+]
+
+[[package]]
+name = "pnet_macros"
+version = "0.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "regex",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "pnet_macros_support"
+version = "0.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56"
+dependencies = [
+ "pnet_base",
+]
+
+[[package]]
+name = "pnet_packet"
+version = "0.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba"
+dependencies = [
+ "glob",
+ "pnet_base",
+ "pnet_macros",
+ "pnet_macros_support",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -509,6 +640,74 @@ dependencies = [
]
[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "regex"
+version = "1.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
+
+[[package]]
name = "rtnetlink"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -533,6 +732,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
name = "serde"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -562,13 +767,19 @@ dependencies = [
]
[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
name = "socket2"
-version = "0.5.5"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
+checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
dependencies = [
"libc",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -583,6 +794,7 @@ dependencies = [
"local-ip-address",
"netlink-packet-route",
"rtnetlink",
+ "surge-ping",
"thiserror",
"tokio",
]
@@ -594,6 +806,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
+name = "surge-ping"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "efbf95ce4c7c5b311d2ce3f088af2b93edef0f09727fa50fbe03c7a979afce77"
+dependencies = [
+ "hex",
+ "parking_lot",
+ "pnet_packet",
+ "rand",
+ "socket2",
+ "thiserror",
+ "tokio",
+ "tracing",
+]
+
+[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -664,6 +892,37 @@ dependencies = [
]
[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index f77a7ef..4b38969 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,3 +18,4 @@ netlink-packet-route = "0.19.0"
thiserror = "1.0.57"
ipnet = "2.9.0"
local-ip-address = "0.6.1"
+surge-ping = "0.8.1"
diff --git a/src/config.rs b/src/config.rs
index 5d49042..e7ee2e9 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -14,13 +14,17 @@ pub struct Config {
#[arg(short, long)]
pub port: Option<u16>,
- /// wait <TIMEOUT> (ms) when checking for open ports in ms (requires --port=<PORT>)
- #[arg(short, long, default_value_t = 250, requires = "port")]
+ /// <TIMEOUT> (ms) used for ICMP (or TCP when using --port=<PORT>)
+ #[arg(short, long, default_value_t = 250)]
pub timeout: u64,
- /// Discover hosts on <NETWORK> with <PORT> (requires --port=<PORT>)
- #[arg(short, long, id = "NETWORK", requires = "port")]
- pub scan: Option<IpNet>,
+ /// Include network neighbours
+ #[arg(short, long)]
+ pub neigh: bool,
+
+ /// Discover hosts on <NETWORK>
+ #[arg(short, long, id = "NETWORK")]
+ pub scan: Option<Option<IpNet>>,
/// include <NAME>. If <NAME> is a valid path or '-', hosts with be read from the file or
/// stdin, respectivly.
diff --git a/src/error.rs b/src/error.rs
index e98fe68..048440c 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -10,6 +10,12 @@ pub enum Error {
#[error("IO error: {0}")]
IO(#[from] std::io::Error),
+ #[error("Local IP error: {0}")]
+ LocalIp(#[from] local_ip_address::Error),
+
+ #[error("IpNet error: {0}")]
+ IpNet(#[from] ipnet::PrefixLenError),
+
#[error("Join error: {0}")]
Join(#[from] tokio::task::JoinError),
diff --git a/src/main.rs b/src/main.rs
index 6f60514..529c1ed 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,6 +15,8 @@ use tokio::{
mod config;
+const PAYLOAD: [u8; 8] = [0; 8];
+
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let config = Config::parse();
@@ -53,7 +55,9 @@ async fn main() -> Result<(), anyhow::Error> {
let cache = Arc::new(Mutex::new(cache));
let names = Arc::new(Mutex::new(names));
- join_set.spawn(sshr::netlink::neighbours(tx.clone()));
+ if config.neigh {
+ join_set.spawn(sshr::netlink::neighbours(tx.clone()));
+ }
if let Some(ip_net) = config.scan {
join_set.spawn(sshr::scanner::scan(tx.clone(), ip_net));
@@ -76,6 +80,8 @@ async fn main() -> Result<(), anyhow::Error> {
if block_in_place(|| TcpStream::connect_timeout(&addr, timeout)).is_err() {
return Ok(());
}
+ } else if surge_ping::ping(ip_addr, &PAYLOAD).await.is_err() {
+ return Ok(());
}
if let Some(s) = config.resolve.then(|| lookup_addr(&ip_addr).ok()).flatten() {
diff --git a/src/netlink.rs b/src/netlink.rs
index 2945a09..9e21dbc 100644
--- a/src/netlink.rs
+++ b/src/netlink.rs
@@ -1,8 +1,7 @@
-use std::{collections::HashSet, net::IpAddr};
+use std::net::IpAddr;
use futures::stream::TryStreamExt;
use netlink_packet_route::{
- address::AddressAttribute,
neighbour::{NeighbourAddress, NeighbourAttribute, NeighbourMessage, NeighbourState},
route::RouteType,
};
diff --git a/src/scanner.rs b/src/scanner.rs
index fa801e5..c51dffc 100644
--- a/src/scanner.rs
+++ b/src/scanner.rs
@@ -5,7 +5,13 @@ use tokio::{sync::mpsc::Sender, task::JoinSet};
use crate::Result;
-pub async fn scan(tx: Sender<IpAddr>, ip_net: IpNet) -> Result<()> {
+pub async fn scan(tx: Sender<IpAddr>, ip_net: Option<IpNet>) -> Result<()> {
+ let ip_net = match ip_net {
+ Some(net) if !net.addr().is_unspecified() => net,
+ Some(net) => IpNet::new(local_ip_address::local_ip()?, net.prefix_len())?,
+ None => IpNet::new(local_ip_address::local_ip()?, 24)?,
+ };
+
let mut join_set = JoinSet::new();
for ip_addr in ip_net.hosts() {
let tx = tx.clone();