For most of this year I’ve been working on a new product called Cisco OnPlus, a network management service for small business. In order to do its job effectively, OnPlus needs to know what devices are present on the network, and one of the key tools we use to accomplish this is DNS Service Discovery. In this article I will show you a little bit about how we use DNS-SD, and show you how you can put it to work effectively in your networks.
Cisco OnPlus is a cloud-based network management tool that helps resellers support their customers. The figure below shows you a typical view of a customer network from an OnPlus browser screen. (The customer in this case being my Dad.) OnPlus not only identifies the devices on the customer’s network, it also performs configuration backups, firmware updates, and monitors network performance.
In order to get this information about the customer’s network, OnPlus relies on the OnPlus Network Agent – an ARM-based Linux PC about the size of a paperback book. This computer is a close relative of the Sheeva Plug, and despite its small size it runs a fairly complete distribution of Linux.
The agent regularly runs a complete inventory of the network, attempting to learn as much as possible about all of the devices it can find. The inventory process uses a huge list of protocols when scanning the network, including:
DNS Service Discovery
DHCP Packet Inspection
DNS Packet Inspection
Windows Management Instrumentation
Cisco Discovery Protocol, or CDP
When it comes to locating devices made by my business unit at Cisco, the most useful protocols are DNS Service Discovery and Cisco Discovery Protocol. DNS Service Discovery provides all the information the inventory process needs to fully identify a device: its specific Product ID (more or less a model number), the version number of both the hardware and the firmware, its MAC address, and its IP address. (CDP provides a nearly, but not identical bundle of data.) This information is readily available because devices made by Cisco’s Small Business Technology Group use DNS-SD to broadcast information using our proprietary service type:
A Quick Overview of DNS Service Discovery
So what exactly is DNS Service Discovery? If you’re like me, you became aware of DNS-SD because Apple uses it as part of Bonjour. Bonjour is a proprietary implementation of Zeroconf, a set of technologies marked by by three key network components:
The history of Zeroconf is a somewhat quixotic story, based around the shared idea that setting up small networks ought to be a painless and simple process. The components of Zeroconf provide a nice, vendor-agnostic way to set up networks in such a way that no consumer would ever have to manually assign an IP address, set up a DHCP server, or manually enter the address of a printer.
Apple has embraced this idea, with their implementation of Zeroconf called Bonjour, an Apple trademark. If you run iTunes on your Apple or Windows PC, you may well see that there are other users out there running iTunes who would be happy to share their collections with you. This happens more or less with no work on your part, and can be a really nice feature in a big office:
iTunes accomplishes this sharing using DNS-SD, which is built into OS X and is configured on Windows machines as part of the iTunes installation. Every instance of iTunes that is configured to share its library uses Bonjour to advertise an instance of the
daapservice. If we look in the official roster of registered DNS Service types, we find this record:
daap Digital Audio Access Protocol (iTunes) Amandeep Jawa
Defined TXT keys: txtvers, Version, iTSh Version, Machine ID, Database ID, Machine Name, Password
This is a pretty simple definition – let’s see what it looks like on the network.
On my desktop Linux sytem, I have the avahi utilities installed. Avahi provides a nice suite of tools used to implement DNS-SD. I’ll use the
avahi-browse command to see what these
daap services actually look like:
mark@ubuntu:~$ avahi-browse _daap._tcp -t + eth0 IPv4 Itunes NAS Server on nas iTunes Audio Access local + eth0 IPv4 Denise___s Library iTunes Audio Access local + eth0 IPv4 Mark___s Library iTunes Audio Access local mark@ubuntu:~$
If I ask
avahi-browse to resolve the services, it will query the service provider for the details in the advertisement. A partial output is shown below:
mark@ubuntu:~$ avahi-browse _daap._tcp -r -t + eth0 IPv4 Itunes NAS Server on nas iTunes Audio Access local + eth0 IPv4 Denise___s Library iTunes Audio Access local + eth0 IPv4 Mark___s Library iTunes Audio Access local = eth0 IPv4 Itunes NAS Server on nas iTunes Audio Access local hostname = [nas.local] address = [192.168.1.165] port =  txt = ["ffid=075abcc4" "Password=false" "Version=196610" "iTSh Version=131073" "mtd-version=svn-1676" "Machine Name=Itunes NAS Server" "Machine ID=BE8926F6" "Database ID=BE8926F6" "txtvers=1"]
From this information, I know have everything I need in order to connect to to a server and start playing music. I have a hostname, IP address, and a port, all of which can be used to access the service. Finally I have a txt record that contains an aribtrary set of name/value pairs, as defined in the service definition. The us of these fields is up to the creator of the service, and in this case most of them are self-evident.
Browsing the Network
We use the avahi toolkit in OnPlus to browse the network for devices. It is worth doing a little exploring on my home network to see what kind of information we get out of this process.
To get a high-level view, I can ask
avahi-browse to query for a special service:
_services._dns-sd._udp. When this browse request goes out on the network, all the active nodes using DNS-SD issue records detailing the types of services they support. The result on my home network looks like this:
mark@ubuntu:~$ avahi-browse _services._dns-sd._udp -t + eth0 IPv4 _udisks-ssh _tcp local + eth0 IPv4 _workstation _tcp local + eth0 IPv4 _ir-hvac-021 _tcp local + eth0 IPv4 _ir-hvac-020 _tcp local + eth0 IPv4 _ir-hvac-000 _tcp local + eth0 IPv4 _pdl-datastream _tcp local + eth0 IPv4 _printer _tcp local + eth0 IPv4 _tivo-videos _tcp local + eth0 IPv4 _readynas _tcp local + eth0 IPv4 _smb _tcp local + eth0 IPv4 _afpovertcp _tcp local + eth0 IPv4 _rsp _tcp local + eth0 IPv4 _daap _tcp local + eth0 IPv4 _http _tcp local + eth0 IPv4 _csco-sb _tcp local mark@ubuntu:~$
As you can see, there are a surprising number of DNS-SD services present. On my network, an explanation for each of the services is:
|_udisks-ssh:||A remote disk management tool being advertised by my Ubuntu systems|
|_workstation:||Some sort of workgroup management interface support by various Linux systems.|
|_ir-hvac-0xx:||Management interfaces on a Trane thermostat that happens to have wireless access to my network|
|Printer page description language interface. This is a service that is used in Bonjour printing. Both of my networked printers support it.|
|_printer||Both of my printers use this advertisement to offer TCP port 515 up for LPR print spooling|
|_tivo-videos||My Tivo sends out this advertisement which provides a complete URL I can use to get an XML-formatted version of the Now Playing section of the Tivo UI.|
|_readynas||My Netgear ReadyNAS uses this unregistered service type to advertise something that can be reached on port 9. Exactly what, I don’t know, but I think it might be just a way for PC users to find the NAS with RAIDar.|
|_smb||My Netgear ReadyNAS advertises its Windows shares with this service type|
|_afpovertcp||My Netgear ReadyNAS uses this registered service type to advertise its Apple File Sharing volumes|
|_rsp||I have a Firefly iTunes server running on my NAS. In addition to serving music via DAAP, it uses the Roku Server Protocol as well, presumably working with software that doesn’t support iTunes protocols.|
|_http||Most of the devices on my network that are running web servers issue an HTTP advertisement, which points to that interface.|
|_csco-sb||My two Cisco SB devices advertise their presence using this service|
This special command to show me the services available is not actually used in OnPlus. Instead, we call
avahi-browse with the -r and -p commands, asking it to do a full resolution on all discovered services.
The place where we get the most interesting results from
avahi-browse is when we tell it to look specifically for instances of the
cisco-sb service. That command produces output like this:
mark@ubuntu:~$ avahi-browse -r -t _csco-sb._tcp + eth0 IPv4 switch32026a _csco-sb._tcp local + eth0 IPv4 onplus005229 _csco-sb._tcp local = eth0 IPv4 switch32026a _csco-sb._tcp local hostname = [sg200-26p.local] address = [192.168.1.168] port =  txt = ["hostname=sg200-26p" "serialNo=DNI1515005U" "MACAddress=44E4D932026A" "PIDVID=SLM2024PT V01" "fmVersion=22.214.171.124" "deviceDescr=26-port Gigabit PoE Smart Switch" "deviceType=Switch" "model=SG 200-26P"] = eth0 IPv4 onplus005229 _csco-sb._tcp local hostname = [PLG1000F0AD4E005229.local] address = [192.168.1.167] port =  txt = ["accessType=http" "MDFID=Unassigned" "hostname=onplus005229" "serialNo=PLGF0AD4E005229" "MACAddress=F0:AD:4E:00:52:29" "PIDVID=Unassigned" "fmVersion=6.2.2.007" "deviceDescr=Cisco OnPlus Network Agent" "deviceType=Service Appliance" "model=PLG1000" "version=1.0"] mark@ubuntu:~$
If you look at the first ‘=’ records that is issued by
avahi-browse, you can see that when it comes to discovery, I have really hit the jackpot. I’ve identified a device on my system that I can reach with a specific IP address. I have a MAC address that I can now use as a globally unique identifier. And I have the Cisco Product ID, the hardware version, and the firmware version, as well as the user-assigned host name and a friendly model name.
When I have information like this, it allows me to fill in the details in the topology map quite accurately. Better yet, since this is a Cisco device, the OnPlus appliance can now send it some queries to find out more network information. As an example, the switch’s CAM table provides me with a list of devices and the ports they are attached to, which helps me fill in some of the details of the topology picture.
Processing This Data
If you are a programmer, the natural question you might be asking is how you access these service advertisements from inside your program. In the case of Cisco OnPlus, most of the code running the inventory task consists of PHP scripts. As far as I know, there are no bindings in PHP to DNS-SD services, and we elected not to try to invent that wheel.
Instead, we use PHP’s
popen() function to run instances of
avahi-browse, collecting the output from the program and parsing it accordingly. We actually have three instances of the browser running at any time. Two are dedicated to Cisco-specific services, while the third looks at all other services. Even though other services might not give us as munch information as
csco-sb, they still supply host names, MAC addresses, IP addresses, descriptions, and more, and we use whatever we can find.
These instances of
avahi-browse run as independent discovery processes, collecting and storing data as it is seen on the network. The records that they collect are then used by the inventory process when it is periodically launched.
The DNS-SD discovery processes actually take an active role in the inventory scheme. When one of the avahi-based processes discovers a significant new device on the network, such as one advertising
cisco-sb, it stores the data record and then triggers an early start to the inventory process. This allows OnPlus to respond to new devices on the network in something close to real-time.
So let’s say you decide you want to use DNS-SD for some form of network discovery. I’ve shown you how you can you discover network nodes that are advertising a service, but how do you actually perform that advertisment?
In the OnPlus Network we use the avahi package to advertise services as well as to find them. The
avahi-publish command does the job, typically started as a daemon to run for the lifetime of the system. When executing
avahi-publish, you will normally want to specify:
A service type
The name of the service instance
A port to access the service
Text records containing whatever name/value pairs you want to publish
One thing to note is that you can use DNS-SD to advertise things that don’t necessarily map directly to a port. For example, if you just want to let everyone know of your existence, the port parameter might be irrelevant, but the name/value pairs could still be valuable.
As an example, I might create a photo sharing service that I advertise on the network using a service I’ll call
PhotoMark. To let everyone know about this, I execute the following command when my system starts up:
avahi-publish -s mark _PhotoMark._tcp 9999 "payload=.gif" "folder=/pictures"
Anyone on the network using DNS-SD could then see that I was advertising photo sharing with photos of type GIF accessible on my
pictures folder. Of course, the details of the protocol are not included in the advertisement – that’s outside the scope of DNS-SD.
Often a good choice for the service instance is to simply use the computer name:
avahi-publish -s `uname -n` _PhotoMark._tcp 9999 "payload=.gif" "folder=/pictures"
In this article I showed you how we use DNS-SD on the Cisco OnPlus Network Agent. Mostly it involves calling the avahi command line tools and parsing their output with PHP scripts.
In my next post, I’ll show you how to do the same thing on a Windows PC using the Apple Bonjour SDK. Unfortunately, Windows has not included DNS-SD support in the O/S, so instead of using the Win32 API to do service discovery, you will have to rely on some slightly less elegant methods. But when it comes to network discovery, functionality and interoperability trump elegance every day of the week.