LAN IP Address Detector

Say you want to SSH into that box downstairs and you can't remember the IP address. And you're too lazy to bring up a browser, log into your cable modem, navigate through three menus to the list of current DNS assignments and figure it out from there. You try pinging some possibilities, but — the gods are laughing at you — one's your printer, another's your blue-ray machine, and the next few never answer.

Well, this little script will try pinging all those final octets on your subnet for you. And since it takes at least a second for ping to timeout and you don't want to wait that times the number of unused final octets on your LAN to get your answer, it launches them in parallel. Takes about 2 seconds to test all 255 of them.

The script is written in Common Lisp, using SBCL threads functions. But you don't have to bring up SBCL to run it — I wrapped it as an executable script. Searches 192.168.0.x by default, but you can change that with a command line parameter.

The coolest thing in the script is the FOREACH macro I wrote that manages the threading with the ability to limit the maximum number of active threads at a time. I found this necessary because launching 255 ping processes (I use the Linux iputils system call) can sometimes generate an error from too many file handles open. This puzzled me at first — since ulimit -n says I have 1024 available as a user. But then I realized that there's probably piping involved and each of those gets a file handle. Now, I could have increased the ulimit, but I'd been wanting to write a foreach loop with thread limit capability for awhile and this gave me an excuse. (Reason: with a 4-core hyperthreaded Intel board there's no reason to ever launch more than, say, 8 parallel proceseses that are intense number-crunchers; they just step on each other paging state. Proof: when I limit the number of simultaneous crunch-threads to 8 or less it takes (a little) less time than when I launch, say, 1000 of them.)

Here's the code.

And here's the output of a run: