MulticastDNS mdnsd

Status: More or less feature complete, requires more testing.

Feature wishlist



This is the overall principle, clients (programs) performs queries through a local unix socket to the responder daemon which in turn performs these queries on the network and provides a cache of previously asked records.

 [Other mDNS responders] <--network (mdns protocol)--> [mdnsd] <--unix sockets--> [clients]

The responder itself is multi-threaded using a simple work-queue scheme. This has the advantage that threads can be completely disabled on systems where libpthread or threads in general aren't desired (small embedded systems in particular), while at the same time has the ability to take advantage of modern multicore processors.

This is some ugly ascii to demonstrate the general data flow within and around the application

                                                                   ____ | UNIX pipe socket(s) | <--> [Applications]
                                                                  /      ---------------------
                                                                 /        __________
   --> [work queue] <---------[event dispatcher]  <--I/O ready signal--- |          |
  |     ___|_____                                                        | NETWORK  |
   ----| Workers | <--------------------- read from fdX----------------- |          |
       |w0,w1,wn |                                                       |          |
       |_________| ------------------> [output queue] --- write fdX ---> |__________|

The event dispatcher is implemented on top of kqueue(), it's used both for I/O ready signals and general timers. The purpose of the output queue is to aggregate several responses into one mdns packet (multicast allows packet sizes as large as the MTU of the network with an upper limit of 9000 bytes).

Static configuration

Configuration of "static" hosts will be done using /etc/mdnsd.conf (or similar), in the absence of a configuration file a default set of names could be announced.

Names and resources allows both quoted and non-quoted strings a features dynamic variables that updates when the underlying data changes (for example ip addresses). Variables prefixed with a $-sign represents system data while %-variables reference the selected name of a resource set (rrset {}), this allows for example PTR records to automatically track A records.

All resources are claimed unique on the network except those marked as shared. Interface specific statements can be wrapped inside a interface {} statement. Any number of res {} are allowed, even with the same type.

This is an example of what a configuration file could look like.

# Announce an A and AAAA record for our hostname, if hostname.local
# already is in use by somebody else we fall back to hostname-ifname.local
zone "local." {
    rrset hostname {
        name = "$(hostname)";
        name = "$(hostname)-$(ifname)";
        # These variables will expand to as many records as there are
        # ip-addresses assigned to the interface.
        res A { data = "$(ifaddrs4)"; }
        res AAAA { data = "$(ifaddrs6)"; }

    # This will be created under ._tcp.local.
    zone "_tcp" {
        rrset workstation {
            name = "$(hostname) [$(mac)]._workstation";
            res PTR { data = "%(hostname)"; }

# Announce a matching PTR record(s) for our IPv4 addresses
# Resource data is a "pointer" to our hostname record.
rrset "ip4-ptr" {
    name = "$(ifaddrs4)";
    res PTR { data = "%(hostname)"; }

# Announce a matching PTR record(s) for our IPv6 addresses
# Resource data is a "pointer" to our hostname record.
rrset "ip6-ptr" {
    name = "$(ifaddrs6)";
    res PTR { data = "%(hostname)"; }

Dynamic configuration

Names and resources can be added during run time using the UNIX pipe and features the exact same variable system as the static configuration.

MulticastDNS/responderd (last edited 2008-09-08 19:03:47 by FredrikLindberg)