Setting the System Hostname from DHCP in Ubuntu 11.10

The Problem

While implementing a naming scheme (I’m going with the not very creative name-after-types-of-alcohol naming scheme) for machines at work, I wanted bash prompt to reflect my machine’s current hostname as distributed by DHCP.  I’m running Ubuntu 11.10 on my laptop, a Dell Inspiron N5110.

By default, Linux systems determine their hostname by using the hostname command. hostname, in turn, uses uname(2) to determine the hostname.

Ubuntu 11.10 uses NetworkManager as tool of choice for users to configure network interfaces and NetworkManager seems to be using dhclient as its DHCP client. I’m personally more familiar with dhcpcd, but that’s neither here nor there (or so I thought).

What I wanted to accomplish was simple. I wanted Ubuntu to set my hostname dynamically upon receiving an address from DHCP, so that hostname returned a name that came from DHCP. I know that DHCP has a mechanism by which clients can request a particular hostname, but this is the opposite of what I want. I want DHCP to tell me my hostname, and I want Ubuntu to set it. Here’s how I made that happen.

 

Background

In the good old days, when I was one of the cool kids drinking the Gentoo kool-aid, I remember dealing with this exact same issue using a switch to dhcpcd. It turns out that it was the -H switch.  From man dhcpcd:

-H
Forces dhcpcd to set hostname of the host to the hostname option supplied
by DHCP server. By default dhcpcd will NOT set hostname of the host to the
hostname option received from DHCP server.

Great! This is exactly what I want.

Unfortunately, as I mentioned before, NetworkManager doesn’t use dhcpcd. It uses dhclient, provided by the isc-dhcp-client package. The simple functionality that I want can’t be unique to dhcpcd, can it?

Well, it is, sort of. dhclient doesn’t natively support this functionality, but instead offers a hook-based interface in which scripts can be run at certain times in the address-acquisition process. The dhclient-script program provides the framework for this hook-based interface. It looks for hooks in two places: /etc/dhcp/dhclient-enter-hooks.d/ and /etc/dhcp/dhclient-exit-hooks.d/. For our purposes, we want to set our hostname based upon the address acquired from DHCP, so we’ll have to place our script in the latter location, as it should be executed as an “exit” hook.

 

The Solution

The script itself has fortunately already been written by the Debian folks. Look here for the original article if you are interested, but here is the script, modified slightly to work on Ubuntu 11.10:

#!/bin/sh
# Filename:     /etc/dhcp/dhclient-exit-hooks.d/hostname
# Purpose:      Used by dhclient-script to set the hostname of the system
#               to match the DNS information for the host as provided by
#               DHCP.
#

if [ "$reason" != BOUND ] && [ "$reason" != RENEW ] \
   && [ "$reason" != REBIND ] && [ "$reason" != REBOOT ]
then
        return
fi

echo dhclient-exit-hooks.d/hostname: Dynamic IP address = $new_ip_address
hostname=$(host $new_ip_address | cut -d ' ' -f 5)
echo $hostname > /etc/hostname
hostname $hostname
echo dhclient-exit-hooks.d/hostname: Dynamic Hostname = $hostname

Save this script in /etc/dhcp/dhclient-exit-hooks.d/ and your system’s hostname will henceforth be set automatically by dhclient.

 

Update

Since saving this script, I’ve been noticing that I’d receive strange hostnames from DHCP. It turns out that the reason for this was virtual machines requesting an IP address. To fix this, we need to add some sort of specification to the hostname script that only updates our hostname if the response from DHCP is intended for a real (not virtual) interface.

To support this kind of logic, dhclient-script provides the $interface variable. From man dhclient-script:

The interface name is passed in  $interface,  and  the  media  type  is passed in $medium.

So, we add this to the top of our script:

# Do not update hostname for virtual machine IP assignments
if [ "$interface" != "eth0" ] && [ "$interface" != "wlan0" ]
then
    return
fi

Add a test block for each “real” interface that could receive a response from DHCP for your machine.

Post a comment or leave a trackback: Trackback URL.

Leave a comment