You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
4.9 KiB
Bash
185 lines
4.9 KiB
Bash
#!/bin/sh
|
|
export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/home/root
|
|
# Network discovery script v2.64 - ARM and MIPSR2 - 02/2025 - rs232
|
|
#------------------------------------------------------
|
|
# FreshTomato Network Discovery - usage
|
|
#
|
|
# arping = * scanning via arping (preferred)
|
|
# traceroute = scanning via traceroute
|
|
# nc = scanning via netcat
|
|
# all = all the above in round-robin
|
|
#
|
|
# lan = * only LANs interfaces
|
|
# wan = only WANs interfaces
|
|
# both = scan LANs and WANs
|
|
#
|
|
# clear = removes dirty records from the arp table post scan
|
|
#
|
|
# <5-200> = default 60, maximum number of concurrent scans
|
|
#------------------------------------------------------
|
|
script_name=$(basename "$0")
|
|
pid_file="/tmp/var/run/${script_name}.pid"
|
|
|
|
cleanup() {
|
|
rm -f "$pid_file"
|
|
exit 0
|
|
}
|
|
|
|
trap cleanup INT TERM EXIT
|
|
|
|
if [ -e "$pid_file" ]; then
|
|
pid_age=$(($(date +%s) - $(stat -c %Y "$pid_file")))
|
|
if [ "$pid_age" -gt 120 ]; then
|
|
echo "PID file is older than 2 minutes. Removing stale PID file."
|
|
rm -f "$pid_file"
|
|
fi
|
|
fi
|
|
|
|
debug=$(nvram get discovery_debug 2>/dev/null)
|
|
debug="${debug:-0}"
|
|
[ "$debug" -eq 1 ] && { echo "Debugging..."; date >> /tmp/discovery.debug; echo "$@" >> /tmp/discovery.debug; }
|
|
lim=$(echo "$@" | grep -oE '[0-9]+' | head -n 1 | awk '{if($1 < 5) print 5; else if($1 > 200) print 200; else print $1}')
|
|
[ -z "$lim" ] && lim=60
|
|
alias slp='usleep 250000'
|
|
alias low='nice -n 19'
|
|
tmp="/tmp/discovery.tmp"
|
|
scan=0
|
|
cl=0
|
|
runlan=0
|
|
runwan=0
|
|
fkill=0
|
|
|
|
iplist() {
|
|
input_cidr="$1"
|
|
cidr=$(echo "$input_cidr" | cut -d '/' -f 2)
|
|
ip=$(echo "$input_cidr" | cut -d '/' -f 1)
|
|
awk -v cidr="$cidr" -v ip="$ip" '
|
|
BEGIN {
|
|
split(ip, a, ".");
|
|
ip_int = a[1] * 256^3 + a[2] * 256^2 + a[3] * 256 + a[4];
|
|
num_addrs = 2^(32 - cidr);
|
|
base_ip = int(ip_int / num_addrs) * num_addrs;
|
|
for (i = 1; i < num_addrs - 1; i++) {
|
|
current_ip = base_ip + i;
|
|
printf "%d.%d.%d.%d\n",
|
|
int(current_ip / 256^3) % 256,
|
|
int(current_ip / 256^2) % 256,
|
|
int(current_ip / 256) % 256,
|
|
current_ip % 256;
|
|
}
|
|
}'
|
|
}
|
|
|
|
check_procs() {
|
|
case "$1" in
|
|
arping) pidof arping ;;
|
|
traceroute) pidof traceroute ;;
|
|
nc) pidof nc ;;
|
|
esac | wc -w
|
|
}
|
|
|
|
md5_param=$(echo "$@" | md5sum | cut -d' ' -f1)
|
|
if [ -f "$tmp" ]; then
|
|
if ! grep -q "$md5_param" "$tmp"; then
|
|
# Kill previous instances with different parameters
|
|
for PID in $(pidof "$script_name"); do
|
|
[ "$PID" != "$$" ] && kill -9 "$PID" &>/dev/null
|
|
done
|
|
# Kill scanning tools
|
|
for tool in arping traceroute nc; do
|
|
[ "$(check_procs "$tool")" -gt 0 ] && killall -q "$tool"
|
|
done
|
|
sleep 1
|
|
fkill=1
|
|
fi
|
|
else
|
|
echo 0 > "$tmp"
|
|
echo "$md5_param" >> "$tmp"
|
|
fi
|
|
|
|
for param in "$@"; do
|
|
case "$param" in
|
|
clear) cl=1 ;;
|
|
lan) runlan=1 ;;
|
|
wan) runlan=0; runwan=1 ;;
|
|
both) runlan=1; runwan=1 ;;
|
|
traceroute) scan=1 ;;
|
|
nc) scan=2 ;;
|
|
all) scan=$(head -1 "$tmp") ;;
|
|
esac
|
|
done
|
|
[ "$runlan" -eq 0 ] && [ "$runwan" -eq 0 ] && runlan=1
|
|
|
|
if [ -e "$pid_file" -a "$fkill" -ne 1 ]; then
|
|
echo "Status-devices - Background discovery processes already running; skipping this run." | tee /dev/tty | logger
|
|
cleanup
|
|
fi
|
|
|
|
scanthis() {
|
|
for iface in $this; do
|
|
cidr=$(ip a l dev "$iface" | grep inet | grep -v inet6 | awk '{print $2}')
|
|
[ "$(echo "$cidr" | cut -d/ -f2)" -lt 22 ] && {
|
|
echo "$iface - subnet mask shorter than /22. Too many IPs to scan - skipping..." | tee /dev/tty | logger
|
|
continue
|
|
}
|
|
[ "$(echo "$cidr" | cut -d/ -f2)" -lt 32 ] && {
|
|
ip=$(echo "$cidr" | cut -d/ -f1)
|
|
ipn=$(ip neigh show dev "$iface" | grep 'REACHABLE\|PERMANENT' | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
|
|
iplist "$cidr" | grep -vwE "$ip|$(echo "$ipn" | tr ' ' '\n')" | while read -r ip_addr; do
|
|
if [ "$scan" -eq 0 ]; then
|
|
while [ "$(check_procs arping)" -gt "$lim" ]; do slp; done
|
|
low arping -I "$iface" -q -c1 -w1 "$ip_addr" &>/dev/null &
|
|
elif [ "$scan" -eq 1 ]; then
|
|
while [ "$(check_procs traceroute)" -gt "$lim" ]; do slp; done
|
|
low traceroute -i "$iface" -r -F -m1 -q1 -s "$ip" "$ip_addr" &>/dev/null &
|
|
elif [ "$scan" -eq 2 ]; then
|
|
while [ "$(check_procs nc)" -gt "$lim" ]; do slp; done
|
|
low nc -w 1 "$ip_addr" &>/dev/null &
|
|
fi
|
|
done
|
|
wait
|
|
}
|
|
done
|
|
}
|
|
|
|
prune() {
|
|
ip n | grep -w "$1" | while read -r badip; do
|
|
ip=$(echo "$badip" | awk '{print $1}')
|
|
dev=$(echo "$badip" | awk '{print $3}')
|
|
ip neigh change "$ip" nud none dev "$dev"
|
|
done
|
|
}
|
|
|
|
echo $$ > "$pid_file"
|
|
|
|
[ "$runlan" -eq 1 ] && {
|
|
this=$(brctl show | grep -Eo ^br[0-9])
|
|
scanthis
|
|
}
|
|
|
|
unset wans
|
|
[ "$runwan" -eq 1 ] && {
|
|
[ "$(ip rule | grep -Eo 'WAN[1-4]' | sort -u | wc -l)" -gt 0 ] && {
|
|
for WAN in $(ip rule | grep -Eo 'WAN[1-4]' | sort -u); do
|
|
wans="$wans $(ip r l t "$WAN" | grep default | grep -Eo '[vlan|eth]+[0-9]{1,4}')"
|
|
done
|
|
} || {
|
|
wans=$(ip route | grep ^default | awk '{print $5}')
|
|
}
|
|
this="$wans"
|
|
scanthis
|
|
}
|
|
|
|
[ "$cl" -eq 1 ] && {
|
|
prune "FAILED\|INCOMPLETE"
|
|
usleep $((lim * 30000))
|
|
prune "STALE\|DELAY\|PROBE"
|
|
}
|
|
|
|
scan=$(((${scan:-0} + 1) % 3))
|
|
{
|
|
echo "$scan"
|
|
echo "$md5_param"
|
|
} >> "$tmp"
|
|
|
|
cleanup |