Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

LABS
Making Printers and Common Resources Available to Separate Network Segments via Bonjour and DNS-SD

Abstract

When we moved to a new office, we faced a problem: how do we give printer access to everyone though we had segregated machines to different networks? And how do we make it transparent to the user?

The solution we found was to add a new VLAN (i.e. network segment) for the printers (and other common resources, e.g. license servers), use DNS Service Discovery (dns-sd), and add a handful of crafted records to our DNS server.

This blog post is directed at Operations staff at companies which have the following characteristics:

  • primarily use Apple workstations
  • have network-attached printers
  • use Bonjour for printer discovery
  • need to print from multiple VLANs
  • use djbdns

The Problem

The short version: people couldn’t print from the WiFi network.

Network/VLAN Configuration

This is a synopsis of our network (note: the IP addresses and subnet masks are simplified for purposes of our discussion):

VLAN    Name            IP
1       PIVOT           10.0.1.0/24
2       SERVER          10.0.2.0/24
3       PAIRING_DMZ     10.0.3.0/24
4       VOIP            10.0.4.0/24
5       PIVOTAL_WIFI    10.0.5.0/24
6       PIVOTAL_GUEST   10.0.6.0/24
7       SECURITY        10.0.7.0/24
8       COMMON          10.0.8.0/24

Note that the last VLAN (“COMMON”) is the one where we have placed all the resources. We named it COMMON as in “Common Resources”.

Determining What Records Needed to be Added

We used a bonjour browser to discover which records we needed to add (note: you need to run the bonjour browser on a machine that is on the same network as the printers, otherwise the printers won’t show up). We navigated as follows: local. → _pdl-datastream._tcp. 1 We found our printers (goldfinger and blofeld, named after James Bond villains). Here are the relevant records for Goldfinger:

  • Goldfinger
    • goldfinger.local.:9100
    • txtvers=1
    • qtotal=1
    • pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL
    • ty=HP Color LaserJet 4700
    • product=(HP Color LaserJet 4700)
    • priority=40
    • adminurl=http://goldfinger.local.

In our setup, we use tinydns to serve our DNS records. For those using BIND, the dns-sd.org website has an excellent how-to.

Add the Required DNS-SD records

First, we need to create the basic dns-sd records. We only need to add these records once.

^b._dns-sd._udp.sf.pivotallabs.com.:sf.pivotallabs.com.:86400::
^lb._dns-sd._udp.sf.pivotallabs.com.:sf.pivotallabs.com.:86400::

Translating the bonjour records to DNS—the easy way

Download this script to create the DNS records (courtesy Michael Sierchio). Save the script as “make_printer_dns”.  Then use the bonjour browser to extract the printer information and save that information to a file with the same name as the printer (e.g. hp4020.sf.pivotallabs.com).  In this example, we use a heredoc to save the information extracted from the HP 4700 Color Laserjet, and then we run the script to output the djbdns records:

$ cat > goldfinger.sf.pivotallabs.com. <<EOF
txtvers=1
qtotal=1
pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL
ty=HP Color LaserJet 4700
product=(HP Color LaserJet 4700)
priority=40
adminurl=http://goldfinger.sf.pivotallabs.com.
EOF
$ make_printer_dns goldfinger.sf.pivotallabs.com.

^_pdl-datastream._tcp.sf.pivotallabs.com.:goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.
:goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.:33:000000004321412goldfinger02sf13pivotallabs03com0000
:goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.:16:11txtvers=110qtotal=1112pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL31ty=HP Color LaserJet 470040product=(HP Color LaserJet 4700)13priority=4056adminurl=http72//goldfinger.sf.pivotallabs.com.

Copy the above records into your djbdns source files and regenerate the database (i.e. tinydns-data).  You have now created the  records necessary to allow printer discovery across subnets.

Translating the bonjour records to DNS—the hard way

[Editor’s note:  do not use this hard technique; use the easy way instead.  This portion is meant for instruction rather than actual implementation]

We add a PTR record for Goldfinger printer. We’ll need to add a similar record every time we add a new printer:

^_pdl-datastream._tcp.sf.pivotallabs.com.:Goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.

Then we need to create DNS SRV records for the Goldfinger printer. These can be crafted by hand, but I prefer to use Anders Brownworth’s tinydns record builder. We enter the following information for the SRV record builder:

  • Service: Goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.
  • Priority: 0
  • Weight: 0
  • Port: 9100
  • Target: goldfinger.sf.pivotallabs.com.
  • Time To Live: 86400

