Advertising Rendezvous services in Linux

by Rob Flickenger

Since I'm running a node on href="http://seattlewireless.net/">SeattleWireless (as well as a href="http://muzik.rob.swn/">streaming jukebox that I'm developing), I'd
like to let people know what local services are available. Sure, most
visitors just jump straight to their favorite website to check their email (or
their popularity) when they hit my
node, but perhaps they'd like to enjoy some local content at a whopping
11Mbps?


I'm already running NoCat to give people an
opening splash screen. But when they close it (or if their browser is
killing pop-up windows for them) then they have no easy way to get back to
my local content.


This is one reason why I love multicast DNS service advertisements (and
Rendezvous, in particular).
My Linux Jukebox and Wiki are now announcing themselves like an old-time
barker at the county fair. Wireless users at the cafe across the street (or
anywhere within a block or so) can find my local services any time just by looking at available
rendezvous sites. As if that weren't enough, my streamer is even
advertising itself as a DAAP stream, so iTunes 4 users can see that it's
available from inside iTunes itself.



Spam yourself silly in iTunes 4



Here's how I did it:


First, get a multicast DNS advertiser. I found
Apple's
own Posix implementation
to be more than adequate. (You can download it
after a free registration on Apple's site.) The application
you're after is mDNSProxyResponderPosix, in the mDNSPosix/ directory. It built cleanly and without so
much as a warning under Linux 2.4.20. Once it's built, install it somewhere
handy (like /usr/local/bin, for example.) There are a couple of other
multicast DNS projects floating around (like href="http://dotlocal.org/mdnsd/">mdnsd), but Apple's example code
seemed to work easiest out of any of the responders I tried.


Next, figure out what services you want to advertise. They don't even have to
be local services; the Proxy server will obligingly hand out whatever IP
addresses you care to throw at it, local or not. I'm advertising my local
Wiki, the Jukebox, and the NoCat website, just for fun.


The mDNSProxyResponderPosix program expects the following arguments:


[IP] [Host] [Service title] [Service type] [Port] [Optional text]

The first argument is the IP address you'd like to advertise. The second
should be a simple name that will be resolved as a .local address in multicast DNS. The Service title should be enclosed in double quotes, and should be a descriptive name for what is being advertised.


The Service type field is a little tricky. It takes the form


_service._transport.

...where service is a well-known IANA service name (i.e. something out of
/etc/services) and transport is the actual transport (like _tcp. or
_udp.) The Port argument is simply the port number, and the optional text
field supplies additional information to the application receiving the
advertisements (more on that later.)


For example, here's how I advertise my local music jukebox:


$ mDNSProxyResponderPosix 10.15.6.1 muzik "Music Jukebox" _http._tcp. 80 &

This creates a muzik.local address that resolves to
10.15.6.1. It is an http service, running on tcp port
80. Also notice the & at the end of the
line; mDNSProxyResponderPosix doesn't auto-daemonize (hey, it's just
example code, after all...) As it binds to port 5353, it doesn't need any
special privileges to run, so I recommend running it as a non-privileged
user.



Ads, Ads everywhere



This is all well and good for the jukebox, but what if you need to go to a
particular URL? For example, to get to my wiki, you need to go to
http://florian.local/wiki, not just http://florian.local/.
This is where the optional text field at the end comes in. Safari accepts a
path= argument in this field that gets appended to the URL line. For
example:


$ mDNSProxyResponderPosix 10.15.6.1 florian "About SWN-BelmontEast" _http._tcp. 80 path=/wiki &


And there you have it. In case you're curious, href="http://seattlewireless.net/index.cgi/NodeBelmontEast">SWN-BelmontEast
is the ESSID of my node on SeattleWireless.


Incidentally, if you're using VirtualHosts in Apache, you'll
have to tell apache to respond to the name you're advertising
(florian.local in the above example.) This is done easily with the
ServerAlias directive from within your <VirtualHost> stanza in your httpd.conf:


ServerName florian.rob.swn
ServerAlias florian.local

What about advertising non-local services, like other web sites? Just specify their IP address
as normal.

$ mDNSProxyResponderPosix 216.218.203.211 nocat "NoCatNet" _http._tcp. 80 &


Finally, since we have music available, it would be nice to advertise
directly to iTunes' sharing feature. Since iTunes is simply expecting
advertisements to the daap service (as opposed to http), this is a
piece of cake:


