Productively Distracted
Posted Friday November 30, 2012 around 8:21 PM

I recently needed to perform an ICMP echo (aka a ping) in Clojure. After some research I found the java method InetAddress.isReachable. I wrapped this as a clojure function like so:

(ns pinger
  (import (java.net InetAddress)))

(defn ping
  [host]
  (.isReachable (InetAddress/getByName host) 5000))
Download

Running this worked great on bigjason.com:

(println (ping "bigjason.com"))
;; => true
Download

However when I tried pinging one of my routers, it failed:

(println (ping "192.168.1.1"))
;; => false
Download

While a manual ping worked just fine:

$ ping -c 4 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: icmp_seq=0 ttl=64 time=0.776 ms
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=3.134 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=3.198 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=0.995 ms

--- 192.168.1.1 ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.776/2.026/3.198/1.143 ms
Download

Confused I did some more research and found this in the documentation of isReachable:

A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host.

A little checking revealed the router was indeed blocking port 7. So figuring it must be a privilege problem, I ran it again with sudo. It worked exactly as expected sending out an actual ping.

Moral

If you want to send out an ICMP message on a *nix based system with the jvm, you must be root.

blog comments powered by Disqus