Anders’s script gives us the following record, which we add to our tinydns records:

:Goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.:33:000000004321412goldfinger02sf13pivotallabs03com00:86400

But we’re not done: we still need to create the TXT record which has the important information we uncovered with our bonjour browser. A regular tinydns TXT record (one which begins with a “‘”) won’t do because we have several records. We need to use a generic record (a special TXT record). This one we’ll need to handcraft.

  • First, start with a colon (“:”) to indicate a generic record, then add the FQDN:

:Goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.
  • Then, append the record type (TXT, type 16):

:16:
  • Then we’ll need to prepare our data. We take the information we pulled from the Bonjour browser:

txtvers=1
qtotal=1
pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL
ty=HP Color LaserJet 4700
product=(HP Color LaserJet 4700)
priority=40
adminurl=http://goldfinger.sf.pivotallabs.com.
  • Then we pipe that data through a small ruby script:

ruby -e 'STDIN.read.split("n").each { |t| printf("\%03o%s",t.length,t.gsub(":","\\072")) }; puts'
  • We take the result, and append it to our record. Our final record looks like this:

:Goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.:16:11txtvers=110qtotal=1112pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL31ty=HP Color LaserJet 470040product=(HP Color LaserJet 4700)13priority=4056adminurl=http72//goldfinger.sf.pivotallabs.com.

Testing the output

Once we’ve added the records and rebuilt our djbdns database, we test to make sure it really works:

nslookup -query=srv goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.
Server:		10.80.0.18
Address:	10.80.0.18#53

Non-authoritative answer:
goldfinger._pdl-datastream._tcp.sf.pivotallabs.com	service = 0 0 9100 goldfinger.sf.pivotallabs.com.

nslookup -query=txt Goldfinger._pdl-datastream._tcp.sf.pivotallabs.com.

Goldfinger._pdl-datastream._tcp.sf.pivotallabs.com  text = "txtvers=1" "qtotal=1" "pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL" "ty=HP Color LaserJet 4700" "product=(HP Color LaserJet 4700)" "priority=40" "adminurl=http://goldfinger.sf.pivotallabs.com."

Note the following:

  • we have replaced the bonjour hostname, “goldfinger.local.”, with the fully qualified DNS name, “goldfinger.sf.pivotallabs.com.”
  • we have ignored the very first bonjour record, “goldfinger.local.:9100″. It served no purpose in dns-sd.

Success

After restarting our DNS server, our clients were able to add a printer easily through Mac OS X’s System Preferences → Printers → “+”.

Gotchas

Client machines need to have the domain (e.g. “sf.pivotallabs.com”) in their search-path for dns-sd to work. For ISC-dhcpd, the appropriate entry would be “option domain-name ‘sf.pivotallabs.com';”

We noticed a propagation delay with older (Snow Leopard) Macs—they didn’t always see the printers right away. In these cases, we tried flushing the DNS cache (“dscacheutil -flushcache” or, in Lion, “sudo killall -HUP mDNSResponder”), but that seemed to have no effect. A few days later the printers became discoverable from those workstations.

Apple clients will use SNMP queries to determine some of the printers capabilities.  We encourage you to all SNMP traffic to the network where the printers are located.

Footnotes

1 pdl-datastream is a Registered Port for printing. There are at least 2 other ports commonly used for printing: ipp (631) and printer (515). Our decision to use pdl-datastream over the other two was arbitrary. That being said, we have found that using the ipp port to be counter-productive and should be avoided. We have found that when we advertise ipp and the printer in question is Airprint-capable, then printing will not work (I suspect AirPrint does not work across subnets, but am not sure).

Acknowledgements

Special thanks to my co-authors Michael Sierchio and Matthew Kocher

Keywords

tinydns, dns-sd, DNS Service Discovery

Comments
  1. Michael Sierchio says:

    awk ‘{ printf “%0.3o%s”, length($0), $0 }’

    Never use Ruby where you can use Perl; never use Perl where you can use awk; never use awk where you can use sed; never use sed.

    – M

  2. Michael Sierchio says:

    Sorry for my lack of markdown fu.

    awk ‘{ print “\\%0.3o”, length($0), $0 }’

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *