getting your ip-address

A friend asked me how to retrieve your IP-number in emacs; he needs it to
figure out in which of various networks he lives, to update proxy settings and the like. He
had found a decade-old function get-ip-address on the internet, and
thought (correctly!) that it can't be that hard.



So, fortunately, it wasn't too hard to do it a bit better, esp. with all the
improvements in emacs in the last ten years.



The somewhat-ugly-but-it-works solution is to use the output of the ifconfig
tool:

(defun get-ip-address (&optional dev)
"get the IP-address for device DEV (default: eth0)"
(let ((dev (if dev dev "eth0")))
(substring ;; chop the final "\n"
(shell-command-to-string
(concat
"ifconfig " dev
"|grep 'inet addr'|sed 's/.*inet addr:\\(\\([0-9\.]\\)*\\).*/\\1/'"))
0 -1)))


Now, calling (get-ip-address "eth0") or (get-ip-address "lo") in your scripts
will get you the IP-number. Obviously, this only works on systems that have
this ifconfig, and is also vulnerable to small changes in the output. Don't even ask about IPv6.



The solution does give us a nice example of using shell-command-to-string,
which is really useful function to integrate with all kinds of external tools;
the difference with decade-old get=ip-address is striking.



However, we can do even better in these modern times. More recent versions of
emacs provide nice networking functionality:

(defun get-ip-address (&optional dev)
"get the IP-address for device DEV (default: eth0)"
(let ((dev (if dev dev "eth0")))
(format-network-address (car (network-interface-info dev)) t)))


All fine - but unfortunately, this does not work on Windows; there is no such
thing as network-interface-info there, not even in the latest Emacs
incarnations. Is there nothing else we can do on Windows? Well… we can go
back to the first solution (using shell-command-to-string, and see if we can
use it with Windows' ipconfig tool. Something like:
(defun get-ip-address () 
"Win32: get the IP-address of the first network interface"
(let ((ipconfig (shell-command-to-string "ipconfig | findstr Address")))
(string-match "\\(\\([0-9]+.\\)+[0-9]+\\)" ipconfig)
(match-string 0 ipconfig)))


The Windows version does not support choosing the interface; I'll leave that
as an excercise to a reader with some more Win-fu; that same reader might also
have a solution that does not involve ipconfig, but uses some Win32-API. And
of course, that user is invited to help the emacs development team to add a
Win32 version of network-interface-info.

No comments:

Post a Comment

Followers

Popular Posts