5.2 KiB
Design
Context
See proposal.md — Why.
The relevant facts, all from the running system (macOS 27.0.1 build 26A434, CUPS 2.4.2 in the container) and the CUPS sources:
- The container registers the queue with CUPS' own DNS-SD code
(
scheduler/dirsvc.c):_printer._tcpunconditionally, and_ipp._tcp/_ipps._tcpwith the sub-type list fromDNSSDSubTypes. The list is passed to oneDNSServiceRegistercall as<type>,<subtypes>(snprintf(temp, "%s,%s", type, subtypes)), soDNSSDSubTypesdecides the whole sub-type set. DNSSDSubTypesdefaults to_cups,_print,_universal(scheduler/conf.c) and is settable with theBrowseDNSSDSubTypesdirective.- The queue's TXT record already carries what a driverless client needs:
URF,pdl=…,image/urf,TLS=1.2,Color=T,Duplex=T,mopria-certified=1.3. - macOS' Add Printer browser (
AddPrinter.app'sPMBrowser.framework) browses_ipp._tcp,_cupsand_ipp._tcp,_universal(plus the_ippsforms) and keys a printer's registration types by theregTypethe browse callback reports.-[DNSSDPrinter isShared]is YES when any of them ends in,_cups, and-[DNSSDPrinter airprintMatch]returns nothing whenisSharedis YES.
Goals / Non-Goals
Goals:
- The queue is advertised so that macOS classifies it as an AirPrint printer and offers the driverless driver, without changing anything else a client sees.
Non-Goals:
- Replacing CUPS' DNS-SD advertising with hand-written Avahi service files, or changing the TXT record CUPS generates. CUPS' advertisement works for every other client; only the sub-type set is wrong.
- Changing the certificate, the queue's PPD or the device URI.
Decisions
Drop _cups from DNSSDSubTypes instead of suppressing CUPS' registration.
BrowseDNSSDSubTypes _print,_universal removes exactly the marker that makes
macOS treat the queue as shared, while keeping the _universal sub-type that
makes isAirPrint YES. _print is kept because CUPS ships it by default and
dropping it would remove information some clients use, with no benefit here.
Alternatives considered:
- Advertise the queue with a hand-written Avahi service definition and turn
CUPS' own advertising off. Gives full control over sub-types and TXT, but
duplicates what CUPS already generates (including the UUID and
printer-typeTXT that CUPS clients resolve the queue with) and has to be kept in sync with the queues. Only worth it if the sub-type turns out not to be sufficient. - Keep
_cupsand patch macOS' classification — not possible; it is the client's behaviour. - Stop sharing the printer (
printer-is-shared=false) — would remove the queue from mDNS entirely.
Keep CUPS' TXT record and the /cups device URI.
The /cups path marker and the printer-type TXT key come from CUPS' own
advertisement and tell CUPS clients that this is a CUPS server; they are what
makes dnssd://…/cups?uuid=… resolve. macOS' sub-type-based isShared is a
separate mechanism from that marker, so removing the sub-type keeps CUPS
clients working while fixing macOS' driver choice.
Rely on airprintMatch's remaining requirements being satisfied by the
existing advertisement.
After the sub-type fix, airprintMatch also needs a device-ID entry with the
TXT-derived URF: key and a dnssd servicetype: entry for _ipp._tcp /
_ipps._tcp, and a locally built generic URF PPD. Those come from the printer's
TXT record, which already carries URF and pdl (PMBrowser normalises TXT keys
to its KEY: form) and from the service type in the browse result — the same
inputs a real AirPrint printer provides. If the GUI still offers only the
generic driver, the fallback is the Avahi service file mentioned above.
Risks / Trade-offs
- [The queue is still classified as shared because the
/cupsdevice URI orprinter-typeTXT matter in a code path not covered by the disassembly] → Small risk; the disassembly ofisShared/isAirPrint/airprintMatchcovers the driver-choice gate. Verify on the client; fall back to an Avahi service file if needed. - [Some client relies on the
_cupssub-type to identify the server] → CUPS'dnssdbackend uses the TXTprinter-type/cups_sharedmarker for that, not the sub-type, so the/cupsURI is unchanged. Verify withlpinfo -von a CUPS client. - [
cupsctl's rewrite of/etc/cups/cupsd.confdrops the directive] →cupsAdminSetServerSettings()copies unrecognised directives through verbatim (cups/adminutil.c), soBrowseDNSSDSubTypessurvives thecupsctl --share-printers --remote-adminthe entrypoint runs after cupsd has started. Confirmed by reading the write loop, not by a live run. - [macOS caches the previous classification for an existing printer entry] → Nothing the server can do; the printer has to be removed and added again. It is documented in the README.
Migration Plan
Rebuild and redeploy the image; no volume reset. cupsd re-registers the
queue's services on start and drops the _cups sub-type, so the change takes
effect immediately (mDNS caching on clients aside). Rollback is redeploying the
previous image; the extra sub-type reappears and macOS falls back to the generic
driver as before.