OpenPrinting / cups

OpenPrinting CUPS Sources
https://openprinting.github.io/cups
Apache License 2.0
956 stars 174 forks source link

CUPS discovers its own shared queues and creates temporary queues pointing to itself #176

Open tillkamppeter opened 3 years ago

tillkamppeter commented 3 years ago

I create a CUPS queue on my locally installed CUPS and share it (turn sharing for CUPS on and also mark the printer itself shared). On remote machines it gets visible by that, as expected.

Now I call cupsEnumDests() like this:

  cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, 0, 0,
                (cups_dest_cb_t)add_dest_cb, dest_list);

to let the callback function add_dest_cb() add all printers reported to dest_list. In the end the list contains all permanent queues which I have created and it also contains the IPP printers discovered in the network (advertsed via DNS-SD).

This is all OK, but cupsEnumDests() also discovers the shared printers on my local CUPS. So if I have created a queue named printer and shared it and the host name of my local machine is my_cups_server, cupsEnumDests() also lists a discovered printer making up a temporary queue named printer_my_cups_server and when printing to it this queue gets created with the device URI ipps://my_cups_server:631/printers/printer making my CUPS daemon passing on a job to this queue to itself, into the queue printer.

cupsEnumDests() (or cupsd if it is doing the "dirty work" for this function) needs a filter to exclude temporary queues for shared local (from the same cupsd) printers.

michaelrsweet commented 3 years ago

@tillkamppeter Can you provide the output of lpstat -v and lpstat -e?

tillkamppeter commented 3 years ago

Here we go:

$ lpstat -v
device for commandtops-test: usb://HP/OfficeJet%20Pro%208730?serial=CN783F60W1&interface=1
device for Printer: ipps://HP%20OfficeJet%20Pro%208730%20%5B08C229%5D._ipps._tcp.local/
device for second: /dev/null
$ lpstat -e
commandtops-test
Printer
second
$ lpstat -l -e
commandtops-test permanent ipp://localhost/printers/commandtops-test usb://HP/OfficeJet%20Pro%208730?serial=CN783F60W1&interface=1
Printer permanent ipp://localhost/printers/Printer ipps://HP%20OfficeJet%20Pro%208730%20%5B08C229%5D._ipps._tcp.local/
second permanent ipp://localhost/printers/second file:/dev/null
$

lpstat -e does not reveal this problem, unfortunately (another bug?), but right after I run a program which uses cupsEnumDests() to list all CUPS queues including the potential ones for discovered printers and then exercises the queue of each listed printer, I get:

$ lpstat -v
device for commandtops-test: usb://HP/OfficeJet%20Pro%208730?serial=CN783F60W1&interface=1
device for commandtops_test_till_x1nano: ipps://till-x1nano.local:631/printers/commandtops-test
device for Printer: ipps://HP%20OfficeJet%20Pro%208730%20%5B08C229%5D._ipps._tcp.local/
device for Printer_till_x1nano: ipps://till-x1nano.local:631/printers/Printer
device for second: /dev/null
device for second_till_x1nano: ipps://till-x1nano.local:631/printers/second

The potential queues are now physically created and therefore listed by lpstat -v. This means that cupsEnumDests()sees 6 queues, the 3 ones physically created in the first place and 3 additional ones pointing to the 3 first ones. Note that my machine's host name is till-x1nano.local and my CUPS here is an unsnapped standard CUPS running on port 631 (and also on /run/cups/cups.sock. All the three CUPS printers are shared.

tillkamppeter commented 3 years ago

This is the call of cupsEnumDests() which I am using:

  cupsEnumDests(CUPS_DEST_FLAGS_NONE, 1000, NULL, 0, 0,
        (cups_dest_cb_t)add_dest_cb, dest_list);

This is the callback function add_dest_cb():

