CUPS – IPP vs. IPPEverywhere

CUPS, the tooling of most printing workflows on UNIX-ish systems including MacOS and many linux distributions, is an archaic, unwieldy, tool. It is also indispensable, at least for the moment

IPP is a venerable printing standard that has been around since the 1900s and is supported by almost all network printers today. It’s HTTP, with a body that encodes key-value attributes followed by an arbitrary amount of binary data (usually an image document in a vector or raster image encoding, negotiated via attributes)

IPPEverywhere is a new standard from the PWG that builds on IPP to offer “driverless” printing, mostly by making some of the attributes mandatory to ensure a basic set of features, and by requiring common image encoding formats like PDF or PS or JPEG, so that print clients do not have to implement local image encoding. IPPEverywhere also requires mDNS for link-local device discovery

CUPS has been a reference implementation of IPP for many years and was officially adopted by Apple and ships with MacOS. In recent years it has added good support for IPPEverywhere, and it continues to be the default print workflow in many systems

Unfortunately even its own developers think the old bits should die. They added IPPEverywhere support, but no by updating the old pieces. Instead they added a warning that all the old parts would stop working, and that only IPPEverywhere would be supported in future versions

As a software developer this makes a lot of sense to me. The old process was already so strained, a crutch we collectively built to lurch us into the 2000s, slowly building a standard around PPDs and Ghostscript and ICC color profiles. We needed it to get to IPPEverywhere, but it cannot come with us when we switch. As in life we sometimes need to let go of old parts that we needed to get here but that now hold us back


As a human who uses printers, this seems insane. Not just as a human who owns old printers and wants to still use them, but as a human who uses any printer of any age, including the ones that natively support IPPEverywhere

Obviously it would be great if this would change. Ideally every print option could be supported via IPP attributes, every print client would support all these options, and the internal image processing the printer does would be fast and reliable and always render good results

But printers are complicated robots with software written by image geeks and ink nerds, and these robots do not support this driverless world. The big expensive printers literally never will — they will always have customized drivers, just like any other piece of big equipment. The home and office end of things go differently, but we aren’t there yet

The thing that everyone from system administrators to printer manufactures uses to make their hardware-specific backend talk to IPPEverywhere systems is: CUPS. I don’t mean to say that printers don’t offer native IPPEverywhere support, but if you go to the HP or Canon printer support site it will link you to a client-side driver. On UNIX-y systems this driver is often literally PPD files and plugins for CUPS

For example, the Canon MF750x series supports all the necessary standards and is entirely usable via IPPEverywhere, but only advertises 300dpi. The IPP interface works fine with higher resolutions, but IPPEverywhere clients won’t be able to use them. Likewise many of the color processing options are available via IPP but are not advertised in the “driverless” system, and even if advertised are not accessible on clients

So if you’re actually running an environment where you want to provide high-quality print services to IPPEverywhere clients, you’re installing the “deprecated” driver to CUPS so that it can advertise the proper, fully-featured interface to clients. You’re still using that old PPD-based system and binary plugins to actually make it work, even though the clients would never be able to talk to this robot

There is an official path forward via things PAPPL. That project uses the new parts of CUPS to provide IPPEverywhere, but throws away the old driver parts and asks printer manufactures (and integrators) to write against a document-oriented interfaces instead of making random shell calls on a stream. It’s a good idea

But unless you want to reverse-engineer the binary drivers your printer manufacture provides, the best we can do is cram the old CUPS callstack into a wrapper and pretend we don’t see it. That seems to be the official recommendation: https://github.com/apple/cups/issues/5271


In the mean time, here’s a one-line patch to force CUPS-2.4.2 to advertise the “printer-dns-sd-name” attribute even if it isn’t connected to Avahi. I am not clear why the CUPS team thinks it’s important to hide this attribute when Avahi is down. This attribute is not technically needed to print, but without it the printer will have a blank name on IPPEverywhere clients1

The string printer->reg_name is usually different from printer->name – often reg_name is “printer @ host” and is supplied by Avahi – but as far as I can tell this string is only used for display purposes and is not subject to format restrictions, so I picked something easy to code

diff -urN cups-2.4.2.orig/scheduler/ipp.c cups-2.4.2/scheduler/ipp.c
--- cups-2.4.2.orig/scheduler/ipp.c	2025-01-06 15:44:09.205483250 +0000
+++ cups-2.4.2/scheduler/ipp.c	2025-01-06 15:47:05.957099061 +0000
@@ -4947,7 +4947,7 @@
     if (printer->reg_name)
       ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-dns-sd-name", NULL, printer->reg_name);
     else
-      ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_NOVALUE, "printer-dns-sd-name", 0);
+      ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-dns-sd-name", NULL, printer->name);
   }
 #endif /* HAVE_DNSSD */
 
  1. At least on iOS ↩︎

Leave a Reply

Your email address will not be published. Required fields are marked *