-
-
Save Qhilm/6d5b76732bef21c7a2838b678f5f0665 to your computer and use it in GitHub Desktop.
opn-arp.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/bash | |
# This file is located under /usr/local/bin/opn-arp.sh | |
# Source configuration file | |
. /usr/local/etc/opn-arp.conf # This file defines: | |
# - interfaces to be used | |
# - dhcpv6_range_start | |
# - dhcpv6_range_stop | |
# Define file paths for IPv4 and IPv6 ARP/NDP tables | |
CURRENT4="/tmp/current_arp_table4.txt" | |
STATIC4="/tmp/static_arp_table4.txt" | |
OUT4="/tmp/result_arp_table4.txt" | |
CURRENT6="/tmp/current_arp_table6.txt" | |
STATIC6="/tmp/static_arp_table6.txt" | |
OUT6="/tmp/result_arp_table6.txt" | |
# Ensure all necessary files exist | |
touch $CURRENT4 $STATIC4 $OUT4 $CURRENT6 $STATIC6 $OUT6 | |
# Function to normalize IPv6 address | |
normalize_ipv6() { | |
local ip=$1 | |
# Remove interface name if present | |
ip=${ip%\%*} | |
# Expand :: to appropriate number of :0: | |
if [[ $ip == *::* ]]; then | |
local colons=${ip//[^:]}; | |
local missing=$((8 - ${#colons})) | |
local replacement=$(printf ':0%.0s' $(seq 1 $missing)) | |
ip=${ip/::/$replacement:} | |
fi | |
# Add leading zeros to each group | |
ip=$(echo $ip | awk -F: '{for(i=1;i<=NF;i++) printf "%04x:", substr("0000" $i, length($i)+1)}' | sed 's/:$//') | |
echo $ip | |
} | |
# Function to compare two IPv6 addresses | |
compare_ipv6() { | |
local a=$(normalize_ipv6 $1) | |
local b=$(normalize_ipv6 $2) | |
if [[ $a < $b ]]; then | |
echo -1 | |
elif [[ $a > $b ]]; then | |
echo 1 | |
else | |
echo 0 | |
fi | |
} | |
# Function to check if an IPv6 address is in the specified range | |
is_ipv6_in_range() { | |
local ip=$1 | |
local start=$2 | |
local stop=$3 | |
# Check if it's a link-local address (starts with fe80) | |
if [[ $ip == fe80::* ]]; then | |
return 0 # Always include link-local addresses | |
fi | |
# Check if it's a ULA address (starts with fd) | |
if [[ $ip == fd* ]]; then | |
return 0 # Always include ULA addresses | |
fi | |
local cmp_start=$(compare_ipv6 "$ip" "$start") | |
local cmp_stop=$(compare_ipv6 "$ip" "$stop") | |
[ $cmp_start -ge 0 ] && [ $cmp_stop -le 0 ] | |
} | |
# Main loop | |
while true | |
do | |
# Clear previous content | |
> "$CURRENT4" | |
> "$CURRENT6" | |
if [ -z "$interfaces" ] | |
then | |
# If no specific interfaces are defined, check all | |
arp -an | grep -v 'incomplete' | grep -v 'permanent' | awk '{print $2 " | " $4}' > "$CURRENT4" | |
ndp -an | grep -v 'incomplete' | grep -v 'permanent' | grep -v 'Neighbor' | awk '{print $1 " | " $2}' | while read -r line; do | |
ip=$(echo "$line" | cut -d '|' -f1 | tr -d ' ') | |
if [ -z "$dhcpv6_range_start" ] || [ -z "$dhcpv6_range_stop" ] || is_ipv6_in_range "$ip" "$dhcpv6_range_start" "$dhcpv6_range_stop"; then | |
echo "$line" >> "$CURRENT6" | |
fi | |
done | |
echo "Processed all interfaces" | |
else | |
# If specific interfaces are defined, check only those | |
for a in $interfaces | |
do | |
echo "Processing interface: $a" | |
arp -an | grep -v 'incomplete' | grep -v 'permanent' | grep "$a" | awk '{print $2 " | " $4}' >> "$CURRENT4" | |
ndp -an | grep -v 'incomplete' | grep -v 'permanent' | grep -v 'Neighbor' | grep "$a" | awk '{print $1 " | " $2}' | while read -r line; do | |
ip=$(echo "$line" | cut -d '|' -f1 | tr -d ' ') | |
if [ -z "$dhcpv6_range_start" ] || [ -z "$dhcpv6_range_stop" ] || is_ipv6_in_range "$ip" "$dhcpv6_range_start" "$dhcpv6_range_stop"; then | |
echo "$line" >> "$CURRENT6" | |
fi | |
done | |
done | |
fi | |
# Compare current and static tables, output new entries | |
comm -2 -3 <(sort -u "$CURRENT4") <(sort -u "$STATIC4") > "$OUT4" | |
comm -2 -3 <(sort -u "$CURRENT6") <(sort -u "$STATIC6") > "$OUT6" | |
# Log and add new IPv4 entries | |
while read -r line; do | |
logger -p daemon.notice "New IPv4/MAC pair seen: $line" | |
echo "$line" >> "$STATIC4" | |
done < "$OUT4" | |
# Log and add new IPv6 entries | |
while read -r line; do | |
logger -p daemon.notice "New IPv6/MAC pair seen: $line" | |
echo "$line" >> "$STATIC6" | |
done < "$OUT6" | |
# Sort and remove duplicates from static tables | |
sort -u -o "$STATIC4" "$STATIC4" | |
sort -u -o "$STATIC6" "$STATIC6" | |
# Wait before next iteration | |
sleep 5 | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment