Ping Everyone

Jan 6, 02:12 AM

So… I was bored (i.e. trying very hard not to do something that I should be doing), and decided to ping every address in IPv4 space. This is approximately equivalent to running down the street banging on doors to see who’s home, except that computers generally don’t mind being bothered. I mostly just wanted to see if my results looked anything like this: http://xkcd.com/195/

I decided (as I frequently do for coding whims) to use processing (free, wonderful, cross platform, http://processing.org ).

First, I ran into two small issues:

  1. Java, and thus Processing can’t ping. Honestly.
  2. There are 2^32 addresses in IPv4 space.

Limitation 1 was sidestepped by making a system call to the native ping command (in this case on Mac OS X, although my OS choice depends more on the computer that I’m sitting in front of than anything. Unfortunately this brought a new limitation: I couldn’t find a way to get ping to timeout faster than 1 second.

That combined with limitation 2 means that pinging every computer (assuming worst case as always) could take 136 years. Although I hope I’m around then, the odds are against it, and by then we’ll hopefully have migrated to IPv6 and beyond.

Aha, I think! I’ll just run the program in eleventy bajillion threads, each querying once a second! In this case, eleventy bajillion threads is 2^16 or 65535 threads, each running for 18.2 hours! That sounds more reasonable, but still unreasonable. Maybe I need to scale back my grand dreams of virtual door knocking and only knock on one door per street, or even one per city. Heartbroken, but perseverant I settled upon only knocking addresses ending in .1.1 (bad choice -I know. In retrospect I should have picked a random number from 2 to 253 each time to avoid magic).

And so, with one swift keystroke, the program ran.
Unfortunately, my poor laptop (MacBook Pro ~3 years old) couldn’t keep it together and froze before it even finished loading the threads.

/sigh

Errors encountered:

  1. You can’t just run eleventy bajillion instances of ping. Eventually (and only after a few hundred) you get a “resource unavailable” error. This was overcome by tossing a random sleep and recursive call in the ping function’s catch statement. Writing awful code is wonderful when you can get away with it*.
  2. You can’t just run eleventy bajillion threads. Each thread slows the computer down, increases context switching, eventually induces thrashing, and will bring even the most powerful computer to a grinding halt.

Thus, I slowed the program down to 100 active threads, most of which were just sitting there waiting for ping results. When one thread finishes pinging, the next one is started and so on. The result: (drumroll please!)

Well, that was boring. squints at the XKCD comic I guess I kind of see a match, but it could just as easily be a bug in my code. Speaking of which, the code!

If you’re curious, or want to provide 4 lines of lisp that improve on its functionality, it is available here:

http://duodec.net/fileman/netmap.pde

Simply download processing and run! The only OS dependant issue is the ping args/results. I scan for the “ 0.0%” returned by ping.

Tonight I’m going to set a new color coded version running that checks a.b.random(2-253).random(2-253) a few times for each a,b pair.

Edit:
Results here:

Edit 2:
Ealf on reddit.com informed me that
I took the liberty of reflowing your data to match the XKCD map. Comparing the two, you can see that most of the green space surrounding North America on the XKCD map (109-120 or so) is now in use — it’s been eaten by APNIC.
His result:

This looks much more like the XKCD map. The more you know.

I’m going to fix my program to create this map format and create a higher resolution version.

*During personal projects with very limited scope and zero importance
magneon

Fribbles, Processing

---

Comment

  1. Your map won’t look like the xkcd one unless you use the Hilbert curve to map your results. See here for more info:

    http://corte.si/posts/code/hilbert/explorer/index.html

    cortesi · Jan 7, 04:39 AM · #

  2. You don’t have to test the entire IP4 range. There are blocks that are not routable and therefor wont really add anything to your results, unless you are sitting inside one of them.

    The private blocks are listed below and reduce your pool by 17,891,328 addresses. :)

    10.0.0.0 – 10.255.255.255
    172.16.0.0 – 172.31.255.255
    192.168.0.0 – 192.168.255.255

    Richard · Jan 7, 08:16 AM · #

  3. Can you do raw sockets with Java? Then you could avoid ping process spawn overhead + mandatory 1 second wait for completion per IP.

    Jon · Jan 7, 11:48 AM · #

  4. I didn’t think to exclude the private IP ranges, that would help :). As for raw sockets? I don’t believe Java offers that level of network access, although I could be wrong.

    magneon · Jan 10, 12:09 AM · #

  5. Starting from Java 1.5.0 you can query a InetAddress to see if it is reachable. For example:

    int timeout = 100; // in milliseconds!
    String host = “82.197.131.89”; // by name or ip string.
    boolean ping = InetAddress.getByName(host).isReachable(timeout);

    or

    int timeout = 100: // in milliseconds!
    byte[] host = new byte[] {82, 197, 131, 89}; // by ip as byte array.
    boolean ping = InetAddress.getByAddress(host).isReachable(timeout);

    The latter example gives you the possibility to iterate in an easy manner over ip space.

    According to the Java API a JVM should implement the isReachable(timeout) method typically by sending an ICMP ECHO REQUEST if the privilege can be obtained from the underlying OS and fall back trying to open a TCP connection on port 7 (Echo service) if not.

    I enjoy what you’re doing and hope you’ll be bored more often ;-)

    Marco Borst · Jan 10, 02:39 PM · #

Commenting is closed for this article.

---