Tag Archives: technology

avahi and DNS

Related to my last posting, sudo was lagging when attempting to resolve hostnames unique to local network (my work’s domain). Anyway, after strace-ing, I found that sudo was timing-out while using avahi to resolve these local names.

From strace sudo ls:

connect(7, {sa_family=AF_FILE, path="/var/run/avahi-daemon/socket"}, 110) 
    = 0
fcntl64(7, F_GETFL)                     = 0x2 (flags O_RDWR)
fstat64(7, {st_mode=S_IFSOCK|0777, st_size=0, ...}) = 0
    = 0xb77e3000
_llseek(7, 0, 0xbfebaf98, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
write(7, "RESOLVE-HOSTNAME-IPV4 newcastle."..., 49) = 49
read(7, "-15 Timeout reached\n", 4096)  = 20

That explains the lag I was experiencing with sudo.

The solution is in NSCD’s configuration: I want avahi consulted last, after DNS and hosts have been exhausted. In my case, DNS would produce the correct answer.

Looking at /etc/nsswitch.conf:

hosts:          files mdns4_minimal [NOTFOUND=return] dns mdns4

Just as suspected: avahi (multicast DNS) is being consulted before DNS. After switching the two entries (DNS and mdns4_minimal) and running sudo, no more lag! Problem solved.


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.



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:

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:

# 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 ]

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.



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" ]

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

%d bloggers like this: