/*
- * "$Id: dirsvc.c 7676 2008-06-18 23:42:37Z mike $"
+ * "$Id: dirsvc.c 7933 2008-09-11 00:44:58Z mike $"
*
* Directory services routines for the Common UNIX Printing System (CUPS).
*
- * Copyright 2007-2008 by Apple Inc.
+ * Copyright 2007-2009 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
*
* Contents:
*
+ * cupsdDeregisterPrinter() - Stop sending broadcast information for a local
+ * printer and remove any pending references to
+ * remote printers.
+ * cupsdLoadRemoteCache() - Load the remote printer cache.
+ * cupsdRegisterPrinter() - Start sending broadcast information for a
+ * printer or update the broadcast contents.
+ * cupsdRestartPolling() - Restart polling servers as needed.
+ * cupsdSaveRemoteCache() - Save the remote printer cache.
+ * cupsdSendBrowseList() - Send new browsing information as necessary.
+ * ldap_rebind_proc() - Callback function for LDAP rebind
+ * ldap_connect() - Start new LDAP connection
+ * ldap_reconnect() - Reconnect to LDAP Server
+ * ldap_disconnect() - Disconnect from LDAP Server
+ * cupsdStartBrowsing() - Start sending and receiving broadcast
+ * information.
+ * cupsdStartPolling() - Start polling servers as needed.
+ * cupsdStopBrowsing() - Stop sending and receiving broadcast
+ * information.
+ * cupsdStopPolling() - Stop polling servers as needed.
+ * cupsdUpdateDNSSDName() - Update the computer name we use for
+ * browsing...
+ * cupsdUpdateLDAPBrowse() - Scan for new printers via LDAP...
+ * cupsdUpdateSLPBrowse() - Get browsing information via SLP.
+ * dequote() - Remote quotes from a string.
+ * dnssdAddAlias() - Add a DNS-SD alias name.
+ * dnssdBuildTxtRecord() - Build a TXT record from printer info.
+ * dnssdComparePrinters() - Compare the registered names of two printers.
+ * dnssdDeregisterPrinter() - Stop sending broadcast information for a
+ * printer.
+ * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT
+ * record format.
+ * dnssdRegisterCallback() - DNSServiceRegister callback.
+ * dnssdRegisterPrinter() - Start sending broadcast information for a
+ * printer or update the broadcast contents.
+ * dnssdStop() - Stop all DNS-SD registrations.
+ * dnssdUpdate() - Handle DNS-SD queries.
+ * get_hostconfig() - Get an /etc/hostconfig service setting.
+ * is_local_queue() - Determine whether the URI points at a local
+ * queue.
+ * process_browse_data() - Process new browse data.
+ * process_implicit_classes() - Create/update implicit classes as needed.
+ * send_cups_browse() - Send new browsing information using the CUPS
+ * protocol.
+ * ldap_search_rec() - LDAP Search with reconnect
+ * ldap_freeres() - Free LDAPMessage
+ * ldap_getval_char() - Get first LDAP value and convert to string
+ * send_ldap_ou() - Send LDAP ou registrations.
+ * send_ldap_browse() - Send LDAP printer registrations.
+ * ldap_dereg_printer() - Delete printer from directory
+ * send_slp_browse() - Register the specified printer with SLP.
+ * slp_attr_callback() - SLP attribute callback
+ * slp_dereg_printer() - SLPDereg() the specified printer
+ * slp_get_attr() - Get an attribute from an SLP registration.
+ * slp_reg_callback() - Empty SLPRegReport.
+ * slp_url_callback() - SLP service url callback
+ * update_cups_browse() - Update the browse lists using the CUPS
+ * protocol.
+ * update_lpd() - Update the LPD configuration as needed.
+ * update_polling() - Read status messages from the poll daemons.
+ * update_smb() - Update the SMB configuration as needed.
*/
/*
#ifdef HAVE_DNSSD
+# ifdef HAVE_COREFOUNDATION
+static void dnssdAddAlias(const void *key, const void *value,
+ void *context);
+# endif /* HAVE_COREFOUNDATION */
static char *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
int for_lpd);
static int dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b);
const char *name, const char *regtype,
const char *domain, void *context);
static void dnssdRegisterPrinter(cupsd_printer_t *p);
+static void dnssdStop(void);
static void dnssdUpdate(void);
#endif /* HAVE_DNSSD */
* Only deregister if browsing is enabled and it's a local printer...
*/
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdDeregisterPrinter(p=%p(%s), removeit=%d)", p, p->name,
+ removeit);
+
if (!Browsing || !p->shared ||
- (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_SCANNER)))
return;
/*
void
cupsdLoadRemoteCache(void)
{
+ int i; /* Looping var */
cups_file_t *fp; /* remote.cache file */
int linenum; /* Current line number */
- char line[1024], /* Line from file */
+ char line[4096], /* Line from file */
*value, /* Pointer to value */
*valueptr, /* Pointer into value */
scheme[32], /* Scheme portion of URI */
p = NULL;
}
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else if (!p)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
}
else if (!strcasecmp(line, "Info"))
{
cupsdSetString(&p->hostname, host);
cupsdSetString(&p->uri, value);
- cupsdSetString(&p->device_uri, value);
+ cupsdSetDeviceURI(p, value);
}
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else if (!strcasecmp(line, "Option") && value)
{
&(p->options));
}
}
+ else if (!strcasecmp(line, "Reason"))
+ {
+ if (value)
+ {
+ for (i = 0 ; i < p->num_reasons; i ++)
+ if (!strcmp(value, p->reasons[i]))
+ break;
+
+ if (i >= p->num_reasons &&
+ p->num_reasons < (int)(sizeof(p->reasons) / sizeof(p->reasons[0])))
+ {
+ p->reasons[p->num_reasons] = _cupsStrAlloc(value);
+ p->num_reasons ++;
+ }
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Syntax error on line %d of remote.cache.", linenum);
+ }
else if (!strcasecmp(line, "State"))
{
/*
if (value && !strcasecmp(value, "idle"))
p->state = IPP_PRINTER_IDLE;
else if (value && !strcasecmp(value, "stopped"))
+ {
p->state = IPP_PRINTER_STOPPED;
+ cupsdSetPrinterReasons(p, "+paused");
+ }
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else if (!strcasecmp(line, "StateMessage"))
{
!strcasecmp(value, "false")))
p->accepting = 0;
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else if (!strcasecmp(line, "Type"))
{
if (value)
p->type = atoi(value);
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else if (!strcasecmp(line, "BrowseTime"))
{
p->browse_expire = t;
}
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else if (!strcasecmp(line, "JobSheets"))
{
}
}
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else if (!strcasecmp(line, "AllowUser"))
{
cupsdAddPrinterUser(p, value);
}
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else if (!strcasecmp(line, "DenyUser"))
{
cupsdAddPrinterUser(p, value);
}
else
- {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of remote.cache.", linenum);
- break;
- }
}
else
{
void
cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
{
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p,
+ p->name);
+
if (!Browsing || !BrowseLocalProtocols ||
- (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_SCANNER)))
return;
#ifdef HAVE_LIBSLP
{
int i; /* Looping var */
cups_file_t *fp; /* printers.conf file */
- char temp[1024]; /* Temporary string */
+ char temp[1024], /* Temporary string */
+ value[2048]; /* Value string */
cupsd_printer_t *printer; /* Current printer class */
time_t curtime; /* Current time */
struct tm *curdate; /* Current date */
else
cupsFilePrintf(fp, "Printer %s>\n", printer->name);
- cupsFilePrintf(fp, "Type %d\n", printer->type);
-
cupsFilePrintf(fp, "BrowseTime %d\n", (int)printer->browse_expire);
if (printer->info)
- cupsFilePrintf(fp, "Info %s\n", printer->info);
-
- if (printer->make_model)
- cupsFilePrintf(fp, "MakeModel %s\n", printer->make_model);
+ cupsFilePutConf(fp, "Info", printer->info);
if (printer->location)
- cupsFilePrintf(fp, "Location %s\n", printer->location);
+ cupsFilePutConf(fp, "Location", printer->location);
+
+ if (printer->make_model)
+ cupsFilePutConf(fp, "MakeModel", printer->make_model);
- if (printer->device_uri)
- cupsFilePrintf(fp, "DeviceURI %s\n", printer->device_uri);
+ cupsFilePutConf(fp, "DeviceURI", printer->device_uri);
if (printer->state == IPP_PRINTER_STOPPED)
- {
cupsFilePuts(fp, "State Stopped\n");
- cupsFilePrintf(fp, "StateMessage %s\n", printer->state_message);
- }
else
cupsFilePuts(fp, "State Idle\n");
+ for (i = 0; i < printer->num_reasons; i ++)
+ cupsFilePutConf(fp, "Reason", printer->reasons[i]);
+
+ cupsFilePrintf(fp, "Type %d\n", printer->type);
+
if (printer->accepting)
cupsFilePuts(fp, "Accepting Yes\n");
else
cupsFilePuts(fp, "Accepting No\n");
- cupsFilePrintf(fp, "JobSheets %s %s\n", printer->job_sheets[0],
- printer->job_sheets[1]);
+ snprintf(value, sizeof(value), "%s %s", printer->job_sheets[0],
+ printer->job_sheets[1]);
+ cupsFilePutConf(fp, "JobSheets", value);
for (i = 0; i < printer->num_users; i ++)
- cupsFilePrintf(fp, "%sUser %s\n", printer->deny_users ? "Deny" : "Allow",
- printer->users[i]);
+ cupsFilePutConf(fp, printer->deny_users ? "DenyUser" : "AllowUser",
+ printer->users[i]);
for (i = printer->num_options, option = printer->options;
i > 0;
i --, option ++)
- cupsFilePrintf(fp, "Option %s %s\n", option->name, option->value);
+ {
+ snprintf(value, sizeof(value), "%s %s", option->name, option->value);
+ cupsFilePutConf(fp, "Option", value);
+ }
if (printer->type & CUPS_PRINTER_CLASS)
cupsFilePuts(fp, "</Class>\n");
for (count = 0, p = (cupsd_printer_t *)cupsArrayFirst(Printers);
count < max_count && p != NULL;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
- if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) &&
+ if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_SCANNER)) &&
p->shared && p->browse_time < ut)
count ++;
if (!p)
break;
- else if ((p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)) ||
+ else if ((p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_SCANNER)) ||
!p->shared)
continue;
else if (p->browse_time < ut)
strerror(errno));
BrowseLocalProtocols &= ~BROWSE_CUPS;
BrowseRemoteProtocols &= ~BROWSE_CUPS;
- return;
+
+ if (FatalErrors & CUPSD_FATAL_BROWSE)
+ cupsdEndProcess(getpid(), 0);
}
+ }
+ if (BrowseSocket >= 0)
+ {
/*
* Bind the socket to browse port...
*/
BrowseSocket = -1;
BrowseLocalProtocols &= ~BROWSE_CUPS;
BrowseRemoteProtocols &= ~BROWSE_CUPS;
- return;
+
+ if (FatalErrors & CUPSD_FATAL_BROWSE)
+ cupsdEndProcess(getpid(), 0);
}
}
- /*
- * Set the "broadcast" flag...
- */
-
- val = 1;
- if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
+ if (BrowseSocket >= 0)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set broadcast mode - %s.",
- strerror(errno));
+ /*
+ * Set the "broadcast" flag...
+ */
+
+ val = 1;
+ if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set broadcast mode - %s.",
+ strerror(errno));
#ifdef WIN32
- closesocket(BrowseSocket);
+ closesocket(BrowseSocket);
#else
- close(BrowseSocket);
+ close(BrowseSocket);
#endif /* WIN32 */
- BrowseSocket = -1;
- BrowseLocalProtocols &= ~BROWSE_CUPS;
- BrowseRemoteProtocols &= ~BROWSE_CUPS;
- return;
- }
+ BrowseSocket = -1;
+ BrowseLocalProtocols &= ~BROWSE_CUPS;
+ BrowseRemoteProtocols &= ~BROWSE_CUPS;
- /*
- * Close the socket on exec...
- */
+ if (FatalErrors & CUPSD_FATAL_BROWSE)
+ cupsdEndProcess(getpid(), 0);
+ }
+ }
- fcntl(BrowseSocket, F_SETFD, fcntl(BrowseSocket, F_GETFD) | FD_CLOEXEC);
+ if (BrowseSocket >= 0)
+ {
+ /*
+ * Close the socket on exec...
+ */
- /*
- * Finally, add the socket to the input selection set as needed...
- */
+ fcntl(BrowseSocket, F_SETFD, fcntl(BrowseSocket, F_GETFD) | FD_CLOEXEC);
- if (BrowseRemoteProtocols & BROWSE_CUPS)
- {
/*
- * We only listen if we want remote printers...
+ * Finally, add the socket to the input selection set as needed...
*/
- cupsdAddSelect(BrowseSocket, (cupsd_selfunc_t)update_cups_browse,
- NULL, NULL);
+ if (BrowseRemoteProtocols & BROWSE_CUPS)
+ {
+ /*
+ * We only listen if we want remote printers...
+ */
+
+ cupsdAddSelect(BrowseSocket, (cupsd_selfunc_t)update_cups_browse,
+ NULL, NULL);
+ }
}
}
else
if ((error = DNSServiceCreateConnection(&DNSSDRef))
!= kDNSServiceErr_NoError)
+ {
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to create master DNS-SD reference: %d", error);
+
+ if (FatalErrors & CUPSD_FATAL_BROWSE)
+ cupsdEndProcess(getpid(), 0);
+ }
else
{
/*
"Unable to open an SLP handle; disabling SLP browsing!");
BrowseLocalProtocols &= ~BROWSE_SLP;
BrowseRemoteProtocols &= ~BROWSE_SLP;
+ BrowseSLPHandle = NULL;
+
+ if (FatalErrors & CUPSD_FATAL_BROWSE)
+ cupsdEndProcess(getpid(), 0);
}
BrowseSLPRefresh = 0;
"Need to set BrowseLDAPDN to use LDAP browsing!");
BrowseLocalProtocols &= ~BROWSE_LDAP;
BrowseRemoteProtocols &= ~BROWSE_LDAP;
+
+ if (FatalErrors & CUPSD_FATAL_BROWSE)
+ cupsdEndProcess(getpid(), 0);
}
else
{
- /* Open LDAP handle... */
- BrowseLDAPHandle = ldap_connect();
+ /*
+ * Open LDAP handle...
+ */
+
+ if ((BrowseLDAPHandle = ldap_connect()) == NULL &&
+ (FatalErrors & CUPSD_FATAL_BROWSE))
+ cupsdEndProcess(getpid(), 0);
}
BrowseLDAPRefresh = 0;
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
- if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_SCANNER)))
cupsdRegisterPrinter(p);
}
argv[1] = pollp->hostname;
if (cupsdStartProcess(polld, argv, envp, -1, -1, statusfds[1], -1, -1,
- 0, DefaultProfile, &(pollp->pid)) < 0)
+ 0, DefaultProfile, NULL, &(pollp->pid)) < 0)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"cupsdStartPolling: Unable to fork polling daemon - %s",
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
p;
p = (cupsd_printer_t *)cupsArrayNext(Printers))
- if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT)))
+ if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
+ CUPS_PRINTER_SCANNER)))
cupsdDeregisterPrinter(p, 1);
/*
#ifdef HAVE_DNSSD
if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
- {
- if (WebIFRef)
- {
- DNSServiceRefDeallocate(WebIFRef);
- WebIFRef = NULL;
- }
-
- if (RemoteRef)
- {
- DNSServiceRefDeallocate(RemoteRef);
- RemoteRef = NULL;
- }
-
- cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDRef));
-
- DNSServiceRefDeallocate(DNSSDRef);
- DNSSDRef = NULL;
-
- cupsArrayDelete(DNSSDPrinters);
- DNSSDPrinters = NULL;
-
- DNSSDPort = 0;
- }
+ dnssdStop();
#endif /* HAVE_DNSSD */
#ifdef HAVE_LIBSLP
DNSServiceErrorType error; /* Error from service creation */
char webif[1024]; /* Web interface share name */
#ifdef HAVE_COREFOUNDATION_H
- CFStringRef nameRef; /* Computer name CFString */
+ SCDynamicStoreRef sc; /* Context for dynamic store */
+ CFDictionaryRef btmm; /* Back-to-My-Mac domains */
+ CFStringRef nameRef; /* Host name CFString */
char nameBuffer[1024]; /* C-string buffer */
- CFStringEncoding nameEncoding; /* Computer name encoding */
#endif /* HAVE_COREFOUNDATION_H */
* enabled...
*/
+
if (!DNSSDPort)
return;
*/
#ifdef HAVE_COREFOUNDATION_H
- cupsdClearString(&DNSSDName);
+ sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
- if ((nameRef = SCDynamicStoreCopyComputerName(NULL,
- &nameEncoding)) != NULL)
+ if (sc)
{
- if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
- kCFStringEncodingUTF8))
- cupsdSetString(&DNSSDName, nameBuffer);
+ /*
+ * Get the computer name from the dynamic store...
+ */
- CFRelease(nameRef);
- }
+ cupsdClearString(&DNSSDName);
-#else
- cupsdSetString(&DNSSDName, ServerName);
+ if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL)
+ {
+ if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
+ kCFStringEncodingUTF8))
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Dynamic store host name is \"%s\".", nameBuffer);
+ cupsdSetString(&DNSSDName, nameBuffer);
+ }
+
+ CFRelease(nameRef);
+ }
+
+ if (!DNSSDName)
+ {
+ /*
+ * Use the ServerName instead...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Using ServerName \"%s\" as host name.", ServerName);
+ cupsdSetString(&DNSSDName, ServerName);
+ }
+
+ /*
+ * Get any Back-to-My-Mac domains and add them as aliases...
+ */
+
+ cupsdFreeAliases(DNSSDAlias);
+ DNSSDAlias = NULL;
+
+ btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac"));
+ if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID())
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.",
+ (int)CFDictionaryGetCount(btmm));
+ CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL);
+ }
+ else if (btmm)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Bad Back to My Mac data in dynamic store!");
+ else
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add.");
+
+ if (btmm)
+ CFRelease(btmm);
+
+ CFRelease(sc);
+ }
+ else
#endif /* HAVE_COREFOUNDATION_H */
+ cupsdSetString(&DNSSDName, ServerName);
/*
- * Then (re)register the web interface...
+ * Then (re)register the web interface if enabled...
*/
- if (DNSSDName)
- snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDName);
- else
- strlcpy(webif, "CUPS Web Interface", sizeof(webif));
+ if (BrowseWebIF)
+ {
+ if (DNSSDName)
+ snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDName);
+ else
+ strlcpy(webif, "CUPS Web Interface", sizeof(webif));
- if (WebIFRef)
- DNSServiceRefDeallocate(WebIFRef);
+ if (WebIFRef)
+ DNSServiceRefDeallocate(WebIFRef);
- WebIFRef = DNSSDRef;
- if ((error = DNSServiceRegister(&WebIFRef,
- kDNSServiceFlagsShareConnection,
- 0, webif, "_http._tcp", NULL,
- NULL, htons(DNSSDPort), 7,
- "\006path=/", dnssdRegisterCallback,
- NULL)) != kDNSServiceErr_NoError)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "DNS-SD web interface registration failed: %d", error);
+ WebIFRef = DNSSDRef;
+ if ((error = DNSServiceRegister(&WebIFRef,
+ kDNSServiceFlagsShareConnection,
+ 0, webif, "_http._tcp", NULL,
+ NULL, htons(DNSSDPort), 7,
+ "\006path=/", dnssdRegisterCallback,
+ NULL)) != kDNSServiceErr_NoError)
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "DNS-SD web interface registration failed: %d", error);
+ }
}
#endif /* HAVE_DNSSD */
#ifdef HAVE_DNSSD
+# ifdef HAVE_COREFOUNDATION
+/*
+ * 'dnssdAddAlias()' - Add a DNS-SD alias name.
+ */
+
+static void
+dnssdAddAlias(const void *key, /* I - Key */
+ const void *value, /* I - Value (domain) */
+ void *context) /* I - Unused */
+{
+ char valueStr[1024], /* Domain string */
+ hostname[1024]; /* Complete hostname */
+
+
+ (void)context;
+
+ if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() &&
+ CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr),
+ kCFStringEncodingUTF8))
+ {
+ snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDName, valueStr);
+ if (!DNSSDAlias)
+ DNSSDAlias = cupsArrayNew(NULL, NULL);
+
+ cupsdAddAlias(DNSSDAlias, hostname);
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s",
+ hostname);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Bad Back to My Mac domain in dynamic store!");
+}
+# endif /* HAVE_COREFOUNDATION */
+
+
/*
* 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
*/
rp_str[1024], /* Queue name string buffer */
air_str[1024], /* auth-info-required string buffer */
*keyvalue[32][2]; /* Table of key/value pairs */
+ ipp_attribute_t *air_attr; /* auth-info-required attribute */
/*
keyvalue[i ][0] = "pdl";
keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript";
- if (p->num_auth_info_required)
+ if ((air_attr = ippFindAttribute(p->attrs, "auth-info-required",
+ IPP_TAG_KEYWORD)) != NULL &&
+ strcmp(air_attr->values[0].string.text, "none"))
{
char *air = air_str; /* Pointer into string */
- for (j = 0; j < p->num_auth_info_required; j ++)
+ for (j = 0; j < air_attr->num_values; j ++)
{
if (air >= (air_str + sizeof(air_str) - 2))
break;
if (j)
*air++ = ',';
- strlcpy(air, p->auth_info_required[j], sizeof(air_str) - (air - air_str));
+ strlcpy(air, air_attr->values[j].string.text,
+ sizeof(air_str) - (air - air_str));
air += strlen(air);
}
keyvalue[i ][0] = "air";
- keyvalue[i++][1] = air;
+ keyvalue[i++][1] = air_str;
}
/*
p->ipp_ref = NULL;
}
- cupsArrayRemove(DNSSDPrinters, p);
- cupsdClearString(&p->reg_name);
-
if (p->ipp_txt)
{
/*
free(p->ipp_txt);
p->ipp_txt = NULL;
}
+
+ if (p->printer_ref)
+ {
+ DNSServiceRefDeallocate(p->printer_ref);
+ p->printer_ref = NULL;
+ }
+
+ if (p->printer_txt)
+ {
+ /*
+ * p->printer_txt is malloc'd, not _cupsStrAlloc'd...
+ */
+
+ free(p->printer_txt);
+ p->printer_txt = NULL;
+ }
+
+ /*
+ * Remove the printer from the array of DNS-SD printers, then clear the
+ * registered name...
+ */
+
+ cupsArrayRemove(DNSSDPrinters, p);
+ cupsdClearString(&p->reg_name);
}
/* Current printer */
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s",
- name, regtype, p ? p->name : "Web Interface");
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)",
+ name, regtype, p ? p->name : "Web Interface",
+ p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
if (errorCode)
{
"DNSServiceRegister failed with error %d", (int)errorCode);
return;
}
- else if (p && strcasecmp(name, p->reg_name))
+ else if (p && (!p->reg_name || strcasecmp(name, p->reg_name)))
{
cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"",
name, p->name);
*nameptr; /* Pointer into name */
int ipp_len, /* IPP TXT record length */
printer_len; /* LPD TXT record length */
- char resource[1024]; /* Resource path for printer */
const char *regtype; /* Registration type */
- const char *domain; /* Registration domain */
- cupsd_location_t *location, /* Printer location */
- *policy; /* Operation policy for Print-Job */
- unsigned address[4]; /* INADDR_ANY address */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
}
/*
- * If 'Allow printing from the Internet' is enabled (i.e. from any address)
- * let dnssd decide on the domain, otherwise restrict it to ".local".
+ * Register IPP and (optionally) LPD...
*/
- if (p->type & CUPS_PRINTER_CLASS)
- snprintf(resource, sizeof(resource), "/classes/%s", p->name);
- else
- snprintf(resource, sizeof(resource), "/printers/%s", p->name);
+ ipp_len = 0; /* anti-compiler-warning-code */
+ ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
- address[0] = address[1] = address[2] = address[3] = 0;
- location = cupsdFindBest(resource, HTTP_POST);
- policy = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
+ if (p->ipp_ref &&
+ (ipp_len != p->ipp_len || memcmp(ipp_txt, p->ipp_txt, ipp_len)))
+ {
+ /*
+ * Update the existing registration...
+ */
- if ((location && !cupsdCheckAccess(address, "", 0, location)) ||
- (policy && !cupsdCheckAccess(address, "", 0, policy)))
- domain = "local.";
- else
- domain = NULL;
+ /* A TTL of 0 means use record's original value (Radar 3176248) */
+ if ((se = DNSServiceUpdateRecord(p->ipp_ref, NULL, 0, ipp_len, ipp_txt,
+ 0)) == kDNSServiceErr_NoError)
+ {
+ if (p->ipp_txt)
+ free(p->ipp_txt);
- /*
- * Register IPP and (optionally) LPD...
- */
+ p->ipp_txt = ipp_txt;
+ p->ipp_len = ipp_len;
+ ipp_txt = NULL;
+ }
+ else
+ {
+ /*
+ * Failed to update record, lets close this reference and move on...
+ */
- ipp_len = 0; /* anti-compiler-warning-code */
- ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to update IPP DNS-SD record for %s - %d", p->name,
+ se);
+
+ DNSServiceRefDeallocate(p->ipp_ref);
+ p->ipp_ref = NULL;
+ }
+ }
if (!p->ipp_ref)
{
"_ipp._tcp,_cups";
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Registering DNS-SD printer %s with name \"%s\", "
- "type \"%s\", and domain \"%s\"", p->name, name, regtype,
- domain ? domain : "(null)");
+ "Registering DNS-SD printer %s with name \"%s\" and "
+ "type \"%s\"", p->name, name, regtype);
/*
* Register the queue, dropping characters as needed until we succeed...
{
p->ipp_ref = DNSSDRef;
if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection,
- 0, name, regtype, domain, NULL,
+ 0, name, regtype, NULL, NULL,
htons(DNSSDPort), ipp_len, ipp_txt,
dnssdRegisterCallback,
p)) == kDNSServiceErr_BadParam)
"DNS-SD IPP registration of \"%s\" failed: %d",
p->name, se);
}
- else if (ipp_len != p->ipp_len || memcmp(ipp_txt, p->ipp_txt, ipp_len))
- {
- /*
- * Update the existing registration...
- */
-
- /* A TTL of 0 means use record's original value (Radar 3176248) */
- DNSServiceUpdateRecord(p->ipp_ref, NULL, 0, ipp_len, ipp_txt, 0);
-
- if (p->ipp_txt)
- free(p->ipp_txt);
-
- p->ipp_txt = ipp_txt;
- p->ipp_len = ipp_len;
- ipp_txt = NULL;
- }
if (ipp_txt)
free(ipp_txt);
if (BrowseLocalProtocols & BROWSE_LPD)
{
- printer_len = 0; /* anti-compiler-warning-code */
+ printer_len = 0; /* anti-compiler-warning-code */
printer_txt = dnssdBuildTxtRecord(&printer_len, p, 1);
+ if (p->printer_ref &&
+ (printer_len != p->printer_len ||
+ memcmp(printer_txt, p->printer_txt, printer_len)))
+ {
+ /*
+ * Update the existing registration...
+ */
+
+ /* A TTL of 0 means use record's original value (Radar 3176248) */
+ if ((se = DNSServiceUpdateRecord(p->printer_ref, NULL, 0, printer_len,
+ printer_txt,
+ 0)) == kDNSServiceErr_NoError)
+ {
+ if (p->printer_txt)
+ free(p->printer_txt);
+
+ p->printer_txt = printer_txt;
+ p->printer_len = printer_len;
+ printer_txt = NULL;
+ }
+ else
+ {
+ /*
+ * Failed to update record, lets close this reference and move on...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Unable to update LPD DNS-SD record for %s - %d",
+ p->name, se);
+
+ DNSServiceRefDeallocate(p->printer_ref);
+ p->printer_ref = NULL;
+ }
+ }
+
if (!p->printer_ref)
{
/*
*/
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Registering DNS-SD printer %s with name \"%s\", "
- "type \"_printer._tcp\", and domain \"%s\"", p->name,
- name, domain ? domain : "(null)");
+ "Registering DNS-SD printer %s with name \"%s\" and "
+ "type \"_printer._tcp\"", p->name, name);
p->printer_ref = DNSSDRef;
if ((se = DNSServiceRegister(&p->printer_ref,
kDNSServiceFlagsShareConnection,
- 0, name, "_printer._tcp", domain, NULL,
+ 0, name, "_printer._tcp", NULL, NULL,
htons(515), printer_len, printer_txt,
dnssdRegisterCallback,
p)) == kDNSServiceErr_NoError)
"DNS-SD LPD registration of \"%s\" failed: %d",
p->name, se);
}
- else if (printer_len != p->printer_len ||
- memcmp(printer_txt, p->printer_txt, printer_len))
- {
- /*
- * Update the existing registration...
- */
- /* A TTL of 0 means use record's original value (Radar 3176248) */
- DNSServiceUpdateRecord(p->printer_ref, NULL, 0, printer_len,
- printer_txt, 0);
+ if (printer_txt)
+ free(printer_txt);
+ }
+}
- if (p->printer_txt)
- free(p->printer_txt);
- p->printer_txt = printer_txt;
- p->printer_len = printer_len;
- printer_txt = NULL;
- }
+/*
+ * 'dnssdStop()' - Stop all DNS-SD registrations.
+ */
- if (printer_txt)
- free(printer_txt);
+static void
+dnssdStop(void)
+{
+ cupsd_printer_t *p; /* Current printer */
+
+
+ /*
+ * De-register the individual printers
+ */
+
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+ p;
+ p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ dnssdDeregisterPrinter(p);
+
+ /*
+ * Shutdown the rest of the service refs...
+ */
+
+ if (WebIFRef)
+ {
+ DNSServiceRefDeallocate(WebIFRef);
+ WebIFRef = NULL;
}
+
+ if (RemoteRef)
+ {
+ DNSServiceRefDeallocate(RemoteRef);
+ RemoteRef = NULL;
+ }
+
+ cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDRef));
+
+ DNSServiceRefDeallocate(DNSSDRef);
+ DNSSDRef = NULL;
+
+ cupsArrayDelete(DNSSDPrinters);
+ DNSSDPrinters = NULL;
+
+ DNSSDPort = 0;
}
if ((sdErr = DNSServiceProcessResult(DNSSDRef)) != kDNSServiceErr_NoError)
+ {
cupsdLogMessage(CUPSD_LOG_ERROR,
"DNS Service Discovery registration error %d!",
sdErr);
+ dnssdStop();
+ }
}
#endif /* HAVE_DNSSD */
else
p = cupsdAddPrinter(name);
+ if (!p)
+ return;
+
cupsdClearString(&(p->hostname));
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added remote %s \"%s\"...",
cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
}
- if (!p)
- return;
-
if (!p->hostname)
{
/*
else
len = strlen(p->name);
+ if (len >= sizeof(name))
+ {
+ /*
+ * If the printer name length somehow is greater than we normally allow,
+ * skip this printer...
+ */
+
+ len = 0;
+ cupsArrayRestore(Printers);
+ continue;
+ }
+
strncpy(name, p->name, len);
name[len] = '\0';
offset = 0;
argv[4] = NULL;
cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1,
- NULL, &pid);
+ NULL, NULL, &pid);
}
#endif /* __APPLE__ */
else
while ((ptr = cupsdStatBufUpdate(PollStatusBuffer, &loglevel,
message, sizeof(message))) != NULL)
+ {
+ if (loglevel == CUPSD_LOG_INFO)
+ cupsdLogMessage(CUPSD_LOG_INFO, "%s", message);
+
if (!strchr(PollStatusBuffer->buffer, '\n'))
break;
+ }
if (ptr == NULL && !PollStatusBuffer->bufused)
{
/*
- * End of "$Id: dirsvc.c 7676 2008-06-18 23:42:37Z mike $".
+ * End of "$Id: dirsvc.c 7933 2008-09-11 00:44:58Z mike $".
*/