int
add_dest_cb(dest_list_t *user_data, unsigned flags, cups_dest_t *dest)
{
  if (flags & CUPS_DEST_FLAGS_REMOVED)
    /* Remove destination from array */
    user_data->num_dests =
      cupsRemoveDest(dest->name, dest->instance, user_data->num_dests,
             &(user_data->dests));
  else {
    /* Add destination to array... */
    user_data->num_dests =
      cupsCopyDest(dest, user_data->num_dests,
           &(user_data->dests));
    if (dest->is_default)
      user_data->default_dest =
    cupsGetDest(dest->name, dest->instance, user_data->num_dests,
            user_data->dests);
  }
  return (1);
}
tillkamppeter commented 3 years ago

lpstat -e uses cupsGetDests(), lpstat -v uses a CUPS_GET_PRINTERS IPP request.

michaelrsweet commented 2 years ago

OK, I think the Avahi rejection of local queues isn't working like it does with mDNSResponder. I will add a UUID array to reject identical UUIDs.

tillkamppeter commented 2 years ago

UUID array, exactly what I also do in cups-browsed ...

tillkamppeter commented 2 years ago

Also reported on Launchpad for Ubuntu.

doronbehar commented 6 months ago

Also reported on Launchpad for Ubuntu.

Hey all, I reached this issue after reading the above issue, and trying to investigate and maybe help resolve the issue. I'm not sure how is this issue related to the issue described in these reports:

My conclusion after reading the above reports, is that all of the suggested solutions essentially disable Avahi and hence makes it much harder to add printers to CUPS when one actually wants to add a printer discoverable from the local network.

Interestingly, I also discovered that the issue is not directly due to Avahi's behavior, but to GNOME's request from CUPS to give a list of printers. I reached this conclusion after I checked whether the gnome-control-center source code has reference to Avahi, and it doesn't.

Hence I ask: Is there a way for GNOME to differentiate between printers that were actually configured by CUPS' web interface, and printers that cups simply discovers using Avahi? That would help the GNOME developers to fix the issue.

michaelrsweet commented 2 months ago

Does this still happen in the CUPS 2.5 tree with its improved DNS-SD support?

tillkamppeter commented 2 months ago

I have built 2.5.x from GIT master now, but it seems that it does not detect any services via DNS-SD any more (2.4.x does for me).

Here are the available print destinations discovered by DNS-SD:

$ driverless
ipp://HP%20OfficeJet%20Pro%208730%20%5B5B78A3%5D%20(USB)._ipp._tcp.local/
ipps://Canon._ipps._tcp.local/
ipps://HP%20OfficeJet%20Pro%208730%20%5B5B78A3%5D._ipps._tcp.local/
ipps://abc._ipps._tcp.local/
ipps://dnssd._ipps._tcp.local/
ipps://hostname._ipps._tcp.local/
ipps://hp4050._ipps._tcp.local/
ipps://psc2500%20(E313F0)._ipps._tcp.local/
ipps://snmp._ipps._tcp.local/
ipps://test._ipps._tcp.local/
ipps://test-query._ipps._tcp.local/
ipps://test10%20(D7FE90)._ipps._tcp.local/
ipps://test2%20(460BFB)._ipps._tcp.local/
ipps://test3%20(CN783F60W1&interface=1)._ipps._tcp.local/
ipps://test4%20(F7866E)._ipps._tcp.local/
ipps://test5%20(9EA687)._ipps._tcp.local/
ipps://test6%20(59CD60)._ipps._tcp.local/
ipps://usb._ipps._tcp.local/
ipps://utax._ipps._tcp.local/
ipps://x._ipps._tcp.local/
ipps://xyz123._ipps._tcp.local/
$

Now I check what CUPS is seeing:

$ lpstat -l -e
Printer permanent ipp://localhost/printers/Printer ipps://HP%20OfficeJet%20Pro%208730%20%5B5B78A3%5D._ipps._tcp.local/
PrinterVV permanent ipp://localhost/printers/PrinterVV ipps://HP14CB19D68D1E.local:631/ipp/print
testprinter permanent ipp://localhost/printers/testprinter file:/tmp/printout
$

And this is not caused by the _CUPS_DNSSD_GET_DESTS timeout. I have raised it from the now 1 sec to 5 sec and get the same result.

So it seems to generally not detect services via DNS-SD. I have checked ldd /usr/sbin/cupsd and the Avahi libraries are used.

So this way I cannot test the presence or absence of ghost queues accompanying the permanent queues ...