$ mDNSProxyResponderPosix 10.15.6.1 squeal "http://muzik.rob.swn/" _daap._tcp. 80

Unfortunately, you can't play the stream directly from the "shared"
playlist, as Apple uses a href="http://www.deleet.de/projekte/daap/">proprietary protocol to
handle the streaming, which is as yet undocumented and undeciphered. So
since I can't easily stream directly to the user (yet), I do the next best
thing: just spam the user with the relevant URL. If the user is curious
enough to browse to the URL that automagically pops up in their iTunes playlist, they'll be
presented with my streamer.


Of course, mDNSProxyResponderPosix isn't nearly as efficient as it
could be. After all, you're starting a separate instance for each service
you want to advertise, and there isn't even a simple configuration file.
But keep in mind that this application is just example code from Apple, and
in due time more sophisticated multicast DNS advertisement tools will come
along. The full source (as well as the complete spec, and some other href="http://developer.apple.com/techpubs/macosx/Cocoa/TasksAndConcepts/ProgrammingTopics/NetServices/Concepts/Names.html#//apple_ref/doc/uid/20001073/CJBFJHID">great
documents) are available, just waiting for someone to write the killer
Linux / BSD / Windows rendezvous app.


Oh, and if you're trying to get to some of the above urls (like href="http://florian.rob.swn/">http://florian.rob.swn/) but can't resolve
.swn, you should try it from anywhere on href="http://seattlewireless.net/">SeattleWireless. Funny, but the net
looks very different (and much more fun!) from behind a href="http://personaltelco.net/index.cgi/WirelessCommunities">Community Wireless
Network...

Are you using multicast DNS service advertisements in a creative way?


9 Comments

mnot
2003-05-08 14:42:29
Thanks!
This is very helpful! One question - I can't find the proper details for advertising netatalk shares. The protocol is obviously _afpovertcp._local, but how does one indicate a particular share on that server?


Thanks again.

rflicken
2003-05-08 15:03:59
Finding TXT data for AFP
Well, I'm pretty sure the protocol would be _afpovertcp._tcp. and the port number is 548.


Maybe you could do a packet dump of an actual AFP session, and see what's in any multicast dns TXT records?

anonymous2
2003-05-09 16:07:42
why not use mDNSResponder instead of mdNSProxyResponder?
mDNSResponder has a -d flag to autodaemonize, and can also read in a configuration file of hosts/services to advertise as opposed to the one host/service per instance problem mDNSProxyResponder has.


or is there something funky with your setup that requires it? (ie nocat being a captive portal)

rflicken
2003-05-09 16:35:51
why not use mDNSResponder instead of mdNSProxyResponder?
mDNSResponder won't let you advertise arbitrary IP addresses. It will only advertise local services, and in my case, I'm running the advertiser on a separate box from my web server.


But if you are advertising services on the same machine that they are served from, mDNSResponderPosix would do the trick nicely.

anonymous2
2003-05-12 08:01:42
why not use mDNSResponder instead of mdNSProxyResponder?
I'm trying to write a redhat init script to turn the responder on and off. The daemonized version, how can I look up the PID to kill it (and therefore allow the script to respond to a "service rendezvous stop" command)?
rflicken
2003-05-12 08:41:20
Stopping the service
The quickest way is to just run killall mDNSProxyResponder to kill the job by name. You could also do something like kill `ps ax|grep mDNSProxyResponder|grep -v grep|awk '{print $1}'` (although the first one is much simpler...)
anonymous2
2003-05-14 00:52:21
Stopping the service
The proper way to write an init script is to use the init.d functions in /etc/rc.d/init.d/functions by calling them at the start of the script. See other init scripts for an example.


These functions handle all pid details for you, and more. Find more info on them at:


http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/iniscrptfunc.html


Steven Boger
sboger@hotmail.com

rlotz
2003-07-08 12:24:26
mDNSProxyResponder and OpenBSD
mDNSProxyResponder works in OpenBSD (tested with 3.2), if you enable multicast.


I've posted more details.

anonymous2
2003-11-07 17:47:01
Rendezvous Chat
any windows and rendezvous compatible chat clients? iChat on OSX is nice but my parents are anti-mac, and jabber is too difficult to maintain.