GNOME Bugzilla – Bug 693738
gtk print dialog shows "Getting printer information failed" for cups remote printer
Last modified: 2015-05-13 10:35:40 UTC
Created attachment 235949 [details] Print Dialog with error Description of problem: All the GTK applications are hitting in the bug: "Getting printer information failed" in the Print Dialog Other applications work. Version-Release number of selected component (if applicable): cups-1.4.2-48.el6_3.3.x86_64 gtk2-2.18.9-10.el6.x86_64 How reproducible: Always. Steps to Reproduce: 1. Install a Print Server (RHEL6.3). 2. Install a Client (RHEL6.3) 3. Try to print in a GTK application. For example, Firefox, gnome-help or gimp. (with others it works). Actual results: The client can see the shared printers, but the Print Dialog has the Print button disabled and the message is "Getting printer information failed". Expected results: No error. The button is enabled and printing is possible. Additional info: The lpoptions appear well defined. The printer is accessible at "printer-uri-supported=ipp://192.168.122.99:63101/printers/HP-LaserJet-5200" : # lpoptions auth-info-required=none copies=1 device-uri=ipp://192.168.122.99:63101/printers/HP-LaserJet-5200 job-hold-until=no-hold job-priority=50 marker-change-time=1360357008 marker-colors=none marker-levels=24 marker-names='Black Cartridge HP Q7516A' marker-types=tonerCartridge number-up=1 printer-info='HP LaserJet 5200' printer-is-accepting-jobs=true printer-is-shared=false printer-location='GSS 2' printer-make-and-model='HP LaserJet 5200 Postscript (recommended) on 192.168.122.99' printer-state=3 printer-state-change-time=1360356574 printer-state-reasons=none printer-type=27439302 printer-uri-supported=ipp://192.168.122.99:63101/printers/HP-LaserJet-5200 But strace shows that the port number is ignored and the default ipp port is used instead : 2665 connect(22, {sa_family=AF_INET, sin_port=htons(631), sin_addr=inet_addr("192.168.122.99")}, 16) = -1 EINPROGRESS (Operation now in progress) 2665 connect(22, {sa_family=AF_INET, sin_port=htons(631), sin_addr=inet_addr("192.168.122.99")}, 16) = -1 ECONNREFUSED (Connection refused) 2665 close(22) = 0 The following is a tcpdump from the server side : # tcpdump -nn -v -i any host 192.168.122.228 tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes 19:15:56.413416 IP (tos 0x0, ttl 64, id 52810, offset 0, flags [DF], proto TCP (6), length 60) 192.168.122.228.50929 > 192.168.122.99.631: Flags [S], cksum 0x1a9c (correct), seq 2187211175, win 14600, options [mss 1460,sackOK,TS val 6815725 ecr 0,nop,wscale 7], length 0 19:15:56.413462 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40) 192.168.122.99.631 > 192.168.122.228.50929: Flags [R.], cksum 0xbbc8 (correct), seq 0, ack 2187211176, win 0, length 0 19:16:06.240436 IP (tos 0x0, ttl 64, id 55959, offset 0, flags [DF], proto TCP (6), length 209) Has a workaround, if the server also listens on port 631, everything works as expected. Thank you
Hi, I did more testes regarding this issue, suspecting a wrong configuration, but I just confirmed the issue. Server has in cupsd.conf: Port 63101 BrowsePort 63101 Client has cupsd.conf: BrowsePoll 192.168.122.99:63101 BrowsePort 63101 Firewall allows traffic: 7 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:63101 8 ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 state NEW udp dpt:63101 SELinux allows the non-standaard port 63101 in the server and the client: # semanage port -l | grep ipp ipp_port_t tcp 63101, 631, 8610-8614 ipp_port_t udp 63101, 631, 8610-8614 All the non-Gtk application work as expected, using only the port 63101/tcp and udp, but when the Gtk Print Dialog starts the following communications is attempted and fails: 20:24:33.886932 IP 192.168.122.228.52755 > 192.168.122.99.631: Flags [S], seq 1291153458, win 14600, options [mss 1460,sackOK,TS val 5593038 ecr 0,nop,wscale 7], length 0 20:24:33.887248 IP 192.168.122.99.631 > 192.168.122.228.52755: Flags [R.], seq 0, ack 1291153459, win 0, length 0 I tried setting the IPP_PORT Env variable without success. Looking at the source code, I noticed that the Gtk platform when connecting to the cups server uses always the Cups API function "ippPort()" : request->http = httpConnectEncrypt (request->server, ippPort (), cupsEncryption ()); Looking at the ippPort definition in gtk+-2.18.9/modules/printbackends/cups/gtkcupsutils.c : ###################### int /* O - Port number */ ippPort(void) { _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ DEBUG_puts("ippPort()"); if (!cg->ipp_port) _cupsSetDefaults(); DEBUG_printf(("1ippPort: Returning %d...", cg->ipp_port)); return (cg->ipp_port); } ####################### It's not clear what port the function is really returning, but it must be in the library globals: Any thoughts ? Thank you Best regards, Rui Gouveia Red Hat UK, GSS
Hello again, The function _cupsSetDefaults in cups-1.4.2/cups/usersys.c is: ####################### /* * '_cupsSetDefaults()' - Set the default server, port, and encryption. */ void _cupsSetDefaults(void) { cups_file_t *fp; /* File */ const char *home, /* Home directory of user */ *cups_encryption, /* CUPS_ENCRYPTION env var */ *cups_server; /* CUPS_SERVER env var */ char filename[1024]; /* Filename */ _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ DEBUG_puts("_cupsSetDefaults()"); /* * First collect environment variables... */ cups_encryption = getenv("CUPS_ENCRYPTION"); cups_server = getenv("CUPS_SERVER"); /* * Then, if needed, the .cups/client.conf or .cupsrc file in the home * directory... */ if ((cg->encryption == (http_encryption_t)-1 || !cg->server[0] || !cg->ipp_port) && (home = getenv("HOME")) != NULL) { /* * Look for ~/.cups/client.conf or ~/.cupsrc... */ snprintf(filename, sizeof(filename), "%s/.cups/client.conf", home); if ((fp = cupsFileOpen(filename, "r")) == NULL) { snprintf(filename, sizeof(filename), "%s/.cupsrc", home); fp = cupsFileOpen(filename, "r"); } if (fp) { cups_read_client_conf(fp, cg, cups_encryption, cups_server); cupsFileClose(fp); } } if (cg->encryption == (http_encryption_t)-1 || !cg->server[0] || !cg->ipp_port) { /* * Look for CUPS_SERVERROOT/client.conf... */ snprintf(filename, sizeof(filename), "%s/client.conf", cg->cups_serverroot); if ((fp = cupsFileOpen(filename, "r")) != NULL) { cups_read_client_conf(fp, cg, cups_encryption, cups_server); cupsFileClose(fp); } } /* * If we still have things that aren't set, use the compiled in defaults... */ if (cg->encryption == (http_encryption_t)-1) cg->encryption = HTTP_ENCRYPT_IF_REQUESTED; if (!cg->server[0]) { if (!cups_server) { #ifdef CUPS_DEFAULT_DOMAINSOCKET /* * If we are compiled with domain socket support, only use the * domain socket if it exists and has the right permissions... */ struct stat sockinfo; /* Domain socket information */ if (!stat(CUPS_DEFAULT_DOMAINSOCKET, &sockinfo) && (sockinfo.st_mode & S_IRWXO) == S_IRWXO) cups_server = CUPS_DEFAULT_DOMAINSOCKET; else #endif /* CUPS_DEFAULT_DOMAINSOCKET */ cups_server = "localhost"; } cupsSetServer(cups_server); } if (!cg->ipp_port) { const char *ipp_port; /* IPP_PORT environment variable */ struct servent *service; /* Port number info */ if ((ipp_port = getenv("IPP_PORT")) != NULL) { if ((cg->ipp_port = atoi(ipp_port)) <= 0) cg->ipp_port = CUPS_DEFAULT_IPP_PORT; } else if ((service = getservbyname("ipp", NULL)) == NULL || service->s_port <= 0) cg->ipp_port = CUPS_DEFAULT_IPP_PORT; else cg->ipp_port = ntohs(service->s_port); } } ####################### If I define the ENV vars: IPP_PORT and CUPS_SERVER it works!!! :) Since the server is parsed correctly, the problem must be in the port selection. Agree? Thank you Best regards, Rui Gouveia Red Hat UK, GSS
Looking at the function _cupsSetDefaults(void)... Since the server is parsed correctly, the problem must be in the port selection. Correct me if I'm wrong. ### If cg->ipp_port is not defined if (!cg->ipp_port) { const char *ipp_port; /* IPP_PORT environment variable */ struct servent *service; /* Port number info */ ### ipp_port takes the value from ENV(IPP_PORT) and is not null. if ((ipp_port = getenv("IPP_PORT")) != NULL) { ### If conversion from string to integer generates an ### error cg->ipp_port takes the default value CUPS_DEFAULT_IPP_PORT if ((cg->ipp_port = atoi(ipp_port)) <= 0) cg->ipp_port = CUPS_DEFAULT_IPP_PORT; } ### else, if ipp does not exists in the system services ### or service->s_port has an invalid value, then ### cg->ipp_port takes the default value CUPS_DEFAULT_IPP_PORT else if ((service = getservbyname("ipp", NULL)) == NULL || service->s_port <= 0) cg->ipp_port = CUPS_DEFAULT_IPP_PORT; ### else, cg->ipp_port takes the value of the services value. else cg->ipp_port = ntohs(service->s_port); } So, if IPP_PORT is defined, all is ok, but if not, this code jumps directly to getting the default value in services. So, where is the value in the configuration read ? I may be analyzing the wrong code here... Help is appreciated. Thank you Best regards, Rui Gouveia Red Hat UK, GSS
Created attachment 280493 [details] [review] Check connection to remote CUPS server on correct port (gtk+-2.24 version) The problem is that the connection test connects always to standard port provided by ippPort(). It should connect to the port taken from uri of the remote printer instead. The attached patch solves the problem by adding a parameter for specification of the port to gtk_cups_connection_cups_new() and by specifying the port where needed.
Created attachment 280494 [details] [review] Check connection to remote CUPS server on correct port (gtk master version)
Review of attachment 280494 [details] [review]: makes sense to me. please put this on the 3.16 and 3.14 branches too
Review of attachment 280493 [details] [review]: ok.
Did these patches get lost?
Thank you for the review. I wasn't added to CC when I've attached the patch so I missed the Matthias' review. I've pushed the patch to 2.24, 3.14, 3.16 and master.