How to list the IP addresses of all the AirPrint printers on a network

airprintbonjourNetwork

I am trying to make a list of all AirPrint printers on the network at a school. We have many of them because of all the classroom and office printers, but they have not been set up with meaningful names. I tried reading the DHCP allocation table in the router, but many of the printers do not report a host name. I can't check printers in-person because of the disruption to classes from going in to every room and playing with the 1-3 printers there.

The dns-sd command as in How to find IP address of my other Mac?
gives a column called Instance Name, rather than the host name. Using the dns-sd -G option on the instance names gave no such record.

dns-sd -Z is closer, since it gives host names to look up with the G option, but it doesn't give a complete list. There are many more printers in the Add Printer dialog on a Mac than there are in the output of dns-sd -Z.

Does anyone have some code or script to just find all the IP addresses of things advertising by Bonjour?

Best Answer

I do not have an AirPrint printer on my network. And never played with one either...


I cannot test with a real AirPrint device in my proximity right now.

But here is how I can list all the IPP-enabled printers (in this case they are all connected via CUPS):

First, browse for DNS-SD discoverable services (all types):

kp@zdv-wireless-43-219:> dns-sd  -B  _services._dns-sd._udp  local.

  Browsing for _services._dns-sd._udp.local.
  DATE: ---Fri 20 May 2016---
  23:54:37.797  ...STARTING...
  Timestamp     A/R Flags  if Domain  Service Type         Instance Name
  23:54:37.798  Add     3   4 .       _tcp.local.          _ssh
  23:54:37.798  Add     3   4 .       _tcp.local.          _sftp-ssh
  23:54:37.798  Add     3   4 .       _tcp.local.          _airplay
  23:54:37.798  Add     3   4 .       _tcp.local.          _raop
  23:54:37.798  Add     3   4 .       _tcp.local.          _googlecast
  23:54:37.798  Add     3   4 .       _tcp.local.          _nomachine
  23:54:37.798  Add     3   4 local.  _apple-mobdev2._tcp. _sub
  23:54:37.798  Add     3   4 .       _tcp.local.          _apple-mobdev2
  23:54:37.798  Add     3   4 .       _tcp.local.          _ipps
  23:54:37.798  Add     3   4 .       _tcp.local.          _ipp
  23:54:37.798  Add     3   4 .       _tcp.local.          _workstation
  23:54:37.798  Add     3   4 .       _tcp.local.          _http
  23:54:37.798  Add     3   4 .       _tcp.local.          _amzn-wplay
  23:54:37.798  Add     3   4 .       _tcp.local.          _rfb
  23:54:37.798  Add     3   4 .       _tcp.local.          _afpovertcp
  23:54:37.798  Add     3   4 .       _tcp.local.          _smb
  23:54:37.798  Add     3   4 .       _udp.local.          _net-assistant
  23:54:37.798  Add     2   4 .       _tcp.local.          _eppc
  ^C

So yes, there is indeed an IPP print service (but no AirPrint one, which would be marked by stand out being tagged as Service Type of _airprint._tcp in the list).

Second, browse for all present services of type "IPP":

kp@zdv-wireless-43-219:> dns-sd  -B  _ipp._tcp  local.

  Browsing for _ipp._tcp.local.
  DATE: ---Fri 20 May 2016---
  23:54:47.782  ...STARTING...
  Timestamp     A/R  Flags  if Domain  Service Type   Instance Name
  23:54:47.783  Add      3   4 local.  _ipp._tcp.     Officejet6500donna @ mbp
  23:54:47.783  Add      3   4 local.  _ipp._tcp.     raw2dir @ mbp
  23:54:47.783  Add      2   4 local.  _ipp._tcp.     Officejet 6600 @ mbp
  ^C

Ok, one of the instance names is "Officejet 6600 @ mbp".

Third, lookup specific info about the printer named "Officejet 6600 @ mbp":

kp@zdv-wireless-43-219:> dns-sd  -L  "Officejet 6600 @ mbp"  _ipp._tcp  local.

  Lookup Officejet 6600 @ mbp._ipp._tcp.local.
  DATE: ---Fri 20 May 2016---
  23:54:55.252  ...STARTING...
  23:54:55.253  Officejet\0326600\032@\032mbp._ipp._tcp.local. can be reached at mbp2-2.local.:631 (interface 4)
   txtvers=1 qtotal=1 rp=printers/Officejet_6600 ty=Unknown \
    adminurl=https://mbp2-2.local.:631/printers/Officejet_6600 \
     note=Büro\ im\ Keller priority=0 product=\(Officejet\ 6600\ e-All-in-One\) \
      pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/pwg-raster \
       UUID=e7d11337-a440-3f2d-7168-b53de4325791 TLS=1.2 Color=T Scan=T \
        printer-state=3 printer-type=0x480900E
  ^C

Half of the info you are looking for (hostname of the printer) is covered by the sentence "Officejet\0326600\032@\032mbp._ipp._tcp.local. can be reached at mbp2-2.local.:631"

This gives the current (Bonjour-)hostname of node offering the looked-up print service.

Fourth, look up the IPv4 and IPv6 addresses for a given hostname:

