0330160936
Resolves: RHEL-60309
2391 lines
73 KiB
Diff
2391 lines
73 KiB
Diff
From 1d1072a0de573b7850958df614e9ec5b73ea0e0d Mon Sep 17 00:00:00 2001
|
|
From: Till Kamppeter <till.kamppeter@gmail.com>
|
|
Date: Tue, 1 Oct 2024 00:59:58 +0200
|
|
Subject: [PATCH] Removed support for legacy CUPS browsing and for LDAP
|
|
|
|
Legacy CUPS browsing is not needed any more. this functionality got
|
|
removed from CUPS with version 1.6, more than a decade ago. In
|
|
cups-browsed it was implemented as a legacy support layer for servers
|
|
or clients running long-term-support enterprise distributions still
|
|
using CUPS 1.5.x or older. Now the support life of all these
|
|
distributions should have expired and so this legacy support by
|
|
cups-browsed is not needed any more.
|
|
|
|
In addition, the legacy CUPS browsing implementation in cups-browsed
|
|
was listening for UDP packaets on port 631 and by default it accepted
|
|
packets from any source, making it easy for attackers to set up forged
|
|
printers which could make use of vulnerabilities of CUPS or just find
|
|
out about the identity and properties of clients. This is
|
|
CVE-2024-47176:
|
|
|
|
https://ubuntu.com/security/CVE-2024-47176
|
|
https://github.com/OpenPrinting/cups-browsed/security/advisories/GHSA-rj88-6mr5-rcw8
|
|
https://openprinting.github.io/OpenPrinting-News-Flash-cups-browsed-Remote-Code-Execution-vulnerability/
|
|
|
|
The removal of the legacy CUPS browsing support removes also this
|
|
vulnerability.
|
|
|
|
The LDAP implementation in cups-browsed does not follow the LDAP
|
|
printer schema RFC 7612 and is therefore of very limited use.
|
|
---
|
|
INSTALL | 3 +-
|
|
README.md | 53 +-
|
|
configure.ac | 46 +-
|
|
daemon/cups-browsed.8 | 38 +-
|
|
daemon/cups-browsed.c | 1675 ++---------------------------------
|
|
daemon/cups-browsed.conf.5 | 43 +-
|
|
daemon/cups-browsed.conf.in | 27 +-
|
|
test/run-tests.sh | 4 +-
|
|
8 files changed, 138 insertions(+), 1751 deletions(-)
|
|
|
|
diff --git a/INSTALL b/INSTALL
|
|
index 7c5d5941..e48305d2 100644
|
|
--- a/INSTALL
|
|
+++ b/INSTALL
|
|
@@ -111,5 +111,4 @@ PACKAGING THE SOFTWARE FOR OPERATING SYSTEM DISTRIBUTIONS
|
|
`--enable-auto-setup-driverless-only` then.
|
|
|
|
Otherwise cups-browsed is only needed for more advanced setups,
|
|
- like printer clusters or support for legacy CUPS (< 1.6.x) on
|
|
- remote servers or clients.
|
|
+ like printer clusters.
|
|
diff --git a/README.md b/README.md
|
|
index fbdcd186..ee4ee88d 100644
|
|
--- a/README.md
|
|
+++ b/README.md
|
|
@@ -26,15 +26,6 @@ cups-browsed has the following functionality:
|
|
several print dialogs use old CUPS APIs and therefore require
|
|
permanent local queues to see such printers.
|
|
|
|
-- Auto-discover shared printers on remote CUPS servers running CUPS
|
|
- 1.5.x or older via legacy CUPS browsing. This is intended for
|
|
- settings with print servers running long-term-support enterprise
|
|
- distributions.
|
|
-
|
|
-- Broadcast shared local printers using legacy CUPS browsing (of CUPS
|
|
- 1.5.x) for settings with printing clients running long-term-support
|
|
- enterprise distributions.
|
|
-
|
|
- Creating printer clusters where jobs are printed to one single queue
|
|
and get automatically passed on to a suitable member printer.
|
|
|
|
@@ -63,8 +54,8 @@ cups-browsed has the following functionality:
|
|
|
|
- Highly configurable: Which printers are considered? For which type
|
|
of printers queues are created? Cluster types and member printers?
|
|
- which names auto-created queues should get? DNS-SD and/or legacy
|
|
- browsing? ...
|
|
+ which names auto-created queues should get? DNS-SD and/or
|
|
+ BrowsePoll? ...
|
|
|
|
- Multi-threading allows several tasks to be done in parallel and
|
|
assures responsiveness of the daemon when there is a large amount of
|
|
@@ -154,43 +145,33 @@ Most of this is still valid for the current cups-browsed.
|
|
### HELPER DAEMON FOR BROWSING REMOTE CUPS PRINTERS AND IPP NETWORK PRINTERS
|
|
|
|
From version 1.6.0 on in CUPS the CUPS broadcasting/browsing
|
|
-facility was dropped, in favour of Bonjour-based broadcasting of
|
|
-shared printers. This is done as Bonjour broadcasting of shared
|
|
+facility was dropped, in favour of DNS-SD-based broadcasting of
|
|
+shared printers. This is done as DNS-SD broadcasting of shared
|
|
printers is a standard, established by the PWG (Printing Working
|
|
Group, http://www.pwg.org/), and most other network services
|
|
(shared file systems, shared media files/streams, remote desktop
|
|
-services, ...) are also broadcasted via Bonjour.
|
|
+services, ...) are also broadcasted via DNS-SD.
|
|
|
|
Problem is that CUPS only broadcasts its shared printers but does
|
|
not browse broadcasts of other CUPS servers to make the shared
|
|
remote printers available locally without any configuration
|
|
efforts. This is a regression compared to the old CUPS
|
|
broadcasting/browsing. The intention of CUPS upstream is that the
|
|
-application's print dialogs browse the Bonjour broadcasts as an
|
|
+application's print dialogs browse the DNS-SD broadcasts as an
|
|
AirPrint-capable iPhone does, but it will take its time until all
|
|
toolkit developers add the needed functionality, and programs
|
|
using old toolkits or no toolkits at all, or the command line stay
|
|
uncovered.
|
|
|
|
-The solution is cups-browsed, a helper daemon running in parallel
|
|
-to the CUPS daemon which listens to Bonjour broadcasts of shared
|
|
-CUPS printers on remote machines in the local network via Avahi,
|
|
-and can also listen for (and send) CUPS Browsing broadcasts. For
|
|
-each reported remote printer it creates a local raw queue pointing
|
|
-to the remote printer so that the printer appears in local print
|
|
-dialogs and is also available for printing via the command
|
|
-line. As with the former CUPS broadcasting/browsing with this
|
|
-queue the driver on the server is used and the local print dialogs
|
|
-give access to all options of the server-side printer driver.
|
|
-
|
|
-Note that CUPS broadcasting/browsing is available for legacy
|
|
-support, to let the local CUPS daemon work seamlessly together
|
|
-with remote CUPS daemons of version 1.5.x and older which only
|
|
-support CUPS broadcasting/browsing. In networks with only CUPS
|
|
-1.6.x servers (or Ubuntu or Fedora/Red Hat servers with CUPS
|
|
-1.5.x) please use the native Bonjour broadcasting of your servers
|
|
-and cups-browsed, configured for Bonjour browsing only on the
|
|
-clients.
|
|
+The solution is cups-browsed, a helper daemon running in parallel to
|
|
+the CUPS daemon which listens to DNS-SD broadcasts of shared CUPS
|
|
+printers on remote machines in the local network via Avahi. For each
|
|
+reported remote printer it creates a local raw queue pointing to the
|
|
+remote printer so that the printer appears in local print dialogs and
|
|
+is also available for printing via the command line. As with the
|
|
+former CUPS broadcasting/browsing with this queue the driver on the
|
|
+server is used and the local print dialogs give access to all options
|
|
+of the server-side printer driver.
|
|
|
|
Also high availability with redundant print servers and load
|
|
balancing is supported. If there is more than one server providing
|
|
@@ -301,7 +282,7 @@ up. cups-browsed is also robust against any shutdown and restart
|
|
of avahi-daemon.
|
|
|
|
Here is some info on how cups-browsed works internally (first concept of a
|
|
-daemon which does only Bonjour browsing):
|
|
+daemon which does only DNS-SD browsing):
|
|
|
|
- Daemon start
|
|
o Wait for CUPS daemon if it is not running
|
|
@@ -357,7 +338,7 @@ appears, create new queue as <original name>@<server name without
|
|
of the others by one with simple name (mark old queue disappeared
|
|
with timeout now-1 sec and create new queue with simple name).
|
|
|
|
-Fill description of the created CUPS queue with the Bonjour
|
|
+Fill description of the created CUPS queue with the DNS-SD
|
|
service name (= original description) and location with the server
|
|
name without .local.
|
|
|
|
diff --git a/configure.ac b/configure.ac
|
|
index 84de9129..2ff5a43b 100644
|
|
--- a/configure.ac
|
|
+++ b/configure.ac
|
|
@@ -300,50 +300,6 @@ fi
|
|
AC_SUBST(AVAHI_LIBS)
|
|
AC_SUBST(AVAHI_CFLAGS)
|
|
|
|
-dnl
|
|
-dnl LDAP configuration stuff for CUPS.
|
|
-dnl
|
|
-dnl Copyright 2007-2011 by Apple Inc.
|
|
-dnl Copyright 2003-2006 by Easy Software Products, all rights reserved.
|
|
-dnl
|
|
-dnl These coded instructions, statements, and computer programs are the
|
|
-dnl property of Apple Inc. and are protected by Federal copyright
|
|
-dnl law. Distribution and use rights are outlined in the file "COPYING"
|
|
-dnl which should have been included with this file.
|
|
-dnl
|
|
-
|
|
-AC_ARG_ENABLE([ldap], [AS_HELP_STRING([--disable-ldap], [disable LDAP support.])],
|
|
- [enable_ldap="$enableval"],
|
|
- [enable_ldap=yes]
|
|
-)
|
|
-AC_ARG_WITH([ldap-libs], [AS_HELP_STRING([--with-ldap-libs], [set directory for LDAP library.])],
|
|
- LDFLAGS="-L$withval $LDFLAGS"
|
|
- DSOFLAGS="-L$withval $DSOFLAGS",)
|
|
-AC_ARG_WITH([ldap-includes], [AS_HELP_STRING([--with-ldap-includes], [set directory for LDAP includes.])],
|
|
- CFLAGS="-I$withval $CFLAGS"
|
|
- CPPFLAGS="-I$withval $CPPFLAGS",)
|
|
-
|
|
-if test x$enable_ldap != xno; then
|
|
-
|
|
- AC_CHECK_HEADER([ldap.h], [
|
|
- AC_SEARCH_LIBS([ldap_initialize], [ldap], [
|
|
- AC_DEFINE([HAVE_LDAP], [], [Define if LDAP support should be enabled])
|
|
- AC_DEFINE([HAVE_OPENLDAP], [], [If LDAP support is that of OpenLDAP])
|
|
- AC_CHECK_LIB([ldap], [ldap_start_tls],
|
|
- AC_DEFINE([HAVE_LDAP_SSL], [], [If LDAP has SSL/TLS support enabled]))],[
|
|
-
|
|
- AC_CHECK_LIB([ldap], [ldap_init], [
|
|
- AC_DEFINE([HAVE_LDAP], [], [Define if LDAP support should be enabled])
|
|
- AC_DEFINE([HAVE_MOZILLA_LDAP], [], [If LDAP support is that of Mozilla])
|
|
- AC_CHECK_HEADERS([ldap_ssl.h], [], [], [#include <ldap.h>])
|
|
- AC_CHECK_LIB([ldap], [ldapssl_init],
|
|
- AC_DEFINE([HAVE_LDAP_SSL], [], [If LDAP has SSL/TLS support enabled]))])]
|
|
- )
|
|
- AC_CHECK_LIB([ldap], [ldap_set_rebind_proc], AC_DEFINE([HAVE_LDAP_REBIND_PROC], [], [If libldap implements ldap_set_rebind_proc]))
|
|
- ])
|
|
-
|
|
-fi
|
|
-
|
|
PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.30.2])
|
|
AC_SUBST(GLIB_CFLAGS)
|
|
AC_SUBST(GLIB_LIBS)
|
|
@@ -487,7 +443,7 @@ Environment settings:
|
|
Build configuration:
|
|
cups-config: ${with_cups_config}
|
|
init directory: ${INITDDIR}
|
|
- cups dom socket: ${CUPS_DEFAULT_DOMAINSOCKET}
|
|
+ cups domain socket: ${CUPS_DEFAULT_DOMAINSOCKET}
|
|
avahi: ${enable_avahi}
|
|
browsing: ${with_browseremoteprotocols}
|
|
local queue naming for remote CUPS queues: ${REMOTE_CUPS_LOCAL_QUEUE_NAMING}
|
|
diff --git a/daemon/cups-browsed.8 b/daemon/cups-browsed.8
|
|
index 73c2f686..6eb713bf 100644
|
|
--- a/daemon/cups-browsed.8
|
|
+++ b/daemon/cups-browsed.8
|
|
@@ -16,20 +16,14 @@
|
|
.fam T
|
|
.fi
|
|
.SH DESCRIPTION
|
|
-\fBcups-browsed\fP has four independently switchable functions:
|
|
+\fBcups-browsed\fP has two independently switchable functions:
|
|
.IP 1. 4
|
|
-Browse Bonjour broadcasts of remote printers and create/remove local
|
|
-raw queues pointing to these printers.
|
|
+Browse DNS-SD broadcasts of remote printers and create/remove local
|
|
+CUPS queues pointing to these printers.
|
|
.IP 2. 4
|
|
-Browse CUPS broadcasts of remote printers and create/remove local raw
|
|
-queues pointing to these printers.
|
|
-.IP 3. 4
|
|
-Browse an LDAP server for printers and create/remove local raw
|
|
-queues pointing to these printers.
|
|
-.IP 4. 4
|
|
-Broadcast local queues with the CUPS protocol.
|
|
+Find shared printers on given CUPS servers and create local CUPS queues
|
|
+pointing to them.
|
|
.PP
|
|
-Note that 2. and 4. are only to allow communication with legacy CUPS servers (1.5.x or older) on the remote machine(s). The standard method to broadcast for shared/network printers to broadcast their presence is Bonjour. The CUPS broadcasting/browsing protocol is deprecated.
|
|
|
|
cups-browsed can be run permanently (from system boot to shutdown) or on-demand (for example to save resources on mobile devices). For running it on-demand an auto-shutdown feature can be activated to let cups-browsed terminate when it does not have queues any more to take care of.
|
|
|
|
@@ -76,28 +70,8 @@ Display usage and version info and do not start the daemon.
|
|
\fISIGUSR2\f1: Switches cups-browsed into auto shutdown mode.
|
|
|
|
.SH NOTES
|
|
-Please take references to cups 1.6.x to include newer versions.
|
|
-Similarly, cups 1.5.x is intended to encompass older versions too.
|
|
-.PP
|
|
-In environments with only cups 1.6.x servers and clients (plus
|
|
-\fBcups-browsed\fP on either server or client or both) the function described in 1.
|
|
-enables the automatic discovery of remote queues and their display in
|
|
-printing dialogues of applications and with command line tools.
|
|
-.PP
|
|
-The facility provided by 3. allows printers that are registered in an LDAP
|
|
-server to be added as local queues. CUPS servers 1.5.x are able to automatically
|
|
-register printers in LDAP. The facility provided by \fBcups-browsed\fP allows
|
|
-a filter string to further limit the printers that are browsed from LDAP.
|
|
-.PP
|
|
-The facility provided by 4. means that servers running cups 1.6.x plus
|
|
-\fBcups-browsed\fP can broadcast their local queues so that clients with cups
|
|
-1.5.x get these queues automatically available. The outcome of 2. is
|
|
-that clients running cups 1.6.x plus \fBcups-browsed\fP can use the CUPS
|
|
-broadcasts from servers with cups 1.5.x. As with browsing of Bonjour
|
|
-broadcasts, the created local raw queues are available to applications
|
|
-and command line tools.
|
|
-.PP
|
|
This manual page was written for the Debian Project, but it may be used by others.
|
|
+
|
|
.SH SEE ALSO
|
|
|
|
\fBcups-browsed.conf\fP(5)
|
|
diff --git a/daemon/cups-browsed.c b/daemon/cups-browsed.c
|
|
index 828ca94c..31122ec5 100644
|
|
--- a/daemon/cups-browsed.c
|
|
+++ b/daemon/cups-browsed.c
|
|
@@ -47,72 +47,6 @@
|
|
|
|
#include <gio/gio.h>
|
|
|
|
-
|
|
-#ifdef HAVE_LDAP
|
|
-# ifdef __sun
|
|
-# include <lber.h>
|
|
-# endif // __sun
|
|
-# include <ldap.h>
|
|
-# ifdef HAVE_LDAP_SSL_H
|
|
-# include <ldap_ssl.h>
|
|
-# endif // HAVE_LDAP_SSL_H
|
|
-#endif // HAVE_LDAP
|
|
-
|
|
-
|
|
-#ifdef HAVE_LDAP
|
|
-LDAP *BrowseLDAPHandle = NULL;
|
|
- // Handle to LDAP server
|
|
-char *BrowseLDAPBindDN = NULL,
|
|
- // LDAP login DN
|
|
- *BrowseLDAPDN = NULL,
|
|
- // LDAP search DN
|
|
- *BrowseLDAPPassword = NULL,
|
|
- // LDAP login password
|
|
- *BrowseLDAPServer = NULL,
|
|
- // LDAP server to use
|
|
- *BrowseLDAPFilter = NULL;
|
|
- // LDAP query filter
|
|
-int BrowseLDAPUpdate = TRUE,
|
|
- // enables LDAP updates
|
|
- BrowseLDAPInitialised = FALSE;
|
|
- // the init stuff has been done
|
|
-# ifdef HAVE_LDAP_SSL
|
|
-char *BrowseLDAPCACertFile = NULL;
|
|
- // LDAP CA CERT file to use
|
|
-# endif // HAVE_LDAP_SSL
|
|
-#endif // HAVE_LDAP
|
|
-
|
|
-
|
|
-#ifdef HAVE_LDAP
|
|
-#define LDAP_BROWSE_FILTER "(objectclass=cupsPrinter)"
|
|
-static LDAP *ldap_new_connection(void);
|
|
-static LDAP *ldap_reconnect(void);
|
|
-static void ldap_disconnect(LDAP *ld);
|
|
-static int ldap_search_rec(LDAP *ld, char *base, int scope,
|
|
- char *filter, char *attrs[],
|
|
- int attrsonly, LDAPMessage **res);
|
|
-static int ldap_getval_firststring(LDAP *ld, LDAPMessage *entry,
|
|
- char *attr, char *retval,
|
|
- unsigned long maxsize);
|
|
-static void ldap_freeres(LDAPMessage *entry);
|
|
-# ifdef HAVE_LDAP_REBIND_PROC
|
|
-# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
|
|
-static int ldap_rebind_proc(LDAP *RebindLDAPHandle,
|
|
- LDAP_CONST char *refsp,
|
|
- ber_tag_t request,
|
|
- ber_int_t msgid,
|
|
- void *params);
|
|
-# else
|
|
-static int ldap_rebind_proc(LDAP *RebindLDAPHandle,
|
|
- char **dnp,
|
|
- char **passwdp,
|
|
- int *authmethodp,
|
|
- int freeit,
|
|
- void *arg);
|
|
-# endif // defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
|
|
-# endif // HAVE_LDAP_REBIND_PROC
|
|
-#endif // HAVE_LDAP
|
|
-
|
|
#include <cups/cups.h>
|
|
#include <cups/raster.h>
|
|
#include <cupsfilters/ipp.h>
|
|
@@ -291,18 +225,6 @@ typedef struct local_printer_s {
|
|
gboolean cups_browsed_controlled;
|
|
} local_printer_t;
|
|
|
|
-// Browse data to send for local printer
|
|
-typedef struct browse_data_s
|
|
-{
|
|
- int type;
|
|
- int state;
|
|
- char *uri;
|
|
- char *location;
|
|
- char *info;
|
|
- char *make_model;
|
|
- char *browse_options;
|
|
-} browse_data_t;
|
|
-
|
|
// Data structure for manual definition of load-balancing clusters
|
|
typedef struct cluster_s
|
|
{
|
|
@@ -439,8 +361,6 @@ static browsepoll_t *local_printers_context = NULL;
|
|
static http_t *local_conn = NULL;
|
|
static gboolean inhibit_local_printers_update = FALSE;
|
|
|
|
-static GList *browse_data = NULL;
|
|
-
|
|
static CupsNotifier *cups_notifier = NULL;
|
|
|
|
static GMainLoop *gmainloop = NULL;
|
|
@@ -450,23 +370,10 @@ static AvahiClient *client = NULL;
|
|
static AvahiServiceBrowser *sb1 = NULL, *sb2 = NULL;
|
|
static int avahi_present = 0;
|
|
#endif // HAVE_AVAHI
|
|
-#ifdef HAVE_LDAP
|
|
-static const char * const ldap_attrs[] =// CUPS LDAP attributes
|
|
- {
|
|
- "printerDescription",
|
|
- "printerLocation",
|
|
- "printerMakeAndModel",
|
|
- "printerType",
|
|
- "printerURI",
|
|
- NULL
|
|
- };
|
|
-#endif // HAVE_LDAP
|
|
static guint queues_timer_id = 0;
|
|
static int browsesocket = -1;
|
|
|
|
#define BROWSE_DNSSD (1<<0)
|
|
-#define BROWSE_CUPS (1<<1)
|
|
-#define BROWSE_LDAP (1<<2)
|
|
static unsigned int BrowseLocalProtocols = 0;
|
|
static unsigned int BrowseRemoteProtocols = BROWSE_DNSSD;
|
|
static unsigned int BrowseInterval = 60;
|
|
@@ -4113,1087 +4020,106 @@ get_local_printers (void)
|
|
g_hash_table_insert (local_printers,
|
|
g_ascii_strdown (dest->name, -1),
|
|
printer);
|
|
- }
|
|
-
|
|
- cupsFreeDests (num_dests, dests);
|
|
-
|
|
- pthread_rwlock_unlock(&lock);
|
|
-}
|
|
-
|
|
-
|
|
-static browse_data_t *
|
|
-new_browse_data (int type, int state, const gchar *uri,
|
|
- const gchar *location, const gchar *info,
|
|
- const gchar *make_model, const gchar *browse_options)
|
|
-{
|
|
- browse_data_t *data = g_malloc (sizeof (browse_data_t));
|
|
- data->type = type;
|
|
- data->state = state;
|
|
- data->uri = g_strdup (uri);
|
|
- data->location = g_strdup (location);
|
|
- data->info = g_strdup (info);
|
|
- data->make_model = g_strdup (make_model);
|
|
- data->browse_options = g_strdup (browse_options);
|
|
- return (data);
|
|
-}
|
|
-
|
|
-
|
|
-static void
|
|
-browse_data_free (gpointer data)
|
|
-{
|
|
- browse_data_t *bdata = data;
|
|
- debug_printf("browse_data_free() in THREAD %ld\n", pthread_self());
|
|
- g_free (bdata->uri);
|
|
- g_free (bdata->location);
|
|
- g_free (bdata->info);
|
|
- g_free (bdata->make_model);
|
|
- g_free (bdata->browse_options);
|
|
- g_free (bdata);
|
|
-}
|
|
-
|
|
-
|
|
-static void
|
|
-prepare_browse_data (void)
|
|
-{
|
|
- static const char * const rattrs[] = { "printer-type",
|
|
- "printer-state",
|
|
- "printer-uri-supported",
|
|
- "printer-info",
|
|
- "printer-location",
|
|
- "printer-make-and-model",
|
|
- "auth-info-required",
|
|
- "printer-uuid",
|
|
- "job-template" };
|
|
- ipp_t *request, *response = NULL;
|
|
- ipp_attribute_t *attr;
|
|
- http_t *conn = NULL;
|
|
- GString *browse_options = NULL;
|
|
-
|
|
- conn = http_connect_local ();
|
|
-
|
|
- if (conn == NULL)
|
|
- {
|
|
- debug_printf("Browse send failed to connect to localhost\n");
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- request = ippNewRequest(CUPS_GET_PRINTERS);
|
|
- ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
|
|
- "requested-attributes", sizeof (rattrs) / sizeof (rattrs[0]),
|
|
- NULL, rattrs);
|
|
- ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
|
|
- "requesting-user-name", NULL, cupsUser ());
|
|
-
|
|
- debug_printf("preparing browse data\n");
|
|
- response = cupsDoRequest (conn, request, "/");
|
|
- if (cupsLastError() > IPP_STATUS_OK_EVENTS_COMPLETE)
|
|
- {
|
|
- debug_printf("browse send failed for localhost: %s\n",
|
|
- cupsLastErrorString ());
|
|
- goto fail;
|
|
- }
|
|
-
|
|
- g_list_free_full (browse_data, browse_data_free);
|
|
- browse_data = NULL;
|
|
- for (attr = ippFirstAttribute(response); attr;
|
|
- attr = ippNextAttribute(response))
|
|
- {
|
|
- int type = -1, state = -1;
|
|
- const char *uri = NULL;
|
|
- gchar *location = NULL;
|
|
- gchar *info = NULL;
|
|
- gchar *make_model = NULL;
|
|
- browse_options = g_string_new ("");
|
|
-
|
|
- // Skip any non-printer attributes
|
|
- while (attr && ippGetGroupTag(attr) != IPP_TAG_PRINTER)
|
|
- attr = ippNextAttribute(response);
|
|
-
|
|
- if (!attr)
|
|
- break;
|
|
-
|
|
- while (attr && ippGetGroupTag(attr) == IPP_TAG_PRINTER)
|
|
- {
|
|
- const char *attrname = ippGetName(attr);
|
|
- int value_tag = ippGetValueTag(attr);
|
|
-
|
|
- if (!strcasecmp(attrname, "printer-type") &&
|
|
- value_tag == IPP_TAG_ENUM)
|
|
- {
|
|
- type = ippGetInteger(attr, 0);
|
|
- if (type & CUPS_PRINTER_NOT_SHARED)
|
|
- {
|
|
- // Skip CUPS queues not marked as shared
|
|
- state = -1;
|
|
- type = -1;
|
|
- break;
|
|
- }
|
|
- }
|
|
- else if (!strcasecmp(attrname, "printer-state") &&
|
|
- value_tag == IPP_TAG_ENUM)
|
|
- state = ippGetInteger(attr, 0);
|
|
- else if (!strcasecmp(attrname, "printer-uri-supported") &&
|
|
- value_tag == IPP_TAG_URI)
|
|
- uri = ippGetString(attr, 0, NULL);
|
|
- else if (!strcasecmp(attrname, "printer-location") &&
|
|
- value_tag == IPP_TAG_TEXT)
|
|
- {
|
|
- // Remove quotes
|
|
- gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1);
|
|
- location = g_strjoinv ("", tokens);
|
|
- g_strfreev (tokens);
|
|
- }
|
|
- else if (!strcasecmp(attrname, "printer-info") &&
|
|
- value_tag == IPP_TAG_TEXT)
|
|
- {
|
|
- // Remove quotes
|
|
- gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1);
|
|
- info = g_strjoinv ("", tokens);
|
|
- g_strfreev (tokens);
|
|
- }
|
|
- else if (!strcasecmp(attrname, "printer-make-and-model") &&
|
|
- value_tag == IPP_TAG_TEXT)
|
|
- {
|
|
- // Remove quotes
|
|
- gchar **tokens = g_strsplit (ippGetString(attr, 0, NULL), "\"", -1);
|
|
- make_model = g_strjoinv ("", tokens);
|
|
- g_strfreev (tokens);
|
|
- }
|
|
- else if (!strcasecmp(attrname, "auth-info-required") &&
|
|
- value_tag == IPP_TAG_KEYWORD)
|
|
- {
|
|
- if (strcasecmp (ippGetString(attr, 0, NULL), "none"))
|
|
- g_string_append_printf (browse_options, "auth-info-required=%s ",
|
|
- ippGetString(attr, 0, NULL));
|
|
- }
|
|
- else if (!strcasecmp(attrname, "printer-uuid") &&
|
|
- value_tag == IPP_TAG_URI)
|
|
- g_string_append_printf (browse_options, "uuid=%s ",
|
|
- ippGetString(attr, 0, NULL));
|
|
- else if (!strcasecmp(attrname, "job-sheets-default") &&
|
|
- value_tag == IPP_TAG_NAME &&
|
|
- ippGetCount(attr) == 2)
|
|
- g_string_append_printf (browse_options, "job-sheets=%s,%s ",
|
|
- ippGetString(attr, 0, NULL),
|
|
- ippGetString(attr, 1, NULL));
|
|
- else if (strstr(attrname, "-default"))
|
|
- {
|
|
- gchar *name = g_strdup (attrname);
|
|
- gchar *value = NULL;
|
|
- *strstr (name, "-default") = '\0';
|
|
-
|
|
- switch (value_tag)
|
|
- {
|
|
- gchar **tokens;
|
|
-
|
|
- case IPP_TAG_KEYWORD:
|
|
- case IPP_TAG_STRING:
|
|
- case IPP_TAG_NAME:
|
|
- // Escape value
|
|
- tokens = g_strsplit_set (ippGetString(attr, 0, NULL),
|
|
- " \"\'\\", -1);
|
|
- value = g_strjoinv ("\\", tokens);
|
|
- g_strfreev (tokens);
|
|
- break;
|
|
-
|
|
- default:
|
|
- // other values aren't needed?
|
|
- debug_printf("skipping %s (%d)\n", name, value_tag);
|
|
- break;
|
|
- }
|
|
-
|
|
- if (value)
|
|
- {
|
|
- g_string_append_printf (browse_options, "%s=%s ", name, value);
|
|
- g_free (value);
|
|
- }
|
|
-
|
|
- g_free (name);
|
|
- }
|
|
-
|
|
- attr = ippNextAttribute(response);
|
|
- }
|
|
-
|
|
- if (type != -1 && state != -1 && uri && location && info && make_model)
|
|
- {
|
|
- gchar *browse_options_str = g_string_free (browse_options, FALSE);
|
|
- browse_data_t *data;
|
|
- browse_options = NULL;
|
|
- g_strchomp (browse_options_str);
|
|
- data = new_browse_data (type, state, uri, location,
|
|
- info, make_model, browse_options_str);
|
|
- browse_data = g_list_insert (browse_data, data, 0);
|
|
- g_free (browse_options_str);
|
|
- }
|
|
-
|
|
- if (make_model)
|
|
- g_free (make_model);
|
|
-
|
|
- if (info)
|
|
- g_free (info);
|
|
-
|
|
- if (location)
|
|
- g_free (location);
|
|
-
|
|
- if (browse_options)
|
|
- {
|
|
- g_string_free (browse_options, TRUE);
|
|
- browse_options = NULL;
|
|
- }
|
|
-
|
|
- if (!attr)
|
|
- break;
|
|
- }
|
|
-
|
|
- fail:
|
|
- if (browse_options)
|
|
- g_string_free(browse_options, TRUE);
|
|
- if (response)
|
|
- ippDelete(response);
|
|
-}
|
|
-
|
|
-
|
|
-static void
|
|
-update_local_printers (void)
|
|
-{
|
|
- gboolean get_printers = FALSE;
|
|
- http_t *conn;
|
|
-
|
|
- if (inhibit_local_printers_update)
|
|
- return;
|
|
-
|
|
- conn = http_connect_local ();
|
|
- if (conn &&
|
|
- (!local_printers_context || local_printers_context->can_subscribe))
|
|
- {
|
|
- if (!local_printers_context ||
|
|
- local_printers_context->subscription_id == -1)
|
|
- {
|
|
- // No subscription yet. First, create the subscription.
|
|
- local_printers_create_subscription (conn);
|
|
- get_printers = TRUE;
|
|
- }
|
|
- else
|
|
- // We already have a subscription, so use it.
|
|
-
|
|
- // Note: for the moment, browse_poll_get_notifications() just
|
|
- // tells us whether we should re-fetch the printer list, so it
|
|
- // is safe to use here.
|
|
- get_printers = browse_poll_get_notifications (local_printers_context,
|
|
- conn);
|
|
- }
|
|
- else
|
|
- get_printers = TRUE;
|
|
-
|
|
- if (get_printers)
|
|
- {
|
|
- get_local_printers ();
|
|
-
|
|
- if (BrowseLocalProtocols & BROWSE_CUPS)
|
|
- prepare_browse_data ();
|
|
- }
|
|
-}
|
|
-
|
|
-
|
|
-static int
|
|
-check_jobs ()
|
|
-{
|
|
- int num_jobs = 0;
|
|
- cups_job_t *jobs = NULL;
|
|
- remote_printer_t *p;
|
|
- http_t *conn = NULL;
|
|
-
|
|
- conn = http_connect_local ();
|
|
- if (conn == NULL)
|
|
- {
|
|
- debug_printf("Cannot connect to local CUPS to check whether there are still jobs.\n");
|
|
- return (0);
|
|
- }
|
|
-
|
|
- if (cupsArrayCount(remote_printers) > 0)
|
|
- for (p = (remote_printer_t *)cupsArrayFirst(remote_printers);
|
|
- p;
|
|
- p = (remote_printer_t *)cupsArrayNext(remote_printers))
|
|
- if (!p->slave_of)
|
|
- {
|
|
- num_jobs = cupsGetJobs2(conn, &jobs, p->queue_name, 0,
|
|
- CUPS_WHICHJOBS_ACTIVE);
|
|
- if (num_jobs > 0)
|
|
- {
|
|
- debug_printf("Queue %s still has jobs!\n", p->queue_name);
|
|
- cupsFreeJobs(num_jobs, jobs);
|
|
- return (1);
|
|
- }
|
|
- }
|
|
-
|
|
- debug_printf("All our remote printers are without jobs.\n");
|
|
- return (0);
|
|
-}
|
|
-
|
|
-
|
|
-static gboolean
|
|
-autoshutdown_execute (gpointer data)
|
|
-{
|
|
- debug_printf("autoshutdown_execute() in THREAD %ld\n", pthread_self());
|
|
- // Are we still in auto shutdown mode and are we still without queues or
|
|
- // jobs
|
|
- if (autoshutdown &&
|
|
- (cupsArrayCount(remote_printers) == 0 ||
|
|
- (autoshutdown_on == NO_JOBS && check_jobs() == 0)))
|
|
- {
|
|
- debug_printf("Automatic shutdown as there are no print queues maintained by us or no jobs on them for %d sec.\n",
|
|
- autoshutdown_timeout);
|
|
- g_main_loop_quit(gmainloop);
|
|
- g_main_context_wakeup(NULL);
|
|
- }
|
|
-
|
|
- // Stop this timeout handler, we needed it only once
|
|
- return (FALSE);
|
|
-}
|
|
-
|
|
-
|
|
-#ifdef HAVE_LDAP_REBIND_PROC
|
|
-# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
|
|
-//
|
|
-// 'ldap_rebind_proc()' - Callback function for LDAP rebind
|
|
-//
|
|
-
|
|
-static int // O - Result code
|
|
-ldap_rebind_proc(LDAP *RebindLDAPHandle, // I - LDAP handle
|
|
- LDAP_CONST char *refsp, // I - ???
|
|
- ber_tag_t request, // I - ???
|
|
- ber_int_t msgid, // I - ???
|
|
- void *params) // I - ???
|
|
-{
|
|
- int rc; // Result code
|
|
-# if LDAP_API_VERSION > 3000
|
|
- struct berval bval; // Bind value
|
|
-# endif // LDAP_API_VERSION > 3000
|
|
- (void)request;
|
|
- (void)msgid;
|
|
- (void)params;
|
|
-
|
|
- //
|
|
- // Bind to new LDAP server...
|
|
- //
|
|
-
|
|
- debug_printf("ldap_rebind_proc: Rebind to %s\n", refsp);
|
|
-
|
|
-# if LDAP_API_VERSION > 3000
|
|
- bval.bv_val = BrowseLDAPPassword;
|
|
- bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword);
|
|
-
|
|
- rc = ldap_sasl_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, LDAP_SASL_SIMPLE,
|
|
- &bval, NULL, NULL, NULL);
|
|
-# else
|
|
- rc = ldap_bind_s(RebindLDAPHandle, BrowseLDAPBindDN, BrowseLDAPPassword,
|
|
- LDAP_AUTH_SIMPLE);
|
|
-# endif // LDAP_API_VERSION > 3000
|
|
-
|
|
- return (rc);
|
|
-}
|
|
-
|
|
-
|
|
-# else // defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
|
|
-//
|
|
-// 'ldap_rebind_proc()' - Callback function for LDAP rebind
|
|
-//
|
|
-
|
|
-static int // O - Result code
|
|
-ldap_rebind_proc(LDAP *RebindLDAPHandle, // I - LDAP handle
|
|
- char **dnp, // I - ???
|
|
- char **passwdp, // I - ???
|
|
- int *authmethodp, // I - ???
|
|
- int freeit, // I - ???
|
|
- void *arg) // I - ???
|
|
-{
|
|
- switch (freeit)
|
|
- {
|
|
- case 1:
|
|
- //
|
|
- // Free current values...
|
|
- //
|
|
-
|
|
- debug_printf("ldap_rebind_proc: Free values...\n");
|
|
-
|
|
- if (dnp && *dnp)
|
|
- free(*dnp);
|
|
-
|
|
- if (passwdp && *passwdp)
|
|
- free(*passwdp);
|
|
- break;
|
|
-
|
|
- case 0:
|
|
- //
|
|
- // Return credentials for LDAP referal...
|
|
- //
|
|
-
|
|
- debug_printf("ldap_rebind_proc: Return necessary values...\n");
|
|
-
|
|
- *dnp = strdup(BrowseLDAPBindDN);
|
|
- *passwdp = strdup(BrowseLDAPPassword);
|
|
- *authmethodp = LDAP_AUTH_SIMPLE;
|
|
- break;
|
|
-
|
|
- default:
|
|
- //
|
|
- // Should never happen...
|
|
- //
|
|
-
|
|
- debug_printf("LDAP rebind has been called with wrong freeit value!\n");
|
|
- break;
|
|
- }
|
|
-
|
|
- return (LDAP_SUCCESS);
|
|
-}
|
|
-# endif // defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
|
|
-#endif // HAVE_LDAP_REBIND_PROC
|
|
-
|
|
-
|
|
-#ifdef HAVE_LDAP
|
|
-//
|
|
-// 'ldap_new_connection()' - Start new LDAP connection
|
|
-//
|
|
-
|
|
-static LDAP * // O - LDAP handle
|
|
-ldap_new_connection(void)
|
|
-{
|
|
- int rc; // LDAP API status
|
|
- int version = 3; // LDAP version
|
|
- struct berval bv = {0, ""}; // SASL bind value
|
|
- LDAP *TempBrowseLDAPHandle=NULL;
|
|
- // Temporary LDAP Handle
|
|
-# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
|
|
- int ldap_ssl = 0; // LDAP SSL indicator
|
|
- int ssl_err = 0; // LDAP SSL error value
|
|
-# endif // defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
|
|
-
|
|
-
|
|
-# ifdef HAVE_OPENLDAP
|
|
-# ifdef HAVE_LDAP_SSL
|
|
- //
|
|
- // Set the certificate file to use for encrypted LDAP sessions...
|
|
- //
|
|
-
|
|
- if (BrowseLDAPCACertFile)
|
|
- {
|
|
- debug_printf("ldap_new_connection: Setting CA certificate file \"%s\"\n",
|
|
- BrowseLDAPCACertFile);
|
|
-
|
|
- if ((rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
|
|
- (void *)BrowseLDAPCACertFile)) != LDAP_SUCCESS)
|
|
- debug_printf("Unable to set CA certificate file for LDAP "
|
|
- "connections: %d - %s\n", rc, ldap_err2string(rc));
|
|
- }
|
|
-# endif // HAVE_LDAP_SSL
|
|
-
|
|
- //
|
|
- // Initialize OPENLDAP connection...
|
|
- // LDAP stuff currently only supports ldapi EXTERNAL SASL binds...
|
|
- //
|
|
-
|
|
- if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost"))
|
|
- rc = ldap_initialize(&TempBrowseLDAPHandle, "ldapi:///");
|
|
- else
|
|
- rc = ldap_initialize(&TempBrowseLDAPHandle, BrowseLDAPServer);
|
|
-
|
|
-# else // HAVE_OPENLDAP
|
|
-
|
|
- int ldap_port = 0; // LDAP port
|
|
- char ldap_protocol[11], // LDAP protocol
|
|
- ldap_host[255]; // LDAP host
|
|
-
|
|
- //
|
|
- // Split LDAP URI into its components...
|
|
- //
|
|
-
|
|
- if (!BrowseLDAPServer)
|
|
- {
|
|
- debug_printf("BrowseLDAPServer not configured!\n");
|
|
- debug_printf("Disabling LDAP browsing!\n");
|
|
- //BrowseLocalProtocols &= ~BROWSE_LDAP;
|
|
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
|
|
- return (NULL);
|
|
- }
|
|
-
|
|
- sscanf(BrowseLDAPServer, "%10[^:]://%254[^:/]:%d", ldap_protocol, ldap_host,
|
|
- &ldap_port);
|
|
-
|
|
- if (!strcmp(ldap_protocol, "ldap"))
|
|
- ldap_ssl = 0;
|
|
- else if (!strcmp(ldap_protocol, "ldaps"))
|
|
- ldap_ssl = 1;
|
|
- else
|
|
- {
|
|
- debug_printf("Unrecognized LDAP protocol (%s)!\n",
|
|
- ldap_protocol);
|
|
- debug_printf("Disabling LDAP browsing!\n");
|
|
- //BrowseLocalProtocols &= ~BROWSE_LDAP;
|
|
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
|
|
- return (NULL);
|
|
- }
|
|
-
|
|
- if (ldap_port == 0)
|
|
- {
|
|
- if (ldap_ssl)
|
|
- ldap_port = LDAPS_PORT;
|
|
- else
|
|
- ldap_port = LDAP_PORT;
|
|
- }
|
|
-
|
|
- debug_printf("ldap_new_connection: PROT:%s HOST:%s PORT:%d\n",
|
|
- ldap_protocol, ldap_host, ldap_port);
|
|
-
|
|
- //
|
|
- // Initialize LDAP connection...
|
|
- //
|
|
-
|
|
- if (!ldap_ssl)
|
|
- {
|
|
- if ((TempBrowseLDAPHandle = ldap_init(ldap_host, ldap_port)) == NULL)
|
|
- rc = LDAP_OPERATIONS_ERROR;
|
|
- else
|
|
- rc = LDAP_SUCCESS;
|
|
-
|
|
-# ifdef HAVE_LDAP_SSL
|
|
- }
|
|
- else
|
|
- {
|
|
- //
|
|
- // Initialize SSL LDAP connection...
|
|
- //
|
|
-
|
|
- if (BrowseLDAPCACertFile)
|
|
- {
|
|
- rc = ldapssl_client_init(BrowseLDAPCACertFile, (void *)NULL);
|
|
- if (rc != LDAP_SUCCESS)
|
|
- {
|
|
- debug_printf("Failed to initialize LDAP SSL client!\n");
|
|
- rc = LDAP_OPERATIONS_ERROR;
|
|
- }
|
|
- else
|
|
- {
|
|
- if ((TempBrowseLDAPHandle = ldapssl_init(ldap_host, ldap_port,
|
|
- 1)) == NULL)
|
|
- rc = LDAP_OPERATIONS_ERROR;
|
|
- else
|
|
- rc = LDAP_SUCCESS;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- debug_printf("LDAP SSL certificate file/database not configured!\n");
|
|
- rc = LDAP_OPERATIONS_ERROR;
|
|
- }
|
|
-
|
|
-# else // HAVE_LDAP_SSL
|
|
-
|
|
- //
|
|
- // Return error, because client libraries doesn't support SSL
|
|
- //
|
|
-
|
|
- debug_printf("LDAP client libraries do not support SSL\n");
|
|
- rc = LDAP_OPERATIONS_ERROR;
|
|
-
|
|
-# endif // HAVE_LDAP_SSL
|
|
- }
|
|
-# endif // HAVE_OPENLDAP
|
|
-
|
|
- //
|
|
- // Check return code from LDAP initialize...
|
|
- //
|
|
-
|
|
- if (rc != LDAP_SUCCESS)
|
|
- {
|
|
- debug_printf("Unable to initialize LDAP!\n");
|
|
-
|
|
- if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
|
|
- debug_printf("Temporarily disabling LDAP browsing...\n");
|
|
- else
|
|
- {
|
|
- debug_printf("Disabling LDAP browsing!\n");
|
|
-
|
|
- //BrowseLocalProtocols &= ~BROWSE_LDAP;
|
|
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
|
|
- }
|
|
-
|
|
- ldap_disconnect(TempBrowseLDAPHandle);
|
|
-
|
|
- return (NULL);
|
|
- }
|
|
-
|
|
- //
|
|
- // Upgrade LDAP version...
|
|
- //
|
|
-
|
|
- if (ldap_set_option(TempBrowseLDAPHandle, LDAP_OPT_PROTOCOL_VERSION,
|
|
- (const void *)&version) != LDAP_SUCCESS)
|
|
- {
|
|
- debug_printf("Unable to set LDAP protocol version %d!\n",
|
|
- version);
|
|
- debug_printf("Disabling LDAP browsing!\n");
|
|
-
|
|
- //BrowseLocalProtocols &= ~BROWSE_LDAP;
|
|
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
|
|
- ldap_disconnect(TempBrowseLDAPHandle);
|
|
-
|
|
- return (NULL);
|
|
- }
|
|
-
|
|
- //
|
|
- // Register LDAP rebind procedure...
|
|
- //
|
|
-
|
|
-# ifdef HAVE_LDAP_REBIND_PROC
|
|
-# if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
|
|
-
|
|
- rc = ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc,
|
|
- (void *)NULL);
|
|
- if (rc != LDAP_SUCCESS)
|
|
- debug_printf("Setting LDAP rebind function failed with status %d: %s\n",
|
|
- rc, ldap_err2string(rc));
|
|
-
|
|
-# else
|
|
-
|
|
- ldap_set_rebind_proc(TempBrowseLDAPHandle, &ldap_rebind_proc, (void *)NULL);
|
|
-
|
|
-# endif // defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
|
|
-# endif // HAVE_LDAP_REBIND_PROC
|
|
-
|
|
- //
|
|
- // Start LDAP bind...
|
|
- //
|
|
-
|
|
-# if LDAP_API_VERSION > 3000
|
|
- struct berval bval;
|
|
- bval.bv_val = BrowseLDAPPassword;
|
|
- bval.bv_len = (BrowseLDAPPassword == NULL) ? 0 : strlen(BrowseLDAPPassword);
|
|
-
|
|
- if (!BrowseLDAPServer || !strcasecmp(BrowseLDAPServer, "localhost"))
|
|
- rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, NULL, "EXTERNAL", &bv, NULL,
|
|
- NULL, NULL);
|
|
- else
|
|
- rc = ldap_sasl_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN,
|
|
- LDAP_SASL_SIMPLE, &bval, NULL, NULL, NULL);
|
|
-
|
|
-# else
|
|
- rc = ldap_bind_s(TempBrowseLDAPHandle, BrowseLDAPBindDN,
|
|
- BrowseLDAPPassword, LDAP_AUTH_SIMPLE);
|
|
-# endif // LDAP_API_VERSION > 3000
|
|
-
|
|
- if (rc != LDAP_SUCCESS)
|
|
- {
|
|
- debug_printf("LDAP bind failed with error %d: %s\n",
|
|
- rc, ldap_err2string(rc));
|
|
-
|
|
-# if defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
|
|
- if (ldap_ssl && (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR))
|
|
- {
|
|
- ssl_err = PORT_GetError();
|
|
- if (ssl_err != 0)
|
|
- debug_printf("LDAP SSL error %d: %s\n", ssl_err,
|
|
- ldapssl_err2string(ssl_err));
|
|
- }
|
|
-# endif // defined(HAVE_LDAP_SSL) && defined (HAVE_MOZILLA_LDAP)
|
|
-
|
|
- ldap_disconnect(TempBrowseLDAPHandle);
|
|
-
|
|
- return (NULL);
|
|
- }
|
|
-
|
|
- debug_printf("LDAP connection established\n");
|
|
-
|
|
- return (TempBrowseLDAPHandle);
|
|
-}
|
|
-
|
|
-
|
|
-//
|
|
-// 'ldap_reconnect()' - Reconnect to LDAP Server
|
|
-//
|
|
-
|
|
-static LDAP * // O - New LDAP handle
|
|
-ldap_reconnect(void)
|
|
-{
|
|
- LDAP *TempBrowseLDAPHandle = NULL; // Temp Handle to LDAP server
|
|
-
|
|
- //
|
|
- // Get a new LDAP Handle and replace the global Handle
|
|
- // if the new connection was successful.
|
|
- //
|
|
-
|
|
- debug_printf("Try LDAP reconnect...\n");
|
|
-
|
|
- TempBrowseLDAPHandle = ldap_new_connection();
|
|
-
|
|
- if (TempBrowseLDAPHandle != NULL)
|
|
- {
|
|
- if (BrowseLDAPHandle != NULL)
|
|
- ldap_disconnect(BrowseLDAPHandle);
|
|
-
|
|
- BrowseLDAPHandle = TempBrowseLDAPHandle;
|
|
- }
|
|
-
|
|
- return (BrowseLDAPHandle);
|
|
-}
|
|
-
|
|
-
|
|
-//
|
|
-// 'ldap_disconnect()' - Disconnect from LDAP Server
|
|
-//
|
|
-
|
|
-static void
|
|
-ldap_disconnect(LDAP *ld) // I - LDAP handle
|
|
-{
|
|
- int rc; // Return code
|
|
-
|
|
- //
|
|
- // Close LDAP handle...
|
|
- //
|
|
-
|
|
-# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
|
|
- rc = ldap_unbind_ext_s(ld, NULL, NULL);
|
|
-# else
|
|
- rc = ldap_unbind_s(ld);
|
|
-# endif // defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
|
|
-
|
|
- if (rc != LDAP_SUCCESS)
|
|
- debug_printf("Unbind from LDAP server failed with status %d: %s\n",
|
|
- rc, ldap_err2string(rc));
|
|
-}
|
|
-
|
|
-
|
|
-//
|
|
-// 'cupsdUpdateLDAPBrowse()' - Scan for new printers via LDAP...
|
|
-//
|
|
-
|
|
-static void
|
|
-cupsdUpdateLDAPBrowse(void)
|
|
-{
|
|
- char uri[HTTP_MAX_URI], // Printer URI
|
|
- host[HTTP_MAX_URI], // Hostname
|
|
- resource[HTTP_MAX_URI], // Resource path
|
|
- local_resource[HTTP_MAX_URI], // Resource path
|
|
- service_name[4096],
|
|
- location[1024], // Printer location
|
|
- info[1024], // Printer information
|
|
- make_model[1024], // Printer make and model
|
|
- type_num[30], // Printer type number
|
|
- scheme[32], // URI's scheme
|
|
- username[64]; // URI's username
|
|
- int port; // URI's port number
|
|
- char *c;
|
|
- int hl;
|
|
- int rc; // LDAP status
|
|
- int limit; // Size limit
|
|
- LDAPMessage *res, // LDAP search results
|
|
- *e; // Current entry from search
|
|
-
|
|
- debug_printf("UpdateLDAPBrowse\n");
|
|
-
|
|
- //
|
|
- // Reconnect if LDAP Handle is invalid...
|
|
- //
|
|
-
|
|
- if (! BrowseLDAPHandle)
|
|
- {
|
|
- ldap_reconnect();
|
|
- return;
|
|
- }
|
|
-
|
|
- //
|
|
- // Search for cups printers in LDAP directory...
|
|
- //
|
|
-
|
|
- rc = ldap_search_rec(BrowseLDAPHandle, BrowseLDAPDN, LDAP_SCOPE_SUBTREE,
|
|
- BrowseLDAPFilter, (char **)ldap_attrs, 0, &res);
|
|
-
|
|
- //
|
|
- // If ldap search was successfull then exit function
|
|
- // and temporary disable LDAP updates...
|
|
- //
|
|
-
|
|
- if (rc != LDAP_SUCCESS)
|
|
- {
|
|
- if (BrowseLDAPUpdate && ((rc == LDAP_SERVER_DOWN) ||
|
|
- (rc == LDAP_CONNECT_ERROR)))
|
|
- {
|
|
- BrowseLDAPUpdate = FALSE;
|
|
- debug_printf("LDAP update temporary disabled\n");
|
|
- }
|
|
- return;
|
|
- }
|
|
-
|
|
- //
|
|
- // If LDAP updates were disabled, we will reenable them...
|
|
- //
|
|
-
|
|
- if (!BrowseLDAPUpdate)
|
|
- {
|
|
- BrowseLDAPUpdate = TRUE;
|
|
- debug_printf("LDAP update enabled\n");
|
|
- }
|
|
-
|
|
- //
|
|
- // Count LDAP entries and return if no entry exist...
|
|
- //
|
|
-
|
|
- limit = ldap_count_entries(BrowseLDAPHandle, res);
|
|
- debug_printf("LDAP search returned %d entries\n", limit);
|
|
- if (limit < 1)
|
|
- {
|
|
- ldap_freeres(res);
|
|
- return;
|
|
- }
|
|
-
|
|
- //
|
|
- // Loop through the available printers...
|
|
- //
|
|
-
|
|
- for (e = ldap_first_entry(BrowseLDAPHandle, res);
|
|
- e;
|
|
- e = ldap_next_entry(BrowseLDAPHandle, e))
|
|
- {
|
|
- //
|
|
- // Get the required values from this entry...
|
|
- //
|
|
-
|
|
- if (ldap_getval_firststring(BrowseLDAPHandle, e,
|
|
- "printerDescription", info, sizeof(info)) == -1)
|
|
- continue;
|
|
-
|
|
- if (ldap_getval_firststring(BrowseLDAPHandle, e,
|
|
- "printerLocation", location,
|
|
- sizeof(location)) == -1)
|
|
- continue;
|
|
-
|
|
- if (ldap_getval_firststring(BrowseLDAPHandle, e,
|
|
- "printerMakeAndModel", make_model,
|
|
- sizeof(make_model)) == -1)
|
|
- continue;
|
|
-
|
|
- if (ldap_getval_firststring(BrowseLDAPHandle, e,
|
|
- "printerType", type_num,
|
|
- sizeof(type_num)) == -1)
|
|
- continue;
|
|
-
|
|
- if (ldap_getval_firststring(BrowseLDAPHandle, e,
|
|
- "printerURI", uri, sizeof(uri)) == -1)
|
|
- continue;
|
|
-
|
|
- //
|
|
- // Process the entry...
|
|
- //
|
|
-
|
|
- memset(scheme, 0, sizeof(scheme));
|
|
- memset(username, 0, sizeof(username));
|
|
- memset(host, 0, sizeof(host));
|
|
- memset(resource, 0, sizeof(resource));
|
|
- memset(local_resource, 0, sizeof(local_resource));
|
|
-
|
|
- httpSeparateURI (HTTP_URI_CODING_ALL, uri,
|
|
- scheme, sizeof(scheme) - 1,
|
|
- username, sizeof(username) - 1,
|
|
- host, sizeof(host) - 1,
|
|
- &port,
|
|
- resource, sizeof(resource)- 1);
|
|
-
|
|
- if (strncasecmp (resource, "/printers/", 10) &&
|
|
- strncasecmp (resource, "/classes/", 9))
|
|
- {
|
|
- debug_printf("don't understand URI: %s\n", uri);
|
|
- return;
|
|
- }
|
|
-
|
|
- strncpy (local_resource, resource + 1, sizeof (local_resource) - 1);
|
|
- local_resource[sizeof (local_resource) - 1] = '\0';
|
|
- c = strchr (local_resource, '?');
|
|
- if (c)
|
|
- *c = '\0';
|
|
-
|
|
- // Build the DNS-SD service name which CUPS would give to this printer
|
|
- // when DNS-SD-broadcasting it
|
|
- snprintf(service_name, sizeof (service_name), "%s @ %s",
|
|
- (strlen(info) > 0 ? info : strchr(local_resource, '/') + 1), host);
|
|
- // Cut off trailing ".local" of host name
|
|
- hl = strlen(service_name);
|
|
- if (hl > 6 && !strcasecmp(service_name + hl - 6, ".local"))
|
|
- service_name[hl - 6] = '\0';
|
|
- if (hl > 7 && !strcasecmp(service_name + hl - 7, ".local."))
|
|
- service_name[hl - 7] = '\0';
|
|
- // DNS-SD service name has max. 63 characters
|
|
- service_name[63] = '\0';
|
|
-
|
|
- debug_printf("LDAP: Remote host: %s; Port: %d; Remote queue name: %s; Service Name: %s\n",
|
|
- host, port, strchr(local_resource, '/') + 1, service_name);
|
|
-
|
|
- pthread_rwlock_wrlock(&lock);
|
|
- examine_discovered_printer_record(host, NULL, port, local_resource,
|
|
- service_name, location, info, "", "",
|
|
- "", 0, NULL);
|
|
- pthread_rwlock_unlock(&lock);
|
|
-
|
|
- }
|
|
-
|
|
- ldap_freeres(res);
|
|
-}
|
|
-
|
|
-
|
|
-//
|
|
-// 'ldap_search_rec()' - LDAP Search with reconnect
|
|
-//
|
|
-
|
|
-static int // O - Return code
|
|
-ldap_search_rec(LDAP *ld, // I - LDAP handler
|
|
- char *base, // I - Base dn
|
|
- int scope, // I - LDAP search scope
|
|
- char *filter, // I - Filter string
|
|
- char *attrs[], // I - Requested attributes
|
|
- int attrsonly, // I - Return only attributes?
|
|
- LDAPMessage **res) // I - LDAP handler
|
|
-{
|
|
- int rc; // Return code
|
|
- LDAP *ldr; // LDAP handler after reconnect
|
|
-
|
|
-
|
|
-# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
|
|
- rc = ldap_search_ext_s(ld, base, scope, filter, attrs, attrsonly, NULL, NULL,
|
|
- NULL, LDAP_NO_LIMIT, res);
|
|
-# else
|
|
- rc = ldap_search_s(ld, base, scope, filter, attrs, attrsonly, res);
|
|
-# endif // defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
|
|
-
|
|
- //
|
|
- // If we have a connection problem try again...
|
|
- //
|
|
-
|
|
- if (rc == LDAP_SERVER_DOWN || rc == LDAP_CONNECT_ERROR)
|
|
- {
|
|
- debug_printf("LDAP search failed with status %d: %s\n",
|
|
- rc, ldap_err2string(rc));
|
|
- debug_printf("We try the LDAP search once again after reconnecting to "
|
|
- "the server\n");
|
|
- ldap_freeres(*res);
|
|
- ldr = ldap_reconnect();
|
|
-
|
|
-# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
|
|
- rc = ldap_search_ext_s(ldr, base, scope, filter, attrs, attrsonly, NULL,
|
|
- NULL, NULL, LDAP_NO_LIMIT, res);
|
|
-# else
|
|
- rc = ldap_search_s(ldr, base, scope, filter, attrs, attrsonly, res);
|
|
-# endif // defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
|
|
- }
|
|
-
|
|
- if (rc == LDAP_NO_SUCH_OBJECT)
|
|
- debug_printf("ldap_search_rec: LDAP entry/object not found\n");
|
|
- else if (rc != LDAP_SUCCESS)
|
|
- debug_printf("ldap_search_rec: LDAP search failed with status %d: %s\n",
|
|
- rc, ldap_err2string(rc));
|
|
-
|
|
- if (rc != LDAP_SUCCESS)
|
|
- ldap_freeres(*res);
|
|
-
|
|
- return (rc);
|
|
-}
|
|
-
|
|
-
|
|
-//
|
|
-// 'ldap_freeres()' - Free LDAPMessage
|
|
-//
|
|
+ }
|
|
|
|
-static void
|
|
-ldap_freeres(LDAPMessage *entry) // I - LDAP handler
|
|
-{
|
|
- int rc; // Return value
|
|
+ cupsFreeDests (num_dests, dests);
|
|
|
|
- rc = ldap_msgfree(entry);
|
|
- if (rc == -1)
|
|
- debug_printf("Can't free LDAPMessage!\n");
|
|
- else if (rc == 0)
|
|
- debug_printf("Freeing LDAPMessage was unnecessary\n");
|
|
+ pthread_rwlock_unlock(&lock);
|
|
}
|
|
|
|
|
|
-//
|
|
-// 'ldap_getval_char()' - Get first LDAP value and convert to string
|
|
-//
|
|
-
|
|
-static int // O - Return code
|
|
-ldap_getval_firststring(LDAP *ld, // I - LDAP handler
|
|
- LDAPMessage *entry, // I - LDAP message or search
|
|
- // result
|
|
- char *attr, // I - the wanted attribute
|
|
- char *retval, // O - String to return
|
|
- unsigned long maxsize) // I - Max string size
|
|
+static void
|
|
+update_local_printers (void)
|
|
{
|
|
- char *dn; // LDAP DN
|
|
- int rc = 0; // Return code
|
|
-# if defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
|
|
- struct berval **bval; // LDAP value array
|
|
- unsigned long size; // String size
|
|
-
|
|
+ gboolean get_printers = FALSE;
|
|
+ http_t *conn;
|
|
|
|
- //
|
|
- // Get value from LDAPMessage...
|
|
- //
|
|
+ if (inhibit_local_printers_update)
|
|
+ return;
|
|
|
|
- if ((bval = ldap_get_values_len(ld, entry, attr)) == NULL)
|
|
- {
|
|
- rc = -1;
|
|
- dn = ldap_get_dn(ld, entry);
|
|
- debug_printf("Failed to get LDAP value %s for %s!\n",
|
|
- attr, dn);
|
|
- ldap_memfree(dn);
|
|
- }
|
|
- else
|
|
+ conn = http_connect_local ();
|
|
+ if (conn &&
|
|
+ (!local_printers_context || local_printers_context->can_subscribe))
|
|
{
|
|
- //
|
|
- // Check size and copy value into our string...
|
|
- //
|
|
-
|
|
- size = maxsize;
|
|
- if (size < (bval[0]->bv_len + 1))
|
|
+ if (!local_printers_context ||
|
|
+ local_printers_context->subscription_id == -1)
|
|
{
|
|
- rc = -1;
|
|
- dn = ldap_get_dn(ld, entry);
|
|
- debug_printf("Attribute %s is too big! (dn: %s)\n",
|
|
- attr, dn);
|
|
- ldap_memfree(dn);
|
|
+ // No subscription yet. First, create the subscription.
|
|
+ local_printers_create_subscription (conn);
|
|
+ get_printers = TRUE;
|
|
}
|
|
else
|
|
- size = bval[0]->bv_len + 1;
|
|
+ // We already have a subscription, so use it.
|
|
|
|
- strncpy(retval, bval[0]->bv_val, size);
|
|
- if (size > 0)
|
|
- retval[size - 1] = '\0';
|
|
- ldap_value_free_len(bval);
|
|
+ // Note: for the moment, browse_poll_get_notifications() just
|
|
+ // tells us whether we should re-fetch the printer list, so it
|
|
+ // is safe to use here.
|
|
+ get_printers = browse_poll_get_notifications (local_printers_context,
|
|
+ conn);
|
|
}
|
|
-# else
|
|
- char **value; // LDAP value
|
|
+ else
|
|
+ get_printers = TRUE;
|
|
|
|
- //
|
|
- // Get value from LDAPMessage...
|
|
- //
|
|
+ if (get_printers)
|
|
+ get_local_printers ();
|
|
+}
|
|
+
|
|
+
|
|
+static int
|
|
+check_jobs ()
|
|
+{
|
|
+ int num_jobs = 0;
|
|
+ cups_job_t *jobs = NULL;
|
|
+ remote_printer_t *p;
|
|
+ http_t *conn = NULL;
|
|
|
|
- if ((value = (char **)ldap_get_values(ld, entry, attr)) == NULL)
|
|
+ conn = http_connect_local ();
|
|
+ if (conn == NULL)
|
|
{
|
|
- rc = -1;
|
|
- dn = ldap_get_dn(ld, entry);
|
|
- debug_printf("Failed to get LDAP value %s for %s!\n",
|
|
- attr, dn);
|
|
- ldap_memfree(dn);
|
|
+ debug_printf("Cannot connect to local CUPS to check whether there are still jobs.\n");
|
|
+ return (0);
|
|
}
|
|
- else
|
|
+
|
|
+ if (cupsArrayCount(remote_printers) > 0)
|
|
+ for (p = (remote_printer_t *)cupsArrayFirst(remote_printers);
|
|
+ p;
|
|
+ p = (remote_printer_t *)cupsArrayNext(remote_printers))
|
|
+ if (!p->slave_of)
|
|
+ {
|
|
+ num_jobs = cupsGetJobs2(conn, &jobs, p->queue_name, 0,
|
|
+ CUPS_WHICHJOBS_ACTIVE);
|
|
+ if (num_jobs > 0)
|
|
+ {
|
|
+ debug_printf("Queue %s still has jobs!\n", p->queue_name);
|
|
+ cupsFreeJobs(num_jobs, jobs);
|
|
+ return (1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ debug_printf("All our remote printers are without jobs.\n");
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+
|
|
+static gboolean
|
|
+autoshutdown_execute (gpointer data)
|
|
+{
|
|
+ debug_printf("autoshutdown_execute() in THREAD %ld\n", pthread_self());
|
|
+ // Are we still in auto shutdown mode and are we still without queues or
|
|
+ // jobs
|
|
+ if (autoshutdown &&
|
|
+ (cupsArrayCount(remote_printers) == 0 ||
|
|
+ (autoshutdown_on == NO_JOBS && check_jobs() == 0)))
|
|
{
|
|
- strncpy(retval, *value, maxsize);
|
|
- if (maxsize > 0)
|
|
- retval[maxsize - 1] = '\0';
|
|
- ldap_value_free(value);
|
|
+ debug_printf("Automatic shutdown as there are no print queues maintained by us or no jobs on them for %d sec.\n",
|
|
+ autoshutdown_timeout);
|
|
+ g_main_loop_quit(gmainloop);
|
|
+ g_main_context_wakeup(NULL);
|
|
}
|
|
-# endif // defined(HAVE_OPENLDAP) && LDAP_API_VERSION > 3000
|
|
|
|
- return (rc);
|
|
+ // Stop this timeout handler, we needed it only once
|
|
+ return (FALSE);
|
|
}
|
|
-#endif // HAVE_LDAP
|
|
|
|
|
|
static int
|
|
@@ -6214,7 +5140,7 @@ get_local_queue_name(const char *service_name,
|
|
/* We can get resource without / or without string after / - use
|
|
* the original string (possible trailing / will be removed) */
|
|
if ((str = strrchr(resource, '/')) == NULL || strlen(str) <= 1)
|
|
- str = resource;
|
|
+ str = (char *)resource;
|
|
|
|
queue_name = remove_bad_chars(str, 0);
|
|
}
|
|
@@ -9610,8 +8536,7 @@ update_cups_queues(gpointer unused)
|
|
// DNS-SD has reported a new remote printer, create a CUPS queue
|
|
// for it, or upgrade an existing queue, or update a queue to
|
|
// use a backup host when it has disappeared on the currently
|
|
- // used host (...or, we've just received a CUPS Browsing packet
|
|
- // for this queue)
|
|
+ // used host (...or, we've just discovered this queue via BrowsePoll)
|
|
case STATUS_TO_BE_CREATED:
|
|
if (p->called)
|
|
break;
|
|
@@ -10134,7 +9059,7 @@ update_netifs (gpointer data)
|
|
if (strlen(list) + strlen(iface->address) + 2 <= sizeof(list))
|
|
{
|
|
snprintf(l, sizeof(list) - strlen(list) - 1,
|
|
- "%s*", iface->address);
|
|
+ "%.65533s*", iface->address);
|
|
l = list + strlen(list);
|
|
}
|
|
}
|
|
@@ -10318,7 +9243,7 @@ examine_discovered_printer_record(const char *host,
|
|
is_cups_queue = 1;
|
|
#endif // HAVE_AVAHI
|
|
// If we do not have a TXT record the printer was not discovered via
|
|
- // DNS-SD but via CUPS legacy or LDAP, so it is a remote CUPS queue
|
|
+ // DNS-SD and so it is a (BrowsePoll-discovered) remote CUPS queue
|
|
// and not an IPP network printer.
|
|
if (txt == NULL)
|
|
is_cups_queue = 1;
|
|
@@ -10441,8 +9366,8 @@ examine_discovered_printer_record(const char *host,
|
|
}
|
|
else
|
|
#endif // HAVE_AVAHI
|
|
- // Printer is discovered via legacy CUPS or LDAP, so we have to give
|
|
- // a IP-based/host-name-based URI to it ( or for DNS-SD-discovered
|
|
+ // Printer is discovered via BrowsePoll, so we have to give a
|
|
+ // IP-based/host-name-based URI to it (or for DNS-SD-discovered
|
|
// printers if DNSSDBasedDeviceURIs config option is not set)
|
|
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri) - 1,
|
|
(strcasestr(type, "_ipps") ? "ipps" : "ipp"), NULL,
|
|
@@ -10465,8 +9390,8 @@ examine_discovered_printer_record(const char *host,
|
|
}
|
|
|
|
|
|
- // Update network interface info if we were discovered by LDAP
|
|
- // or legacy CUPS, needed for the is_local_hostname() function calls.
|
|
+ // Update network interface info if we were discovered by
|
|
+ // BrowsePoll, needed for the is_local_hostname() function calls.
|
|
// During DNS-SD discovery the update is already done by the Avahi
|
|
// event handler function.
|
|
if (FrequentNetifUpdate && (type == NULL || type[0] == '\0'))
|
|
@@ -10527,9 +9452,9 @@ examine_discovered_printer_record(const char *host,
|
|
// We have already created a local queue, check whether the
|
|
// discovered service allows us to upgrade the queue to IPPS
|
|
// or whether the URI part after ipp(s):// has changed, or
|
|
- // whether the discovered queue is discovered via DNS-SD
|
|
- // having more info in contrary to the existing being
|
|
- // discovered by legacy CUPS or LDAP
|
|
+ // whether the discovered queue is discovered via DNS-SD,
|
|
+ // having more info in contrary to the existing one being
|
|
+ // discovered by BrowsePoll
|
|
|
|
int downgrade = 0, upgrade = 0;
|
|
|
|
@@ -10568,14 +9493,14 @@ examine_discovered_printer_record(const char *host,
|
|
debug_printf("Printer %s: New discovered service from host %s, port %d, URI %s is from a non-loopback interface, we have already one from the loopback interface, skipping\n",
|
|
p->queue_name, remote_host, port, uri);
|
|
}
|
|
- // DNS-SD -> CUPS Legacy/LDAP
|
|
+ // DNS-SD -> BrowsePoll
|
|
else if (p->domain != NULL && p->domain[0] != '\0' &&
|
|
(domain == NULL || domain[0] == '\0') &&
|
|
p->type != NULL && p->type[0] != '\0' &&
|
|
(type == NULL || type[0] == '\0'))
|
|
{
|
|
downgrade = 1;
|
|
- debug_printf("Printer %s: New discovered service from host %s, port %d, URI %s is only discovered via legacy CUPS or LDAP, we have already a DNS-SD-discovered one, skipping\n",
|
|
+ debug_printf("Printer %s: New discovered service from host %s, port %d, URI %s is only discovered via BrowsePoll, we have already a DNS-SD-discovered one, skipping\n",
|
|
p->queue_name, remote_host, port, uri);
|
|
}
|
|
|
|
@@ -10597,11 +9522,11 @@ examine_discovered_printer_record(const char *host,
|
|
debug_printf("Upgrading printer %s (Host: %s, Port: %d) to use loopback interface \"lo\". New URI: %s\n",
|
|
p->queue_name, remote_host, port, uri);
|
|
}
|
|
- // CUPS Legacy/LDAP -> DNS-SD
|
|
+ // BrowsePoll -> DNS-SD
|
|
else if ((p->domain == NULL || p->domain[0] == '\0') &&
|
|
domain != NULL && domain[0] != '\0' &&
|
|
- (p->type == NULL || p->type[0] == '\0') &&
|
|
- type != NULL && type[0] != '\0')
|
|
+ (p->type == NULL || p->type[0] == '\0') &&
|
|
+ type != NULL && type[0] != '\0')
|
|
{
|
|
upgrade = 1;
|
|
debug_printf("Discovered printer %s (Host: %s, Port: %d, URI: %s) by DNS-SD now.\n",
|
|
@@ -11683,7 +10608,7 @@ avahi_init()
|
|
|
|
|
|
//
|
|
-// A CUPS printer has been discovered via CUPS Browsing
|
|
+// A CUPS printer has been discovered via BrowsePoll
|
|
// or with BrowsePoll
|
|
//
|
|
|
|
@@ -11757,7 +10682,7 @@ found_cups_printer(const char *remote_host,
|
|
// DNS-SD service name has max. 63 characters
|
|
service_name[63] = '\0';
|
|
|
|
- debug_printf("CUPS browsing: Remote host: %s; Port: %d; Remote queue name: %s; Service Name: %s\n",
|
|
+ debug_printf("BrowsePoll: Remote host: %s; Port: %d; Remote queue name: %s; Service Name: %s\n",
|
|
host, port, strchr(local_resource, '/') + 1, service_name);
|
|
|
|
pthread_rwlock_wrlock(&lock);
|
|
@@ -11790,203 +10715,6 @@ found_cups_printer(const char *remote_host,
|
|
}
|
|
|
|
|
|
-static gboolean
|
|
-process_browse_data (GIOChannel *source,
|
|
- GIOCondition condition,
|
|
- gpointer data)
|
|
-{
|
|
- char packet[2048];
|
|
- http_addr_t srcaddr;
|
|
- socklen_t srclen;
|
|
- ssize_t got;
|
|
- unsigned int type;
|
|
- unsigned int state;
|
|
- char remote_host[256];
|
|
- char uri[1024];
|
|
- char location[1024];
|
|
- char info[1024];
|
|
- char *c = NULL, *end = NULL;
|
|
-
|
|
- debug_printf("process_browse_data() in THREAD %ld\n", pthread_self());
|
|
-
|
|
- memset(packet, 0, sizeof(packet));
|
|
- memset(remote_host, 0, sizeof(remote_host));
|
|
- memset(uri, 0, sizeof(uri));
|
|
- memset(info, 0, sizeof(info));
|
|
-
|
|
- srclen = sizeof (srcaddr);
|
|
- got = recvfrom (browsesocket, packet, sizeof (packet) - 1, 0,
|
|
- &srcaddr.addr, &srclen);
|
|
- if (got == -1)
|
|
- {
|
|
- debug_printf ("cupsd-browsed: error receiving browse packet: %s\n",
|
|
- strerror (errno));
|
|
- // Remove this I/O source
|
|
- return (FALSE);
|
|
- }
|
|
-
|
|
- packet[got] = '\0';
|
|
- httpAddrString (&srcaddr, remote_host, sizeof (remote_host) - 1);
|
|
-
|
|
- // Check this packet is allowed
|
|
- if (!allowed ((struct sockaddr *) &srcaddr))
|
|
- {
|
|
- debug_printf("browse packet from %s disallowed\n",
|
|
- remote_host);
|
|
- return (TRUE);
|
|
- }
|
|
-
|
|
- debug_printf("browse packet received from %s\n",
|
|
- remote_host);
|
|
-
|
|
- if (sscanf (packet, "%x%x%1023s", &type, &state, uri) < 3)
|
|
- {
|
|
- debug_printf("incorrect browse packet format\n");
|
|
- return (TRUE);
|
|
- }
|
|
-
|
|
- info[0] = '\0';
|
|
-
|
|
- // do not read OOB
|
|
- end = packet + sizeof(packet);
|
|
- c = strchr (packet, '\"');
|
|
- if (c >= end)
|
|
- return (TRUE);
|
|
-
|
|
- if (c)
|
|
- {
|
|
- // Extract location field
|
|
- {
|
|
- int i;
|
|
- c++;
|
|
- for (i = 0;
|
|
- i < sizeof (location) - 1 && *c != '\"' && c < end;
|
|
- i++, c++)
|
|
- location[i] = *c;
|
|
- location[i] = '\0';
|
|
- debug_printf("process_browse_data: location: |%s|\n", location); // !!
|
|
- }
|
|
- for (; c < end && *c != '\"'; c++);
|
|
-
|
|
- if (c >= end)
|
|
- return (TRUE);
|
|
-
|
|
- if (*c == '\"')
|
|
- for (c++; c < end && isspace(*c); c++);
|
|
-
|
|
- if (c >= end)
|
|
- return (TRUE);
|
|
-
|
|
- // Is there an info field?
|
|
- if (*c == '\"')
|
|
- {
|
|
- int i;
|
|
- c++;
|
|
- for (i = 0;
|
|
- i < sizeof (info) - 1 && *c != '\"' && c < end;
|
|
- i++, c++)
|
|
- info[i] = *c;
|
|
- info[i] = '\0';
|
|
- debug_printf("process_browse_data: info: |%s|\n", info); // !!
|
|
- }
|
|
- }
|
|
- if (c >= end)
|
|
- return (TRUE);
|
|
-
|
|
- if (!(type & CUPS_PRINTER_DELETE))
|
|
- found_cups_printer (remote_host, uri, location, info);
|
|
-
|
|
- if (in_shutdown == 0)
|
|
- recheck_timer ();
|
|
-
|
|
- // Don't remove this I/O source
|
|
- return (TRUE);
|
|
-}
|
|
-
|
|
-
|
|
-static void
|
|
-broadcast_browse_packets (gpointer data,
|
|
- gpointer user_data)
|
|
-{
|
|
- browse_data_t *bdata = data;
|
|
- netif_t *browse;
|
|
- char packet[2048];
|
|
- char uri[HTTP_MAX_URI];
|
|
- char scheme[32];
|
|
- char username[64];
|
|
- char host[HTTP_MAX_HOST];
|
|
- int port;
|
|
- char resource[HTTP_MAX_URI];
|
|
-
|
|
- debug_printf("broadcast_browse_packets() in THREAD %ld\n", pthread_self());
|
|
-
|
|
- for (browse = (netif_t *)cupsArrayFirst (netifs);
|
|
- browse != NULL;
|
|
- browse = (netif_t *)cupsArrayNext (netifs))
|
|
- {
|
|
- // Replace 'localhost' with our IP address on this interface
|
|
- httpSeparateURI(HTTP_URI_CODING_ALL, bdata->uri,
|
|
- scheme, sizeof(scheme),
|
|
- username, sizeof(username),
|
|
- host, sizeof(host),
|
|
- &port,
|
|
- resource, sizeof(resource));
|
|
- httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof (uri),
|
|
- scheme, username, browse->address, port, resource);
|
|
-
|
|
- if (snprintf (packet, sizeof (packet),
|
|
- "%x " // type
|
|
- "%x " // state
|
|
- "%s " // uri
|
|
- "\"%s\" " // location
|
|
- "\"%s\" " // info
|
|
- "\"%s\" " // make-and-model
|
|
- "lease-duration=%d" // BrowseTimeout
|
|
- "%s%s" // other browse options
|
|
- "\n",
|
|
- bdata->type,
|
|
- bdata->state,
|
|
- uri,
|
|
- bdata->location,
|
|
- bdata->info,
|
|
- bdata->make_model,
|
|
- BrowseTimeout,
|
|
- bdata->browse_options ? " " : "",
|
|
- bdata->browse_options ? bdata->browse_options : "")
|
|
- >= sizeof (packet))
|
|
- {
|
|
- debug_printf ("oversize packet not sent\n");
|
|
- continue;
|
|
- }
|
|
-
|
|
- debug_printf("packet to send:\n%s", packet);
|
|
-
|
|
- int err = sendto (browsesocket, packet,
|
|
- strlen (packet), 0,
|
|
- &browse->broadcast.addr,
|
|
- httpAddrLength (&browse->broadcast));
|
|
- if (err == -1)
|
|
- debug_printf("cupsd-browsed: sendto returned %d: %s\n",
|
|
- err, strerror (errno));
|
|
- }
|
|
-}
|
|
-
|
|
-
|
|
-static gboolean
|
|
-send_browse_data (gpointer data)
|
|
-{
|
|
- debug_printf("send_browse_data() in THREAD %ld\n", pthread_self());
|
|
- update_netifs (NULL);
|
|
- res_init ();
|
|
- update_local_printers ();
|
|
- g_list_foreach (browse_data, broadcast_browse_packets, NULL);
|
|
- g_timeout_add_seconds (BrowseInterval, send_browse_data, NULL);
|
|
-
|
|
- // Stop this timeout handler, we called a new one
|
|
- return (FALSE);
|
|
-}
|
|
-
|
|
-
|
|
static browsepoll_printer_t *
|
|
new_browsepoll_printer (const char *uri_supported,
|
|
const char *location,
|
|
@@ -12410,81 +11138,6 @@ browse_poll (gpointer data)
|
|
}
|
|
|
|
|
|
-#ifdef HAVE_LDAP
|
|
-static gboolean
|
|
-browse_ldap_poll (gpointer data)
|
|
-{
|
|
- char *tmpFilter; // Query filter
|
|
- int filterLen;
|
|
-
|
|
- debug_printf("browse_ldap_poll() in THREAD %ld\n", pthread_self());
|
|
-
|
|
- // do real stuff here
|
|
- if (!BrowseLDAPDN)
|
|
- {
|
|
- debug_printf("Need to set BrowseLDAPDN to use LDAP browsing!\n");
|
|
- BrowseLocalProtocols &= ~BROWSE_LDAP;
|
|
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
|
|
-
|
|
- return (FALSE);
|
|
- }
|
|
- else
|
|
- {
|
|
- if (!BrowseLDAPInitialised)
|
|
- {
|
|
- BrowseLDAPInitialised = TRUE;
|
|
- //
|
|
- // Query filter string
|
|
- //
|
|
-
|
|
- if (BrowseLDAPFilter)
|
|
- filterLen = snprintf(NULL, 0, "(&%s%s)", LDAP_BROWSE_FILTER,
|
|
- BrowseLDAPFilter);
|
|
- else
|
|
- filterLen = strlen(LDAP_BROWSE_FILTER);
|
|
-
|
|
- tmpFilter = (char *)malloc(filterLen + 1);
|
|
- if (!tmpFilter)
|
|
- {
|
|
- debug_printf("Could not allocate memory for LDAP browse query filter!\n");
|
|
- BrowseLocalProtocols &= ~BROWSE_LDAP;
|
|
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
|
|
- return (FALSE);
|
|
- }
|
|
-
|
|
- if (BrowseLDAPFilter)
|
|
- {
|
|
- snprintf(tmpFilter, filterLen + 1, "(&%s%s)", LDAP_BROWSE_FILTER,
|
|
- BrowseLDAPFilter);
|
|
- free(BrowseLDAPFilter);
|
|
- BrowseLDAPFilter = NULL;
|
|
- }
|
|
- else
|
|
- strcpy(tmpFilter, LDAP_BROWSE_FILTER);
|
|
-
|
|
- BrowseLDAPFilter = tmpFilter;
|
|
-
|
|
- //
|
|
- // Open LDAP handle...
|
|
- //
|
|
-
|
|
- BrowseLDAPHandle = ldap_new_connection();
|
|
- }
|
|
-
|
|
- cupsdUpdateLDAPBrowse();
|
|
- if (in_shutdown == 0)
|
|
- recheck_timer();
|
|
- }
|
|
-
|
|
- // Call a new timeout handler so that we run again
|
|
- g_timeout_add_seconds (BrowseInterval, browse_ldap_poll, data);
|
|
-
|
|
- // Stop this timeout handler, we called a new one
|
|
- return (FALSE);
|
|
-}
|
|
-#endif // HAVE_LDAP
|
|
-
|
|
-
|
|
static void
|
|
sigterm_handler(int sig)
|
|
{
|
|
@@ -12728,10 +11381,6 @@ read_configuration (const char *filename)
|
|
{
|
|
if (!strcasecmp(p, "dnssd"))
|
|
protocols |= BROWSE_DNSSD;
|
|
- else if (!strcasecmp(p, "cups"))
|
|
- protocols |= BROWSE_CUPS;
|
|
- else if (!strcasecmp(p, "ldap"))
|
|
- protocols |= BROWSE_LDAP;
|
|
else if (strcasecmp(p, "none"))
|
|
debug_printf("Unknown protocol '%s'\n", p);
|
|
|
|
@@ -13402,40 +12051,6 @@ read_configuration (const char *filename)
|
|
debug_printf("Invalid value for pause between calls of update_cups_queues(): %d\n",
|
|
t);
|
|
}
|
|
-#ifdef HAVE_LDAP
|
|
- else if (!strcasecmp(line, "BrowseLDAPBindDN") && value)
|
|
- {
|
|
- if (value[0] != '\0')
|
|
- BrowseLDAPBindDN = strdup(value);
|
|
- }
|
|
-# ifdef HAVE_LDAP_SSL
|
|
- else if (!strcasecmp(line, "BrowseLDAPCACertFile") && value)
|
|
- {
|
|
- if (value[0] != '\0')
|
|
- BrowseLDAPCACertFile = strdup(value);
|
|
- }
|
|
-# endif // HAVE_LDAP_SSL
|
|
- else if (!strcasecmp(line, "BrowseLDAPDN") && value)
|
|
- {
|
|
- if (value[0] != '\0')
|
|
- BrowseLDAPDN = strdup(value);
|
|
- }
|
|
- else if (!strcasecmp(line, "BrowseLDAPPassword") && value)
|
|
- {
|
|
- if (value[0] != '\0')
|
|
- BrowseLDAPPassword = strdup(value);
|
|
- }
|
|
- else if (!strcasecmp(line, "BrowseLDAPServer") && value)
|
|
- {
|
|
- if (value[0] != '\0')
|
|
- BrowseLDAPServer = strdup(value);
|
|
- }
|
|
- else if (!strcasecmp(line, "BrowseLDAPFilter") && value)
|
|
- {
|
|
- if (value[0] != '\0')
|
|
- BrowseLDAPFilter = strdup(value);
|
|
- }
|
|
-#endif // HAVE_LDAP
|
|
}
|
|
|
|
if (browse_line_found == 0)
|
|
@@ -13526,10 +12141,7 @@ find_previous_queue (gpointer key,
|
|
// in a certain time frame, we will remove the queue
|
|
p->status = STATUS_UNCONFIRMED;
|
|
|
|
- if (BrowseRemoteProtocols & BROWSE_CUPS)
|
|
- p->timeout = time(NULL) + BrowseInterval * 3 / 2;
|
|
- else
|
|
- p->timeout = time(NULL) + TIMEOUT_CONFIRM;
|
|
+ p->timeout = time(NULL) + TIMEOUT_CONFIRM;
|
|
|
|
p->slave_of = NULL;
|
|
debug_printf("Found CUPS queue %s (URI: %s) from previous session.\n",
|
|
@@ -13864,12 +12476,6 @@ main(int argc, char*argv[])
|
|
BrowseLocalProtocols &= ~BROWSE_DNSSD;
|
|
}
|
|
|
|
- if (BrowseLocalProtocols & BROWSE_LDAP)
|
|
- {
|
|
- debug_printf("Local support for LDAP not implemented\n");
|
|
- BrowseLocalProtocols &= ~BROWSE_LDAP;
|
|
- }
|
|
-
|
|
#ifndef HAVE_AVAHI
|
|
if (BrowseRemoteProtocols & BROWSE_DNSSD)
|
|
{
|
|
@@ -13878,14 +12484,6 @@ main(int argc, char*argv[])
|
|
}
|
|
#endif // HAVE_AVAHI
|
|
|
|
-#ifndef HAVE_LDAP
|
|
- if (BrowseRemoteProtocols & BROWSE_LDAP)
|
|
- {
|
|
- debug_printf("Remote support for LDAP not supported\n");
|
|
- BrowseRemoteProtocols &= ~BROWSE_LDAP;
|
|
- }
|
|
-#endif // HAVE_LDAP
|
|
-
|
|
// Wait for CUPS daemon to start
|
|
while ((http = http_connect_local ()) == NULL)
|
|
sleep(1);
|
|
@@ -13974,50 +12572,6 @@ main(int argc, char*argv[])
|
|
}
|
|
}
|
|
|
|
- if (BrowseLocalProtocols & BROWSE_CUPS ||
|
|
- BrowseRemoteProtocols & BROWSE_CUPS)
|
|
- {
|
|
- // Set up our CUPS Browsing socket
|
|
- browsesocket = socket (AF_INET, SOCK_DGRAM, 0);
|
|
- if (browsesocket == -1)
|
|
- {
|
|
- debug_printf("failed to create CUPS Browsing socket: %s\n",
|
|
- strerror (errno));
|
|
- }
|
|
- else
|
|
- {
|
|
- struct sockaddr_in addr;
|
|
- memset (&addr, 0, sizeof (addr));
|
|
- addr.sin_addr.s_addr = htonl (INADDR_ANY);
|
|
- addr.sin_family = AF_INET;
|
|
- addr.sin_port = htons (BrowsePort);
|
|
- if (bind (browsesocket, (struct sockaddr *)&addr, sizeof (addr)))
|
|
- {
|
|
- debug_printf("failed to bind CUPS Browsing socket: %s\n",
|
|
- strerror (errno));
|
|
- close (browsesocket);
|
|
- browsesocket = -1;
|
|
- }
|
|
- else
|
|
- {
|
|
- int on = 1;
|
|
- if (setsockopt (browsesocket, SOL_SOCKET, SO_BROADCAST,
|
|
- &on, sizeof (on)))
|
|
- {
|
|
- debug_printf("failed to allow broadcast: %s\n",
|
|
- strerror (errno));
|
|
- BrowseLocalProtocols &= ~BROWSE_CUPS;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- if (browsesocket == -1)
|
|
- {
|
|
- BrowseLocalProtocols &= ~BROWSE_CUPS;
|
|
- BrowseRemoteProtocols &= ~BROWSE_CUPS;
|
|
- }
|
|
- }
|
|
-
|
|
if (BrowseLocalProtocols == 0 &&
|
|
BrowseRemoteProtocols == 0 &&
|
|
!BrowsePoll)
|
|
@@ -14051,29 +12605,6 @@ main(int argc, char*argv[])
|
|
gmainloop = g_main_loop_new (NULL, FALSE);
|
|
recheck_timer ();
|
|
|
|
- if (BrowseRemoteProtocols & BROWSE_CUPS)
|
|
- {
|
|
- GIOChannel *browse_channel = g_io_channel_unix_new (browsesocket);
|
|
- g_io_channel_set_close_on_unref (browse_channel, FALSE);
|
|
- g_io_add_watch (browse_channel, G_IO_IN, process_browse_data, NULL);
|
|
- }
|
|
-
|
|
- if (BrowseLocalProtocols & BROWSE_CUPS)
|
|
- {
|
|
- debug_printf ("will send browse data every %ds\n",
|
|
- BrowseInterval);
|
|
- g_idle_add (send_browse_data, NULL);
|
|
- }
|
|
-
|
|
-#ifdef HAVE_LDAP
|
|
- if (BrowseRemoteProtocols & BROWSE_LDAP)
|
|
- {
|
|
- debug_printf ("will browse poll LDAP every %ds\n",
|
|
- BrowseInterval);
|
|
- g_idle_add (browse_ldap_poll, NULL);
|
|
- }
|
|
-#endif // HAVE_LDAP
|
|
-
|
|
if (BrowsePoll)
|
|
{
|
|
size_t index;
|
|
@@ -14194,24 +12725,12 @@ fail:
|
|
avahi_shutdown();
|
|
#endif // HAVE_AVAHI
|
|
|
|
-#ifdef HAVE_LDAP
|
|
- if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_LDAP) &&
|
|
- BrowseLDAPHandle)
|
|
- {
|
|
- ldap_disconnect(BrowseLDAPHandle);
|
|
- BrowseLDAPHandle = NULL;
|
|
- }
|
|
-#endif // HAVE_LDAP
|
|
-
|
|
if (browsesocket != -1)
|
|
close (browsesocket);
|
|
|
|
g_hash_table_destroy (local_printers);
|
|
g_hash_table_destroy (cups_supported_remote_printers);
|
|
|
|
- if (BrowseLocalProtocols & BROWSE_CUPS)
|
|
- g_list_free_full (browse_data, browse_data_free);
|
|
-
|
|
// Close log file if we have one
|
|
if (debug_logfile == 1)
|
|
stop_debug_logging();
|
|
diff --git a/daemon/cups-browsed.conf.5 b/daemon/cups-browsed.conf.5
|
|
index 83c69d9f..4af67884 100644
|
|
--- a/daemon/cups-browsed.conf.5
|
|
+++ b/daemon/cups-browsed.conf.5
|
|
@@ -47,7 +47,7 @@ journal or syslog. Only if you run cups-browsed from the command line
|
|
|
|
.fam T
|
|
.fi
|
|
-Only browse remote printers (via DNS-SD or CUPS browsing) from
|
|
+Only browse remote printers (via DNS-SD) from
|
|
selected servers using the "BrowseAllow", "BrowseDeny", and
|
|
"BrowseOrder" directives
|
|
.PP
|
|
@@ -330,8 +330,6 @@ Printers from all servers except "prinserver2.local" are accepted:
|
|
The BrowsePoll directive polls a server for available printers once
|
|
every 60 seconds. Multiple BrowsePoll directives can be specified
|
|
to poll multiple servers. The default port to connect to is 631.
|
|
-BrowsePoll works independently of whether CUPS browsing is activated
|
|
-in BrowseRemoteProtocols.
|
|
.PP
|
|
.nf
|
|
.fam C
|
|
@@ -345,12 +343,11 @@ in BrowseRemoteProtocols.
|
|
The BrowseLocalProtocols directive specifies the protocols to use
|
|
when advertising local shared printers on the network. The default
|
|
is "none". Control of advertising of local shared printers using
|
|
-dnssd is done in /etc/cups/cupsd.conf.
|
|
+dnssd is done by CUPS and configured in /etc/cups/cupsd.conf.
|
|
.PP
|
|
.nf
|
|
.fam C
|
|
BrowseLocalProtocols none
|
|
- BrowseLocalProtocols CUPS
|
|
|
|
|
|
.fam T
|
|
@@ -358,50 +355,26 @@ dnssd is done in /etc/cups/cupsd.conf.
|
|
The BrowseRemoteProtocols directive specifies the protocols to use
|
|
when finding remote shared printers on the network. Multiple
|
|
protocols can be specified by separating them with spaces.
|
|
-The default is "dnssd cups".
|
|
+The default is "dnssd".
|
|
.PP
|
|
.nf
|
|
.fam C
|
|
BrowseRemoteProtocols none
|
|
- BrowseRemoteProtocols CUPS dnssd
|
|
- BrowseRemoteProtocols CUPS
|
|
BrowseRemoteProtocols dnssd
|
|
- BrowseRemoteProtocols ldap
|
|
+
|
|
|
|
.fam T
|
|
.fi
|
|
The BrowseProtocols directive specifies the protocols to use when
|
|
finding remote shared printers on the network and advertising local
|
|
-shared printers. "dnssd" and "ldap" are ignored for BrowseLocalProtocols.
|
|
-Multiple protocols can be specified by separating them with spaces. The
|
|
-default is "none" for BrowseLocalProtocols and "dnssd cups" for
|
|
-BrowseRemoteProtocols.
|
|
+shared printers.
|
|
+Multiple protocols can be specified by separating them with spaces.
|
|
.PP
|
|
.nf
|
|
.fam C
|
|
BrowseProtocols none
|
|
- BrowseProtocols CUPS dnssd
|
|
- BrowseProtocols CUPS
|
|
BrowseProtocols dnssd
|
|
- BrowseProtocols ldap
|
|
|
|
-.fam T
|
|
-.fi
|
|
-The configuration for the LDAP browsing mode define where the LDAP search
|
|
-should be performed. If built with an LDAP library that supports TLS, the
|
|
-path to the server's certificate, or to a certificates store, can be
|
|
-specified.
|
|
-The optional filter allows the LDAP search to be more specific, and is used
|
|
-in addition to the hardcoded filter (objectclass=cupsPrinter).
|
|
-.PP
|
|
-.nf
|
|
-.fam C
|
|
- BrowseLDAPBindDN cn=cups-browsed,dc=domain,dc=tld
|
|
- BrowseLDAPCACertFile /path/to/server/certificate.pem
|
|
- BrowseLDAPDN ou=printers,dc=domain,dc=tld
|
|
- BrowseLDAPFilter (printerLocation=/Office 1/*)
|
|
- BrowseLDAPPassword s3cret
|
|
- BrowseLDAPServer ldaps://ldap.domain.tld
|
|
|
|
.fam T
|
|
.fi
|
|
@@ -459,8 +432,6 @@ The BrowseTimeout directive determines the amount of time that
|
|
browsing-related operations are allowed to take in seconds.
|
|
Notably, adding or removing one printer queue is considered as one
|
|
operation. The timeout applies to each one of those operations.
|
|
-Especially queues discovered by CUPS broadcasts will be removed after
|
|
-this timeout if no further broadcast from the server happens.
|
|
.PP
|
|
.nf
|
|
.fam C
|
|
@@ -582,7 +553,7 @@ Set DNSSDBasedDeviceURIs to "No" if cups-browsed should use the
|
|
conventional host-name/IP-based URIs.
|
|
.PP
|
|
Note that this option has only influence on URIs for printers
|
|
-discovered via DNS-SD, not via legacy CUPS broewsing or LDAP.
|
|
+discovered via DNS-SD, not via BrowsePoll.
|
|
Those printers get always assigned the conventional URIs.
|
|
.PP
|
|
.nf
|
|
diff --git a/daemon/cups-browsed.conf.in b/daemon/cups-browsed.conf.in
|
|
index 6c9612c1..af026966 100644
|
|
--- a/daemon/cups-browsed.conf.in
|
|
+++ b/daemon/cups-browsed.conf.in
|
|
@@ -36,27 +36,27 @@
|
|
|
|
|
|
# Which protocols will we use to discover printers on the network?
|
|
-# Can use DNSSD and/or CUPS and/or LDAP, or 'none' for neither.
|
|
+# Can use DNSSD or 'none'.
|
|
|
|
BrowseRemoteProtocols @BROWSEREMOTEPROTOCOLS@
|
|
|
|
|
|
# Which protocols will we use to broadcast shared local printers to the network?
|
|
-# Can use DNSSD and/or CUPS, or 'none' for neither.
|
|
-# Only CUPS is actually supported, as DNSSD is done by CUPS itself (we ignore
|
|
-# DNSSD in this directive).
|
|
+# Can use DNSSD or 'none'.
|
|
+# Broadcasting is currently not supported, as DNSSD is done by CUPS itself
|
|
+# (we ignore DNSSD in this directive).
|
|
|
|
# BrowseLocalProtocols none
|
|
|
|
|
|
# Settings of this directive apply to both BrowseRemoteProtocols and
|
|
# BrowseLocalProtocols.
|
|
-# Can use DNSSD and/or CUPS and/or LDAP, or 'none' for neither.
|
|
+# Can use DNSSD or 'none'.
|
|
|
|
# BrowseProtocols none
|
|
|
|
|
|
-# Only browse remote printers (via DNS-SD or CUPS browsing) from
|
|
+# Only browse remote printers (via DNS-SD) from
|
|
# selected servers using the "BrowseAllow", "BrowseDeny", and
|
|
# "BrowseOrder" directives
|
|
|
|
@@ -120,8 +120,6 @@ BrowseRemoteProtocols @BROWSEREMOTEPROTOCOLS@
|
|
# Browsing-related operations such as adding or removing printer queues
|
|
# and broadcasting are each allowed to take up to a given amount of time.
|
|
# It can be configured, in seconds, with the BrowseTimeout directive.
|
|
-# Especially queues discovered by CUPS broadcasts will be removed after
|
|
-# this timeout if no further broadcast from the server happens.
|
|
|
|
# BrowseTimeout 300
|
|
|
|
@@ -286,17 +284,6 @@ BrowseRemoteProtocols @BROWSEREMOTEPROTOCOLS@
|
|
# BrowsePoll cups.example.com:631/version=1.1
|
|
|
|
|
|
-# LDAP browsing configuration
|
|
-# The default value for all options is an empty string. Example configuration:
|
|
-
|
|
-# BrowseLDAPBindDN cn=cups-browsed,dc=domain,dc=tld
|
|
-# BrowseLDAPCACertFile /path/to/server/certificate.pem
|
|
-# BrowseLDAPDN ou=printers,dc=domain,dc=tld
|
|
-# BrowseLDAPFilter (printerLocation=/Office 1/*)
|
|
-# BrowseLDAPPassword s3cret
|
|
-# BrowseLDAPServer ldaps://ldap.domain.tld
|
|
-
|
|
-
|
|
# Use DomainSocket to access the local CUPS daemon via another than the
|
|
# default domain socket. "None" or "Off" lets cups-browsed not use CUPS'
|
|
# domain socket.
|
|
@@ -405,7 +392,7 @@ BrowseRemoteProtocols @BROWSEREMOTEPROTOCOLS@
|
|
# conventional host-name/IP-based URIs.
|
|
|
|
# Note that this option has only influence on URIs for printers
|
|
-# discovered via DNS-SD, not via legacy CUPS broewsing or LDAP.
|
|
+# discovered via DNS-SD, not via BrowsePoll.
|
|
# Those printers get always assigned the conventional URIs.
|
|
|
|
# DNSSDBasedDeviceURIs Yes
|
|
diff --git a/test/run-tests.sh b/test/run-tests.sh
|
|
index f3dfaf3d..23a5dd29 100755
|
|
--- a/test/run-tests.sh
|
|
+++ b/test/run-tests.sh
|
|
@@ -938,7 +938,7 @@ while test $tries -lt $timeout; do
|
|
done
|
|
|
|
if test $tries -ge $timeout; then
|
|
- echo "FAIL: CUPS browsed did not remove CUPS queue ${queue_prefix}_ippeve_1 for first test printer!"
|
|
+ echo "FAIL: cups-browsed did not remove CUPS queue ${queue_prefix}_ippeve_1 for first test printer!"
|
|
clean_up 1
|
|
exit 1
|
|
fi
|
|
@@ -1021,7 +1021,7 @@ $runcups lpstat -v
|
|
echo ""
|
|
|
|
if test $tries -ge $timeout; then
|
|
- echo "FAIL: CUPS browsed did not remove CUPS queue ${queue_prefix}_ippeve_2 for second test printer!"
|
|
+ echo "FAIL: cups-browsed did not remove CUPS queue ${queue_prefix}_ippeve_2 for second test printer!"
|
|
clean_up 1
|
|
exit 1
|
|
fi
|
|
--
|
|
2.47.0
|
|
|