Zero configuration software
This article describes implementations for the following ZeroconfTechnologies zero configuration technologies: ~- RFC3927 for self-assigned IPv4 addresses ~- mDNS for name lookup ~- DNS-SD for service discovery
Incidentally, this is the same set of technologies implemented by default by Apple Computer on Mac OS X, since Mac OS 10.2 (till Mac OS 10.1 SLP was used for service discovery).
For this, we needed four pieces of software: ~- IPv4LL code: needed for auto IP configuration ~- kernel patches: needed for auto IP configuration ~- mDNS software: needed for name lookup and discovery ~- name lookup hooks: needed for name lookup
Self-Assigned IPv4 address (RFC3927) software
There are two possible approaches to implement self-assigned IPv4 addresses. Best is to combine it with a DHCP client, and second-best it to put it in a stand-alone application. The advantage of combining it with a DHCP client is that is allows smooth transisition between link-local IP addresses (when no DHCP server is found) and routable IP addresses (when a DHCP server is available). Typically, for the stand-alone applications, a DHCP client is started at system boot time. If that fails (because no DHCP server could be found), the stand-alone application is run. Though this works fine for start-up, it does not deal with a situation where a DHCP server becomes available some time after system boot. Interaction between DHCP and self-assigned IP addresses is discussed in sections 1.9 and 2.11 of RFC3927, and Apple has advice on [mixing link-local and routable IP addresses].
RFC3927 implementations that are combined with a DHCP client are: ~- Apple [Darwin], in the bootp package ~- Microsoft Windows (not open source) ~- Elvis Pf√ºtzenreuter has [written a patch] for the [uDHCP client/server]
Stand-alone implementations are: ~- [Porchdog Howl] autoipd ~- [ZCIP] (Zero-Conf IP), a package that relies on the libnet and libpcap libraries. ~- [zeroconf], a package simular to ZCIP, that relies on the if utility. ~- [Busybox], an embedded Linux implementation ([in networking/zcip.c])
Note that the most (or even all?) of these last four packages originate from the same [code by Arthur van Hoff].
Not all functionality described in RFC3927 can be handled in user-space, by the above implementations. Two following two requirements need to be handled in kernel-space (at least for relatively monolitic kernels like Linux): ~- Broadcasting of ARP replies about 169.254/16 IP addresses. Normally, all ARP requests are broadcasted, and all ARP replies are unicasted. This aids timely conflict detection after network joins. See sections 2.5 and 4 of RFC 3927 for details. ~- After forced reconfiguration of the IP address, existing (TCP) connections need to be closed for security reasons. See section 5 of RFC 3927 for details.
Though there is reported existing kernel patch to deal with broadcasting 169.254/16 ARP replies, we were unable to find it, and subsequently LinkLocalARPMeasurements wrote our own patch.
We are not aware of the status regarding closing of TCP connections after IP reconfiguration. In our opinion this problem is generic for giving up and IP address, not just IP addresses in the 169.254/16 range. So a kernel should always close existing TCP connections after an network interface stops listening to a certain IP address.
Like IPv4 link-local addressing, the Multicast DNS (mDNS) and DNS Service Discovery (DNS-SD) are pioneered by Stuart Cheshire of Apple Computer. Both protocols use multicast name servers one every host to implement name lookup and service discovery,. In addition, DNS-SD can also use regular DNS servers (for, what is called "wide area bonjour" by Apple Computer). Given the very simular technical implementation, mDNS and DNS-SD are often implemented together. The most popular combination among application programmers is Apple's mDNSResponder, but more implemenations are available:
~- [mDNSResponder] (also known as [Bonjour]), an open-source implementation by Apple Computer, has interfaces for C and Java and is available on Mac OS X, Windows, and Linux. In addition, people have written interfaces in [Python] and [Ruby]. ~- [Avahi], a free (LGPL) implementation of mDNS/DNS-SD for Linux ~- [Howl], a multiplatform mDNS/DNS-SD implementation based on Bonjour ~- [JmDNS] in Java ~- [Liaison] ~- [mdnsd], embeddable Multicast DNS Daemon without DNS-SD ~- [pyZeroConf], Python service discovery ~- [tmdns], tiny multicast DNS, from the same project as ZCIP
Name lookup hooks
Having the ability to use multicast DNS for name lookup on the local subnet is very convienant, but most applications to not know about multicast DNS. Of course it is possible to change applications, but it would be better to alter the UNIX socket library functions gethostbyname() and gethostbyaddr() to use multicast DNS, beside the regular DNS and optionally the /etc/hosts file. To be precise, we want the gethostby*() functions to use multicast DNS for queries regarding .local., 169.254.*.* or FE80:* addresses, and regular DNS for everything else.
There are at least two, and possible three way to do create these gethostby*() hooks. ~- On Linux, the cleanest method is to change the behaviour of the Name Service Switch (which handles gethostby*() calls. Andrew White create libnss_mdns, which does exactly this thing. libnss_mdns is distributed with [mDNSResponder] from Apple Computer. ~- Secondly, you can run a name server on the localhost, listening to port 53 (and puting localhost in /etc/resolv.conf as the first name server). If it gets a link-local specific request, it will then forward this to port 5353 (multicast DNS). If not, it should return a failure, so that the next name server is used. [tmdns] implements this solution, although the latest version (0.53) has a bug in this mechanism. ~- There may be a third, poor man's solution, which is to run a regular name server on the localhost (e.g. bind) and let it forward link-local specific solutions to 126.96.36.199 port 5353. However, we never got that too work, and it's a incomplete solution, since a specific daemon also collects the answers from multiple hosts, and return them as a single reply to the original requester. Bind does not do such a thing, and only expects a single reply when it forwards requests.
This page is very simular in lay-out the the WikiPedia:ZeroConf WikiPedia ZeroConf entry, for the very reason that I [rewrote that entry] in this style in May 2005]]. Today the entry is less technical, so I put back some technical details here, and extended it with information regarding gethostby*() hooks and kernel patches.
More information on this wiki about ZeroConf experiments can be found at CategoryZeroconf.