Multicast DNS Quickstart
Obtain the code, either through perforce or grab the latest snapshot. The code should compile fine on both current and 6-STABLE.
Note that this is NOT production ready yet
If anything crashes or misbehaves, please try to obtain a backtrace from gdb
> cd mdnsd > make
If you want it to announce and claim records for your hostname you need to supply a configuration file, the default should do fine.
./mdnsd -f mdnsd.conf.sample
It's quite noisy as most debugging is still enabled, you can change the output by manipulating the DEBUG_MASK in mdnsd/Makefile. Debugging masks are defined in mdnsd/debug.h
If your hostname is foobar, the name foobar.local. will be claimed as yours and you should be able to use this name from another mDNS enabled machine (example Mac OS X client) to contact your machine.
Note that you need to start mdnsd as root if you want to be able to use libmdns, this is because the pipe is created in /var/run/mdnsd.pipe. It's possible to drop privileges with the -u and -g flags.
./mdnsd -f mdnsd.conf.sample -u nobody -g nobody
This needs to be compiled before you can use mdns or nss_mdns.
> cd libmdns > make
You do not need to install it, if you do and want to remove it later it installs the following files
Once mdnsd and libmdns is up and running you can play with the administrative and debugging utility mdns
cd mdns make
> ./mdns ./mdns query [-v] [-i ifnam] [-f family] [-w sec] [-c class] [-t type] name ./mdns db [-i ifnam] name `ident' [-s] add|del `host' ./mdns db [-i ifnam] res `ident' [-p] [-t ttl] add|del `class' `type' `res' ./mdns db -i ifnam list [ident] ./mdns cache [-i ifnam] view|flush
The query subcommand allows you do do a multicast dns query. The class (-c) and type (-t) arguments take case insensitive ascii representations of classes and types. Default class is IN and the default type is ANY. The -i argument allows you to specify a specific interface to query on, the default is all interfaces. The -f argument controls on which family to query (INET4/INET6), the default is both. -w controls how many seconds to wait for a response, there is no NXDOMAIN in mDNS, the absence of a response is interpreted as an implicit NXDOMAIN.
fli@nexus> ./mdns query shiva.local shiva.local. has address fe80::211:24ff:fe76:da00 shiva.local. has address 192.168.1.98 fli@nexus> ./mdns query 192.168.1.98 18.104.22.168.in-addr.arpa. domain name pointer shiva.local. fli@nexus> ./mdns query fe80::211:24ff:fe76:da00 0.0.A.D.6.7.E.F.F.F.22.214.171.124.126.96.36.199.0.0.0.0.0.0.0.0.0.0.0.8.E.F.ip6.arpa. domain name pointer shiva.local.
The db sub-command allows you to manipulate the state of the record database (you need to be root to use this). A resource set (rrset) is identified by an arbitrary unique identifier, a rrset can have one or many names assigned to it, but only one of them are in use at any given moment. Other names are used as fallback names in case name collisions. In addition to the names a rrset of course has resources, a resource is identified by (class, type, resource data). Both names and resource data are abstract and allows the use of variables in the names, the are then auto encoded into the correct format. A variable might expand to more than one data line, hence creating multiple records.
root@nexus> ./mdns db -i em0 list Names on identifier 'hostname' $(hostname).local. (nexus.local.) $(hostname)-$(ifname).local. Resources on identifier 'hostname' 120 IN A $(ifaddrs4) 120 IN AAAA $(ifaddrs6) Names on identifier 'ip4-ptr' $(ifaddrs4) (192.168.1.100) Resources on identifier 'ip4-ptr' 120 IN PTR $(hostname).local. (pointer to 'hostname') Names on identifier 'ip6-ptr' $(ifaddrs6) (fe80:1::219:d1ff:fedd:7914) Resources on identifier 'ip6-ptr' 120 IN PTR $(hostname).local. (pointer to 'hostname')
This is the names and resources created by mdnsd.conf.sample, together they form a real set of records.
For example the identifier 'hostname', it has two names assigned to it "$(hostname).local" which has been expanded to "nexus.local." and is the name currently in use, there is also a fallback name "$(hostname)-$(ifname).local" in case "nexus.local." would have been in use by some other host on the network. It has two resources, one (IN,A) resource with TTL 120 and data "$(ifaddrs4)" and one (IN,AAAA), TTL 120 and data "$(ifaddrs6)". Both "$(ifaddrs4)" and "$(ifaddrs6)" are expanded to the current ip-addresses of the interface "em0" (although not shown in this output).
The command db name and db res allows you to add and remove existing names and resources (root only).
Sub-command cache allows you to view/flush the cache on a specific interface (root only). Example
root@nexus> ./mdns cache -i em0 view shiva [00:11:24:76:da:00]._workstation._tcp.local. 120 116 IN SRV 0 0 9 shiva.local. shiva._sftp-ssh._tcp.local. 120 116 IN SRV 0 0 22 shiva.local. shiva._ssh._tcp.local. 120 116 IN SRV 0 0 22 shiva.local. shiva.local. 120 116 IN AAAA fe80::211:24ff:fe76:da00 0.0.A.D.6.7.E.F.F.F.188.8.131.52.184.108.40.206.0.0.0.0.0.0.0.0.0.0.0.8.E.F.ip6.arpa. 120 116 IN PTR shiva.local. shiva.local. 120 116 IN A 192.168.1.98 220.127.116.11.in-addr.arpa. 120 116 IN PTR shiva.local. shiva [00:11:24:76:da:00]._workstation._tcp.local. 4500 4496 IN TXT _services._dns-sd._udp.local. 4500 4496 IN PTR _workstation._tcp.local. _workstation._tcp.local. 4500 4496 IN PTR shiva [00:11:24:76:da:00]._workstation._tcp.local. shiva._sftp-ssh._tcp.local. 4500 4496 IN TXT _services._dns-sd._udp.local. 4500 4496 IN PTR _sftp-ssh._tcp.local. _sftp-ssh._tcp.local. 4500 4496 IN PTR shiva._sftp-ssh._tcp.local. shiva._ssh._tcp.local. 4500 4496 IN TXT _services._dns-sd._udp.local. 4500 4496 IN PTR _ssh._tcp.local. _ssh._tcp.local. 4500 4496 IN PTR shiva._ssh._tcp.local.
To use this you need to really install libmdns first.
cd nss_mdns make make install
It installs the following files
- /usr/lib/libnss_mdns.a (not sure this should be installed?)
- /usr/lib/libnss_mdns_p.a (not sure this should be installed?)
Now you need to modify you /etc/nsswitch.conf file Change the hosts line to something like this
hosts: files dns mdns
You should now be able to resolv mDNS names from any application.
fli@nexus> ping6 shiva.local PING6(56=40+8+8 bytes) fe80::219:d1ff:fedd:7914%em0 --> ? 16 bytes from fe80::211:24ff:fe76:da00%em0, icmp_seq=0 hlim=64 time=8.527 ms 16 bytes from fe80::211:24ff:fe76:da00%em0, icmp_seq=1 hlim=64 time=0.575 ms 16 bytes from fe80::211:24ff:fe76:da00%em0, icmp_seq=2 hlim=64 time=1.418 ms ^C --- shiva.local. ping6 statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/std-dev = 0.575/3.507/8.527/3.567 ms
If you want you can play with the mdns.conf.sample file, place it in /etc/mdns.conf and nss_mdns should pick it up.
The default looks like this (also hard coded in nss_mdns)
# # nss_mdns sample configuration file # These configuration values represent the default values that # are used when no configuration file is present. # search local. allow local. allow 169.254.0.0/16 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 allow fe80::/10
The search keyword makes nss_mdns auto-append .local. to names that fails to resolve, which means that you even can leave out the .local-part when using mdns names (eg ping6 shiva instead of ping6 shiva.local). The allow keyword controls what types of names that can be resolved, ip-addresses represents PTR-records.