I just ran Fing against my wireless network. Using tcpdump
, it appears that Fing generates Address Resolution Protocol (ARP) request packets. ARP is a pretty simple protocol that runs at the Ethernet Protocol level (Data Link, OSI level 2). An ARP request packet has the broadcast address (ff:ff:ff:ff:ff:ff) as the "to" address, the Android phone's MAC and IP address as the "from" information, and an IP address that Fing wants to know about. It appears that Fing just marches through whatever subnet it's on, in my case 172.31.0.0/24, so 255 IP addresses, from 172.31.0.1 to 172.31.0.254. After the march, it appears to try IP addresses that haven't responded a second time. This looks to me like Fing tries IP addresses in batches, and relies on the underlying Linux kernel to buffer ARP replies, for a Fing thread to deal with as fast as it can. If Fing decides that there's a timeout, it resends. It's not clear to me how Fing (a Java program) gets the phone's Linux kernel to generate ARP packets.
The notorious nmap, invoked with -sn
, the "ping scan" flag, does the same thing. I did an strace
on nmap -sn 172.31.0.0/24
to see how it gets the kernel to send ARP requests. It looks like nmap
creates an ordinary TCP/IP socket, and calls connect()
on the socket to TCP port 80, with an IP address. nmap
must be doing this in non-blocking mode, as it does a large number of connect()
calls sequentially, faster than it would take for Linux to decide to time out a connect()
when there's no host with the IP address.
So there's your answer: create a TCP/IP socket, call connect()
with a particular port and IP address, then see what the error is. If the error is ECONNREFUSED, it's a live IP address, but nothing is listening on that port. If you get a TCP connection, that IP address has a host. IP addresses that the connect()
call times out for, don't have a machine associated. You need to batch the connect()
calls for speed, and you need to wait for connect()
calls to timeout to decide that an IP address does not have a machine associated with it.
connect()
is not part of it. Nmap uses the platform-dependent implementation ofeth_send
in libdnet. For Linux, this usessendto
on aPF_PACkET
raw socket. – bonsaiviking Mar 10 '16 at 19:56nmap
as root, it does do the raw socket things. After looking over the source code innmap..c
, there's a valueo.isr00t
that when set to false, causesnmap
to create regular TCP sockets, and callconnect()
on each IP address. When true, it does the raw socket thing. – Mar 10 '16 at 23:02