]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/dirsvc.c
Merge changes from CUPS 1.4svn-r8606.
[thirdparty/cups.git] / scheduler / dirsvc.c
index 27efd0d00018aabd468b42701452dd37e1c7ff46..11be5585e506a4d120b8db0620c319c23281f175 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$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.
  */
 
 /*
@@ -96,6 +156,10 @@ static void update_smb(int onoff);
 
 
 #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);
@@ -108,6 +172,7 @@ static void dnssdRegisterCallback(DNSServiceRef sdRef,
                                      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 */
 
@@ -180,8 +245,13 @@ cupsdDeregisterPrinter(
   * 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;
 
  /*
@@ -223,9 +293,10 @@ cupsdDeregisterPrinter(
 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 */
@@ -378,17 +449,13 @@ cupsdLoadRemoteCache(void)
         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"))
     {
@@ -415,14 +482,11 @@ cupsdLoadRemoteCache(void)
 
        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)
     {
@@ -443,6 +507,25 @@ cupsdLoadRemoteCache(void)
                                       &(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"))
     {
      /*
@@ -452,13 +535,13 @@ cupsdLoadRemoteCache(void)
       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"))
     {
@@ -486,22 +569,16 @@ cupsdLoadRemoteCache(void)
                !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"))
     {
@@ -513,11 +590,8 @@ cupsdLoadRemoteCache(void)
           p->browse_expire = t;
       }
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of remote.cache.", linenum);
-       break;
-      }
     }
     else if (!strcasecmp(line, "JobSheets"))
     {
@@ -548,11 +622,8 @@ cupsdLoadRemoteCache(void)
        }
       }
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of remote.cache.", linenum);
-       break;
-      }
     }
     else if (!strcasecmp(line, "AllowUser"))
     {
@@ -562,11 +633,8 @@ cupsdLoadRemoteCache(void)
         cupsdAddPrinterUser(p, value);
       }
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of remote.cache.", linenum);
-       break;
-      }
     }
     else if (!strcasecmp(line, "DenyUser"))
     {
@@ -576,11 +644,8 @@ cupsdLoadRemoteCache(void)
         cupsdAddPrinterUser(p, value);
       }
       else
-      {
        cupsdLogMessage(CUPSD_LOG_ERROR,
                        "Syntax error on line %d of remote.cache.", linenum);
-       break;
-      }
     }
     else
     {
@@ -612,8 +677,12 @@ cupsdLoadRemoteCache(void)
 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
@@ -654,7 +723,8 @@ cupsdSaveRemoteCache(void)
 {
   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 */
@@ -723,46 +793,49 @@ cupsdSaveRemoteCache(void)
     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");
@@ -817,7 +890,8 @@ cupsdSendBrowseList(void)
     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 ++;
 
@@ -843,7 +917,8 @@ cupsdSendBrowseList(void)
 
       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)
@@ -1364,9 +1439,14 @@ cupsdStartBrowsing(void)
                        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...
       */
@@ -1391,50 +1471,60 @@ cupsdStartBrowsing(void)
        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
@@ -1453,8 +1543,13 @@ cupsdStartBrowsing(void)
 
     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
     {
      /*
@@ -1521,6 +1616,10 @@ cupsdStartBrowsing(void)
                       "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;
@@ -1538,11 +1637,19 @@ cupsdStartBrowsing(void)
                       "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;
@@ -1566,7 +1673,8 @@ cupsdStartBrowsing(void)
   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);
 }
 
@@ -1650,7 +1758,7 @@ cupsdStartPolling(void)
     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",
@@ -1694,7 +1802,8 @@ cupsdStopBrowsing(void)
   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);
 
  /*
@@ -1720,29 +1829,7 @@ cupsdStopBrowsing(void)
 
 #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
@@ -1819,9 +1906,10 @@ cupsdUpdateDNSSDName(void)
   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 */
 
 
@@ -1830,6 +1918,7 @@ cupsdUpdateDNSSDName(void)
   * enabled...
   */
 
+
   if (!DNSSDPort)
     return;
 
@@ -1838,43 +1927,93 @@ cupsdUpdateDNSSDName(void)
   */
 
 #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 */
 
@@ -2120,6 +2259,41 @@ dequote(char       *d,                   /* I - Destination string */
 
 
 #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.
  */
@@ -2136,6 +2310,7 @@ dnssdBuildTxtRecord(
                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 */
 
 
  /*
@@ -2245,12 +2420,14 @@ dnssdBuildTxtRecord(
   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;
@@ -2258,12 +2435,13 @@ dnssdBuildTxtRecord(
       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;
   }
 
  /*
@@ -2307,9 +2485,6 @@ dnssdDeregisterPrinter(
     p->ipp_ref = NULL;
   }
 
-  cupsArrayRemove(DNSSDPrinters, p);
-  cupsdClearString(&p->reg_name);
-
   if (p->ipp_txt)
   {
    /*
@@ -2319,6 +2494,30 @@ dnssdDeregisterPrinter(
     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);
 }
 
 
@@ -2402,8 +2601,9 @@ dnssdRegisterCallback(
                                        /* 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)
   {
@@ -2411,7 +2611,7 @@ dnssdRegisterCallback(
                    "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);
@@ -2440,12 +2640,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
                        *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,
@@ -2492,31 +2687,44 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
   }
 
  /*
-  * 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)
   {
@@ -2528,9 +2736,8 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
                                              "_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...
@@ -2542,7 +2749,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
     {
       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)
@@ -2574,31 +2781,50 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
                       "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)
     {
      /*
@@ -2606,14 +2832,13 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
       */
 
       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)
@@ -2627,28 +2852,57 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
                        "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;
 }
 
 
@@ -2663,9 +2917,12 @@ dnssdUpdate(void)
 
 
   if ((sdErr = DNSServiceProcessResult(DNSSDRef)) != kDNSServiceErr_NoError)
+  {
     cupsdLogMessage(CUPSD_LOG_ERROR,
                     "DNS Service Discovery registration error %d!",
                    sdErr);
+    dnssdStop();
+  }
 }
 #endif /* HAVE_DNSSD */
 
@@ -3020,6 +3277,9 @@ process_browse_data(
     else
       p = cupsdAddPrinter(name);
 
+    if (!p)
+      return;
+
     cupsdClearString(&(p->hostname));
 
     cupsdLogMessage(CUPSD_LOG_DEBUG, "Added remote %s \"%s\"...",
@@ -3039,9 +3299,6 @@ process_browse_data(
     cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP);
   }
 
-  if (!p)
-    return;
-
   if (!p->hostname)
   {
    /*
@@ -3350,6 +3607,18 @@ process_implicit_classes(void)
       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;
@@ -5072,7 +5341,7 @@ update_lpd(int onoff)                     /* - 1 = turn on, 0 = turn off */
     argv[4] = NULL;
 
     cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1,
-                      NULL, &pid);
+                      NULL, NULL, &pid);
   }
 #endif /* __APPLE__ */
   else
@@ -5094,8 +5363,13 @@ update_polling(void)
 
   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)
   {
@@ -5178,5 +5452,5 @@ update_smb(int onoff)                     /* I - 1 = turn on, 0 = turn off */
 
 
 /*
- * 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 $".
  */