We are finally our own master of our subnet! In this post I will describe how we went from static to dynamic IP addresses using dnsmasq.

In the past, we shared it with other work groups, which made it unreasonable to setup NFS homes, DHCP and NIS (No, we do not want to use Kerberos yet. It seems too much hassle to set up.) For the future we want to lower the load on the network and system administrators, notably me :-). To that end I started to migrate our workgroups network configuration from static to dynamics IPs.

We use already a DHCP server for the nodes of our cluster. So it should be straight forward to create a IP <—> MAC address mapping. The DHCP server in question is dnsmasq and it works very nicely for the cluster. It even provides an TFTP server for the diskless nodes.

The format of the host file ist very simple:

…
dhcp-host=00:23:54:91:86:51,linux-02,192.168.0.2,12h
dhcp-host=00:23:54:91:86:61,linux-03,192.168.0.3,12h
…

That is, every line contains: dhcp-host=MAC_ADRESS,NAME,IP,LEASE_TIME.

How do we get this information. One way is to ask via arping every ip address and extract from the output its MAC address 1:

root@master-node:~# arping -c 1 192.168.0.1
ARPING 192.168.0.1 from 192.168.0.254 eth0
Unicast reply from 192.168.0.1 [C4:7D:4F:E7:99:80]  1.170ms
Sent 1 probes (1 broadcast(s))
Received 1 response(s)

The information we want is in the Unicast reply line in columns 4 and 5. So we grep for reply and we will extract the information with awk {print $4 " " $5}. In order to make this for 127 hosts, I used parallel to simultaneously query many hosts and extract the Information with a load of pipes (I am sure it could all be done in awk … but this was straight forward without fiddling too much with regular expressions):

	seq 129 254|parallel "arping -f -w 0.1 -c1 192.168.0.{1}" \
	|grep reply| awk '{print $4 " " $5 }'\
	|sed 's/\[//' |sed 's/\]//' | tee ip_mac

and send the two column output to a file ip_mac.

Next step is to create the IP <—> hostname mapping:

    for i in {129..254}; do
    	echo -n "192.168.0.$i "
    	host 192.168.0.$i|grep -o -e "[a-z0-9-]*.somedomain.duh"\
    		|| echo ""
    done | tee ip_host

And lastly, we need to combine these two data sets:

#!/usr/bin/python
ip_mac = open('ip_mac').readlines()
ip_host = open("ip_hostname").readlines()
    
for ipmac in ip_mac:
    ip,mac = ipmac.strip().split()
    for iphost in ip_host:
    try:
        iph,host = iphost.strip().split()
    # host has no hostname
    except: 
        iph=iphost.strip()
        host=""
    if ip==iph:
        if host == "":
            print "#dhcp-host=%s,%s,%s,12h"%(ip,mac.lower(),host)
        else:
            print "dhcp-host=%s,%s,%s,12h"%(ip,mac.lower(),host)

I think there are easier ways, and there are some inconveniences:

  • If a host is not online, there will be no reply from arping, whence no MAC address
  • ?
  1. One could also use the arp -a command, but this lists only some of the hosts.