discovery.sh: update to v2.64
parent
86ea31a1d6
commit
5a020a04f1
@ -1,41 +1,185 @@
|
||||
#!/bin/sh
|
||||
export PATH=/bin:/usr/bin:/sbin:/usr/sbin:/home/root
|
||||
# Network discovery script v2.0 - ARM and MIPSR2 - 05/2024 - rs232
|
||||
# Network discovery script v2.64 - ARM and MIPSR2 - 02/2025 - rs232
|
||||
#------------------------------------------------------
|
||||
# FreshTomato Network Discovery - usage
|
||||
# FreshTomato Network Discovery - usage
|
||||
#
|
||||
# default (or arping) = arping scanning
|
||||
# traceroute = uses a traceroute discovery
|
||||
# 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"
|
||||
subnet_mask=$(echo "$input_cidr" | cut -d '/' -f 2)
|
||||
num_addresses=$((2 ** (32 - subnet_mask)))
|
||||
ip_address=$(echo "$input_cidr" | cut -d '/' -f 1)
|
||||
ip_int=0
|
||||
for octet in $(echo "$ip_address" | tr '.' ' '); do
|
||||
ip_int=$((ip_int * 256 + octet))
|
||||
done
|
||||
first_ip_int=$((ip_int & ~(num_addresses - 1)))
|
||||
last_ip_int=$((first_ip_int + num_addresses - 1))
|
||||
for i in $(seq 1 $((num_addresses - 2))); do
|
||||
current_ip_int=$((first_ip_int + i))
|
||||
printf "%d.%d.%d.%d\n" $((current_ip_int >> 24 & 255)) $((current_ip_int >> 16 & 255)) $((current_ip_int >> 8 & 255)) $((current_ip_int & 255))
|
||||
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 | 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
|
||||
}
|
||||
|
||||
[ "$(ps w | grep 'traceroute -i\ | arping -q' | grep -v grep | wc -l)" -gt 0 ] && {
|
||||
logger "Device List Discovery already running - exiting ..."
|
||||
exit
|
||||
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
|
||||
}
|
||||
|
||||
for bridge in $(brctl show | grep -Eo ^br[0-9]); do
|
||||
cidr=$(ip addr list dev $bridge | grep inet | awk '{print $2}')
|
||||
ip=$(echo $cidr | cut -d/ -f1)
|
||||
iplist $cidr | while read -r ip_address; do
|
||||
if [ -z $1 ] || [ $1 == "arping" ]; then usleep 1500 && arping -q -c1 -w1 -I $bridge $ip_address &>/dev/null &
|
||||
elif [ $1 == "traceroute" ]; then traceroute -i $bridge -r -F -m1 -q1 -s $ip $ip_address &>/dev/null &
|
||||
fi
|
||||
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
|
||||
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
|
Loading…
Reference in New Issue