How to find all devices (IP Address, Hostname, MAC Address) on local network

bonjourdnsNetwork

I've read almost every thread related to this, yet no one has quite made it easy to access a table like the following.

  IP Address     Hostname        MAC Address
  192.168.1.10 | myAppleTV     | 02:78:42:9b:bb:12
  192.168.1.10 | myiPhone      | b2:18:4a:3a:42:22
  192.168.1.10 | myiMac        | 09:17:a2:95:c4:00
  192.168.1.10 | myCanonPrinter| a0:ea:72:77:b4:aa

Most of the time I use arp -a and there is also dns-sb, but none of them make it easy to find out 3 key pieces of information whenever I am messing around on the network, i.e., IP Address, Hostname and MAC Address. I am surprised that there isn't a utility that accomplishes this!

Best Answer

If using a third-party utility is not an issue for you, then I recommend giving these a try:

arp-scan (available via Homebrew)

brew install arp-scan
arp-scan --localnet

fing (download and install the "Desktop Embedded CLI" package from fing.com or via Homebrew brew cask install fing)

sudo fing -r 1 -d true -o table,text

Both utilities have a number of additional modes and features. I suggest reading the manuals fully to get the most out of them.

If you need to avoid using third-party tools then here's a way to do something similar with built-in commands. You can run these interactively, but it's probably easier to save it as a script. N.B. to keep it short, this script does no error checking, and only works on /24 subnets. Modifying it to work on subnets of other sizes is left as an exercise to the reader :)

#!/usr/bin/env bash
tab=$'\t'
pIF=$(echo "show State:/Network/Global/IPv4" | scutil | awk -F: '/PrimaryInterface/{sub(/ /,"",$2); print $2}')
sn=$(ipconfig getifaddr $pIF | sed -En 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/p')
for i in {1..254}; do ping -i0.1 -W100 -c1 $sn.$i | grep from; done
arp -a | grep $pIF | sed -e 's/^\?/unnamed/' -e "s/\ at\ /${tab}/g" -e "s/\ on\ /${tab}/g" -e 's/\ ifscope.*$//g' | awk 'BEGIN { FS="\t"; OFS="\t"; printf "%-17s\t%-15s\t%s\n", "MAC","INTERFACE","HOSTNAME (IP)" } { if($2!="(incomplete)") {printf "%-17s\t%-15s\t%s\n",$2,$3,$1}}'

This should output something like:

MAC                 INTERFACE       HOSTNAME (IP)
0:90:b:7a:85:62     en0             r1.lan (192.168.20.1)
2c:36:f8:48:2b:47   en0             cisco-sg300-10p.lan (192.168.20.2)
84:78:ac:a6:95:a0   en0             cisco-sg300-20.lan (192.168.20.3)
b4:fb:e4:cb:93:85   en0             wap1.lan (192.168.20.10)
0:11:32:10:cd:c1    en0             nas.lan (192.168.20.20)
0:11:32:3d:99:c9    en0             nas2.lan (192.168.20.21)
0:11:32:10:cd:c1    en0             unnamed (192.168.20.23)
d4:4b:5e:fe:6a:75   en0             brwd44b5efe6a75.lan (192.168.20.90)