kp@zdv-wireless-43-219:> dns-sd -Gv4v6 mbp2-2.local

  DATE: ---Sat 21 May 2016---
  0:12:41.025  ...STARTING...
  Timestamp     A/R Flags if Hostname    Address                                      TTL
  0:12:41.025  Add  3  4 mbp2-2.local.   FE80:0000:0000:0000:AEBC:32FF:FEAE:CAEB%en0  120
  0:12:41.025  Add  3  4 mbp2-2.local.   FD00:0000:0000:0000:AEBC:32FF:FEAE:CAEB%  120
  0:12:41.025  Add  2  4 mbp2-2.local.   192.168.177.20                               120
  ^C

Summary

Assuming my first command had returned some _airprint service available in my network, then my guess is that one of the returned lines would read:

00:00:00.000  Add     3   4 .       _tcp.local.          _airprint

Thus, my second command would have to be:

kp@zdv-wireless-43-219:> dns-sd  -B  _airprint._tcp  local.

I assume this could return something like

200:00:00.000  Add    3   4 local.  _airprint._tcp.  Some AirPrinter @ somehost

Then my third command should read:

kp@zdv-wireless-43-219:> dns-sd  -L  "Some AirPrinter @ somehost"  local.

Which would return a line telling you "... can be reached at somewhere.local.:1234". From which to derive the fourth command:

kp@zdv-wireless-43-219:> dns-sd  -Gv4v6  somewhere.local.  

Caveats: The last part, about AirPrint service discovery may be wrong. It could be the case that AirPrint services announce themselves just as standard IPP services do. You have to find out yourself. If you do, please report back.


Update

I've googled a bit for "_airprint._tcp".

I didn't find a single instance of anybody who reported in some forum their output from dns-sd -B listing this particular string.

However, there were lots + lots of _airplay._tcp and _ipp._tcp results. This means that "_airprint._tcp" does not seem to exist, and AirPrint printers must be using a different signature to make themselves known to potential clients. However, we already know that all AirPrint services use IPP for communication with their clients, so they also MUST be making the _ipp._tcp service type announcements.

Hence it is safe to conclude that...

  1. ...all AirPrint devices will announce themselves as _ipp._tcp (not _airprint._tcp). Also, it looks like...
  2. ...you can identify AirPrint devices by looking for the TXT record of urf="$anything" and pdl="$anything,image/urf".

To verify this, I checked with what the (fake) announcement from dns-sd.org tells about its AirPrint (warning, it is not permanently on the Internet, sometimes it goes away for hours...). It does return this:

kp@zdv-wireless-43-219:>  dns-sd -Z _ipp._tcp,_universal dns-sd.org.

  Browsing for _ipp._tcp,_universal.dns-sd.org.
  DATE: ---Sat 21 May 2016---
   1:40:45.688  ...STARTING...

  ; To direct clients to browse a different domain, substitute that domain in place of '@'
  lb._dns-sd._udp                                 PTR     @

  ; In the list of services below, the SRV records will typically reference dot-local Multicast DNS names.
  ; When transferring this zone file data to your unicast DNS server, you'll need to replace those dot-local
  ; names with the correct fully-qualified (unicast) domain name of the target host offering the service.

  _ipp._tcp                                       PTR     Stuart's\032Home\032AirPrint\032Printer._ipp._tcp
  Stuart's\032Home\032AirPrint\032Printer._ipp._tcp SRV     0 0 631 airprint.dns-sd.org. ; Replace with unicast FQDN of target host
  Stuart's\032Home\032AirPrint\032Printer._ipp._tcp TXT     "txtvers=1" "qtotal=1" "rp=ipp/printer" \
    "pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL,application/pdf,image/urf" \
    "URF=CP99,W8,OB10,PQ3-4-5,ADOBERGB24,DEVRGB24,DEVW8,SRGB24,IS1-2-4,MT1-2-3-5-12,MT1-2-3-5-12,RS600" \
    "ty=HP LaserJet 400 color M451nw" "product=(HP LaserJet 400 color M451nw)" \
    "priority=10" "adminurl=http://www.dns-sd.org/ServerStaticSetup.html" \
    "note=At Stuart's house" "Color=T" "Duplex=F" "Scan=F"
^C

Indeed, "Stuart's Home AirPrint Printer" mentions "URF" in its TXT records.

So, to summarize the answer to your question "How can I get the IP addresses of all AirPrint printers?"

  1. First, list all IPP printers.
  2. Second, exclude these IPP printers which do NOT enumerate the two above mentioned urf-entries in their TXT records.

Verify my statements

The following (minimal) command will announce a fake AirPrint device in your LAN (until you cancel the command with ^C):

dns-sd                                                                   \                                                                            
    -R "Minimal AirPrint Demo (dummy+fake printer fooling iPad clients)" \               
    _ipp._tcp.,_universal                                                \                                                              
    .                                                                    \                                                                                  
    631                                                                  \                                                                                
    pdl="image/urf"                                                      \                                                                    
    URF=""

Your iOS devices will now enumerate this printer amongst its auto-discovered AirPrint devices.

(BTW, you can announce the port as something different from 631 too -- the iOS clients will still identify it as an AirPrint device...)

Now repeat this little experiment, just leave one of the two image/urf or URF="" statements off your command:

  1. The fake device will still appear as an IPP printer in the DNS-SD/Bonjour browse lists.
  2. But iOS clients will only list as AirPrint-capable these (fake or real) devices with the "URF"-related entries.