Originally published January 24, 2017 @ 1:32 am

A quick script to go through your DHCP server log and get a summary of MAC addresses and associated DHCP requests. The script will attempt to download the IEEE OUI list for identifying the manufacturers associated with the MAC addresses in your log. This is a fairly large text file, so the download may take a few minutes. Once downloaded, the script will not try to download the file again, unless it’s about three months old.

You may need to modify the f="/var/log/boot.log" to point to your DHCP server log file. Depending on the number of log entries, the script may take a while to run. Feel free to optimize it if you can. The output should look something like this:

MAC                IP               Status   Manufacturer        DHCPACK      DHCPDISCOVER DHCPINFORM   DHCPNAK      DHCPOFFER    DHCPRELEASE  DHCPREQUEST
1c:99:4c:b0:e8:22  192.168.22.155  down     Murata Manufacturi  1573         4            0            0            4            0            1575
20:d3:90:da:c2:6d  192.168.22.151  up       Samsung Electronic  10288        1            0            0            1            0            10288
28:b2:bd:4a:71:03  192.168.22.150  down     Intel Corporate     11662        31           0            25           30           0            11687
28:c6:71:06:4c:c3  192.168.22.159  up       Yota Devices OY     9535         31           0            6            31           0            9541

You can download the script here: dhcp_log_stats.

#!/bin/bash
f="/var/log/boot.log"
if [ ! -r "${f}" ]
then
	echo "Cannot access ${f}"
	exit 1
fi

ouif="/var/tmp/oui.txt"
ouiurl="http://standards.ieee.org/regauth/oui/oui.txt"
howold=90

if [ ! -f "${ouif}" ] || test $(find "${ouif}" -mtime +${howold})
then
	echo "Downloading IEEE Organizationally Unique Identifier. This will take a few minutes..."
	wget -q -O "${ouif}" "${ouiurl}"
	if [ -f "${ouif}" ]
	then
		sed -i 's/\r$//g' "${ouif}"
	else
		echo "Cannot download ${ouiurl}"
		exit 1
	fi
fi

IFS=$'\n' ; op_array=($(grep -oP "DHCP[A-Z]{1,}" "${f}" | sort -u)) ; unset IFS
IFS=$'\n' ; mac_array=($(grep -oE '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}' "${f}" | sort -u)) ; unset IFS
IFS=$'\n' ; ip_array=($(grep -oE "([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})" "${f}" | sort -u)) ; unset IFS

s1=$(echo "scale=0;`printf '%s\n' ${op_array[@]} | wc -L`+1"|bc)

printf "%-18s %-16s %-8s %-20s" "MAC" "IP" "Status" "Manufacturer"
for ((i = 0; i < ${#op_array[@]}; i++)) ; do printf "%-${s1}s" "${op_array[$i]}" ; done
printf "\n"

printf '%s\n' ${mac_array[@]} | while read mac
do
	ip_address=$(tac "${f}" | grep -m1 "DHCPOFFER.*${mac}" | grep -oE "([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})")
	if [ -z "${ip_address}" ] ; then ip_address="none" ; fi
	if [ $(ping -q -c 1 -W 5 ${ip_address} > /dev/null 2>&1 ; echo $?) -eq 0 ]
	then
		ip_online="up"
	else
		ip_online="down"
	fi
	oui=$(echo ${mac//[:.- ]/} | tr "[a-f]" "[A-F]" | egrep -o "^[0-9A-F]{6}")
	mfg="$(grep -m1 "^${oui}" "${ouif}" | cut -f3 -d$'\t' | cut -c1-18 | sed -e 's/,\.//g')"
	if [ -z "${mfg}" ]; then mfg="Unknown" ; fi
	printf "%-18s %-16s %-8s %-20s" "${mac}" "${ip_address}" "${ip_online}" "${mfg}"
	printf '%s\n' ${op_array[@]} | while read op
	do
		c=$(grep -cE "${op} .* ${mac} " "${f}")
		printf "%-${s1}s" ${c}
	done
	printf "\n"
done