commit 84cde06da20a968020de17b90c05bc5299d5ec3f Author: Fehér Roland Ádám Date: Mon Jun 1 12:17:46 2026 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b7d3f3e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +arpscan.json +nmaplog.txt diff --git a/arpscan.sh b/arpscan.sh new file mode 100755 index 0000000..d34b265 --- /dev/null +++ b/arpscan.sh @@ -0,0 +1,116 @@ +#!/usr/bin/bash + +# check for nmap and jq +# check for root + +starttime="$(date '+%Y-%m-%d %H:%M:%S')" + +if [ -f arpscan.json ] +then + #tempjson=$(jq '.ips += {} | .ips = ([ .ips | to_entries[] | select(.value.reserved == true) ] | from_entries)' arpscan.json) + tempjson=$(jq '.ips += {} | .ips=(.ips|to_entries|map_values(.value.online=false)|from_entries)' arpscan.json) + #tempjson="$(cat arpscan.json)" + if [ $? -ne 0 ] + then + echo "Failed to load network JSON" 1>&2 + exit 1 + fi +else + exit 1 +fi + +jsonescape() { + jq -Rs . < <(printf "%s" "${1}") +} + +foundhost() { + tempjson=$(jq "$(jsonescape "${1}") as \$ip|.ips[\$ip].mac=$(jsonescape "${2}")|.ips[\$ip].online=true" <<< "${tempjson}") +} + +doscan() { + local nmaplog + nmaplog=$(sudo nmap -sn -n 192.168.16.0/24) + if [ $? -ne 0 ] + then + echo "nmap failed" 1>&2 + return 1 + fi + cat <<< "${nmaplog}" > nmaplog.txt + + local parsestep + local ipaddr + parsestep=waitheader + ipaddr= + + while read -r line + do + case $parsestep in + waitheader) + if [[ "${line}" != "Starting Nmap "* ]] + then + echo "Nmap start header expected, got ${line}" 1>&2 + return 1 + fi + parsestep=hostdata + ;; + hostdata) + if [[ "${line}" == "Nmap done: "* ]] + then + parsestep=scandone + elif [[ "${line}" =~ ^Nmap\ scan\ report\ for\ (.*)$ ]] + then + ipaddr="${BASH_REMATCH[1]}" + elif [[ "${line}" =~ ^Host\ is\ up(\ \(.*\))?.$ ]] + then + continue + elif [[ "${line}" =~ ^MAC\ Address:\ ([A-F0-9:]{17}).*$ ]] + then + local macaddr + macaddr="${BASH_REMATCH[1]}" + if [[ "${ipaddr}" == "" ]] + then + echo "Found MAC without IP" 1>&2 + return 1 + fi + foundhost "${ipaddr}" "${macaddr}" + if [ $? -ne 0 ] + then + echo "Registering host failed" 1>&2 + return 1 + fi + ipaddr= + else + echo "Failed to parse: ${line}" 1>&2 + return 1 + fi + ;; + scandone) + echo "Unexpected data after scan: ${line}" 1>&2 + return 1 + ;; + *) + echo "Invalid parse step: ${parsestep}" 1>&2 + return 1 + ;; + esac + done <<< "$nmaplog" + #done < nmaplog.txt +} + +doscan +if [ $? -ne 0 ] +then + echo "Scan failed" 1>&2 + exit 1 +fi + +## make sure the MAC vendor and device/port fields exist +tempjson="$(jq '.macvendor+={}|.devices+=[]' <<< "${tempjson}")" + +tempjson="$(jq '.ips=(.ips|to_entries|sort_by(.key|split(".")|to_entries|map((.value|tonumber)*pow(256;3-.key))|add)|from_entries)' <<< "${tempjson}")" + +fancyjson="$(jq '. as $root|$root.macvendor|to_entries|map({key:.value[],value:.key})|from_entries as $vendors|($root.devices|map(.*(.ports[]|with_entries(.key|="port_"+.))))|map_values(del(.ports))|map({key:.port_mac,value:.})|from_entries as $ports|$root.ips|map_values(.port=$ports[.mac]|.vendor=$vendors[.mac[0:8]])' <<< "${tempjson}")" + +jq -r '(["[?]","MAC","Vendor","Model","IP","User","Device","Port"],(to_entries|sort_by(.key|split(".")|to_entries|map((.value|tonumber)*pow(256;3-.key))|add)|.[]|[if .value.online then "[#]" else "[ ]" end,.value.mac,.value.vendor,.value.port.model,.key,.value.port.user,.value.port.desc,.value.port.port_name]))|@tsv' <<< "${fancyjson}" | column -ts $'\t' + +cat <<< "${tempjson}" > arpscan.json