1 diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c
2 index 99b8e7b..2688eff 100644
5 @@ -1643,7 +1643,7 @@ do_config_server(http_t *http) /* I - HTTP connection */
7 local_protocols[0] = '\0';
10 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
11 if (cgiGetVariable("BROWSE_LOCAL_DNSSD"))
13 if (local_protocols[0])
14 @@ -1651,7 +1651,7 @@ do_config_server(http_t *http) /* I - HTTP connection */
16 strcat(local_protocols, "dnssd");
18 -#endif /* HAVE_DNSSD */
19 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
22 if (cgiGetVariable("BROWSE_LOCAL_LDAP"))
23 @@ -2718,9 +2718,9 @@ do_menu(http_t *http) /* I - HTTP connection */
24 #endif /* HAVE_GSSAPI */
25 cgiSetVariable("KERBEROS", "");
28 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
29 cgiSetVariable("HAVE_DNSSD", "1");
30 -#endif /* HAVE_DNSSD */
31 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
34 cgiSetVariable("HAVE_LDAP", "1");
35 diff --git a/scheduler/client.c b/scheduler/client.c
36 index e4c9b01..984dcc5 100644
37 --- a/scheduler/client.c
38 +++ b/scheduler/client.c
39 @@ -4987,7 +4987,7 @@ valid_host(cupsd_client_t *con) /* I - Client connection */
40 !strncmp(host, "[::1]:", 6));
44 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
46 * Check if the hostname is something.local (Bonjour); if so, allow it.
48 @@ -4996,7 +4996,7 @@ valid_host(cupsd_client_t *con) /* I - Client connection */
49 (!_cups_strcasecmp(end, ".local") || !_cups_strncasecmp(end, ".local:", 7) ||
50 !_cups_strcasecmp(end, ".local.") || !_cups_strncasecmp(end, ".local.:", 8)))
52 -#endif /* HAVE_DNSSD */
53 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
56 * Check if the hostname is an IP address...
57 diff --git a/scheduler/conf.c b/scheduler/conf.c
58 index badc630..c1edd39 100644
59 --- a/scheduler/conf.c
60 +++ b/scheduler/conf.c
61 @@ -648,7 +648,7 @@ cupsdReadConfiguration(void)
62 Browsing = CUPS_DEFAULT_BROWSING;
63 DefaultShared = CUPS_DEFAULT_DEFAULT_SHARED;
66 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
67 cupsdSetString(&DNSSDRegType, "_ipp._tcp,_cups");
68 #endif /* HAVE_DNSSD */
70 diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c
71 index eb3c862..48dcef9 100644
72 --- a/scheduler/dirsvc.c
73 +++ b/scheduler/dirsvc.c
75 * ldap_connect() - Start new LDAP connection
76 * ldap_reconnect() - Reconnect to LDAP Server
77 * ldap_disconnect() - Disconnect from LDAP Server
78 + * cupsdStartAvahiClient() - Start an Avahi client if needed
79 * cupsdStartBrowsing() - Start sending and receiving broadcast
81 * cupsdStartPolling() - Start polling servers as needed.
84 * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT
86 + * avahiPackTxtRecord() - Pack an array of key/value pairs into an
88 * dnssdRegisterCallback() - DNSServiceRegister callback.
89 * dnssdRegisterPrinter() - Start sending broadcast information for a
90 * printer or update the broadcast contents.
100 # endif /* HAVE_SYSTEMCONFIGURATION */
101 # endif /* __APPLE__ */
102 #endif /* HAVE_DNSSD */
104 +# include <avahi-common/domain.h>
105 +#endif /* HAVE_AVAHI */
109 +typedef char *cupsd_txt_record_t;
110 +#endif /* HAVE_DNSSD */
112 +typedef AvahiStringList *cupsd_txt_record_t;
113 +#endif /* HAVE_AVAHI */
117 @@ -159,27 +174,39 @@ static void update_polling(void);
118 static void update_smb(int onoff);
121 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
122 +static cupsd_txt_record_t dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
124 +static int dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b);
125 +static void dnssdDeregisterPrinter(cupsd_printer_t *p);
126 +static void dnssdRegisterPrinter(cupsd_printer_t *p);
127 +static void dnssdStop(void);
128 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
131 # ifdef HAVE_COREFOUNDATION
132 static void dnssdAddAlias(const void *key, const void *value,
134 # endif /* HAVE_COREFOUNDATION */
135 -static char *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
137 -static int dnssdComparePrinters(cupsd_printer_t *a, cupsd_printer_t *b);
138 -static void dnssdDeregisterPrinter(cupsd_printer_t *p);
139 -static char *dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2],
141 static void dnssdRegisterCallback(DNSServiceRef sdRef,
142 DNSServiceFlags flags,
143 DNSServiceErrorType errorCode,
144 const char *name, const char *regtype,
145 const char *domain, void *context);
146 -static void dnssdRegisterPrinter(cupsd_printer_t *p);
147 -static void dnssdStop(void);
148 static void dnssdUpdate(void);
149 #endif /* HAVE_DNSSD */
152 +static AvahiStringList *avahiPackTxtRecord(char *keyvalue[][2],
154 +static void avahi_entry_group_cb (AvahiEntryGroup *group,
155 + AvahiEntryGroupState state,
157 +static void avahi_client_cb (AvahiClient *client,
158 + AvahiClientState state,
160 +#endif /* HAVE_AVAHI */
163 static const char * const ldap_attrs[] =/* CUPS LDAP attributes */
165 @@ -283,10 +310,10 @@ cupsdDeregisterPrinter(
166 ldap_dereg_printer(p);
167 #endif /* HAVE_LDAP */
170 - if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
171 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
172 + if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD))
173 dnssdDeregisterPrinter(p);
174 -#endif /* HAVE_DNSSD */
175 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
179 @@ -702,10 +729,10 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
180 slpRegisterPrinter(p); */
181 #endif /* HAVE_LIBSLP */
184 - if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
185 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
186 + if ((BrowseLocalProtocols & BROWSE_DNSSD))
187 dnssdRegisterPrinter(p);
188 -#endif /* HAVE_DNSSD */
189 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
193 @@ -1419,6 +1446,27 @@ ldap_disconnect(LDAP *ld) /* I - LDAP handle */
194 #endif /* HAVE_LDAP */
199 + * 'cupsdStartAvahiClient()' - Start an Avahi client if needed
203 +cupsdStartAvahiClient(void)
205 + if (!AvahiCupsClient && !AvahiCupsClientConnecting)
207 + if (!AvahiCupsPollHandle)
208 + AvahiCupsPollHandle = avahi_cups_poll_new ();
210 + if (AvahiCupsPollHandle)
211 + avahi_client_new (avahi_cups_poll_get (AvahiCupsPollHandle),
212 + AVAHI_CLIENT_NO_FAIL, avahi_client_cb, NULL, NULL);
215 +#endif /* HAVE_AVAHI */
219 * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
221 @@ -1542,13 +1590,16 @@ cupsdStartBrowsing(void)
226 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
227 if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_DNSSD)
230 DNSServiceErrorType error; /* Error from service creation */
231 +#endif /* HAVE_DNSSD */
232 cupsd_listener_t *lis; /* Current listening socket */
237 * First create a "master" connection for all registrations...
239 @@ -1573,6 +1624,7 @@ cupsdStartBrowsing(void)
240 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
242 cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
243 +#endif /* HAVE_DNSSD */
246 * Then get the port we use for registrations. If we are not listening
247 @@ -1606,9 +1658,16 @@ cupsdStartBrowsing(void)
250 cupsdUpdateDNSSDName();
253 + cupsdStartAvahiClient ();
254 +#endif /* HAVE_AVAHI */
259 #endif /* HAVE_DNSSD */
261 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
264 if ((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP)
265 @@ -1834,10 +1893,10 @@ cupsdStopBrowsing(void)
270 - if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
271 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
272 + if ((BrowseLocalProtocols & BROWSE_DNSSD))
274 -#endif /* HAVE_DNSSD */
275 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
278 if (((BrowseLocalProtocols | BrowseRemoteProtocols) & BROWSE_SLP) &&
279 @@ -1902,7 +1961,7 @@ cupsdStopPolling(void)
284 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
286 * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
288 @@ -1910,8 +1969,14 @@ cupsdStopPolling(void)
290 cupsdUpdateDNSSDName(void)
293 DNSServiceErrorType error; /* Error from service creation */
294 char webif[1024]; /* Web interface share name */
295 +#endif /* HAVE_DNSSD */
297 + int ret; /* Error from service creation */
298 + char webif[AVAHI_LABEL_MAX]; /* Web interface share name */
299 +#endif /* HAVE_AVAHI */
300 # ifdef HAVE_SYSTEMCONFIGURATION
301 SCDynamicStoreRef sc; /* Context for dynamic store */
302 CFDictionaryRef btmm; /* Back-to-My-Mac domains */
303 @@ -2042,6 +2107,7 @@ cupsdUpdateDNSSDName(void)
305 strlcpy(webif, "CUPS Web Interface", sizeof(webif));
309 DNSServiceRefDeallocate(WebIFRef);
311 @@ -2054,9 +2120,45 @@ cupsdUpdateDNSSDName(void)
312 NULL)) != kDNSServiceErr_NoError)
313 cupsdLogMessage(CUPSD_LOG_ERROR,
314 "DNS-SD web interface registration failed: %d", error);
315 +#endif /* HAVE_DNSSD */
318 + if (!AvahiCupsClient)
320 + * Client not yet running.
324 + if (AvahiWebIFGroup)
325 + avahi_entry_group_reset (AvahiWebIFGroup);
327 + AvahiWebIFGroup = avahi_entry_group_new (AvahiCupsClient,
328 + avahi_entry_group_cb,
331 + if (AvahiWebIFGroup)
333 + ret = avahi_entry_group_add_service (AvahiWebIFGroup,
335 + AVAHI_PROTO_UNSPEC,
338 + "_http._tcp", /* type */
341 + DNSSDPort, /* port */
344 + ret = avahi_entry_group_commit (AvahiWebIFGroup);
347 + cupsdLogMessage (CUPSD_LOG_ERROR,
348 + "Avahi web interface registration failed: %d", ret);
350 +#endif /* HAVE_AVAHI */
353 -#endif /* HAVE_DNSSD */
354 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
358 @@ -2334,13 +2436,15 @@ dnssdAddAlias(const void *key, /* I - Key */
359 "Bad Back to My Mac domain in dynamic store!");
361 # endif /* HAVE_COREFOUNDATION */
362 +#endif /* HAVE_DNSSD */
365 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
367 * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
370 -static char * /* O - TXT record */
371 +static cupsd_txt_record_t /* O - TXT record */
373 int *txt_len, /* O - TXT record length */
374 cupsd_printer_t *p, /* I - Printer information */
375 @@ -2379,7 +2483,12 @@ dnssdBuildTxtRecord(
376 keyvalue[i ][0] = "ty";
377 keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown";
379 - snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName);
380 + snprintf(admin_hostname, sizeof(admin_hostname),
383 + "." /* terminating dot no good for Avahi */
384 +#endif /* HAVE_DNSSD */
386 httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
387 "http", NULL, admin_hostname, DNSSDPort, "/%s/%s",
388 (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
389 @@ -2462,7 +2571,12 @@ dnssdBuildTxtRecord(
390 * Then pack them into a proper txt record...
394 return (dnssdPackTxtRecord(txt_len, keyvalue, i));
395 +#endif /* HAVE_DNSSD */
397 + return (avahiPackTxtRecord(keyvalue, i));
398 +#endif /* HAVE_AVAHI */
402 @@ -2474,7 +2588,16 @@ static int /* O - Result of comparison */
403 dnssdComparePrinters(cupsd_printer_t *a,/* I - First printer */
404 cupsd_printer_t *b)/* I - Second printer */
406 - return (_cups_strcasecmp(a->reg_name, b->reg_name));
416 + return (_cups_strcasecmp(a->reg_name, b->reg_name));
420 @@ -2489,6 +2612,10 @@ dnssdDeregisterPrinter(
422 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name);
429 * Closing the socket deregisters the service
431 @@ -2524,6 +2651,24 @@ dnssdDeregisterPrinter(
432 free(p->printer_txt);
433 p->printer_txt = NULL;
435 +#endif /* HAVE_DNSSD */
438 + if (p->avahi_group)
440 + avahi_entry_group_reset (p->avahi_group);
441 + avahi_entry_group_free (p->avahi_group);
442 + p->avahi_group = NULL;
445 + avahi_string_list_free (p->ipp_txt);
447 + if (p->printer_txt)
448 + avahi_string_list_free (p->printer_txt);
450 + p->ipp_txt = p->printer_txt = NULL;
452 +#endif /* HAVE_AVAHI */
455 * Remove the printer from the array of DNS-SD printers, then clear the
456 @@ -2533,8 +2678,10 @@ dnssdDeregisterPrinter(
457 cupsArrayRemove(DNSSDPrinters, p);
458 cupsdClearString(&p->reg_name);
460 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
465 * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the
467 @@ -2644,8 +2791,10 @@ dnssdRegisterCallback(
468 LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
471 +#endif /* HAVE_DNSSD */
474 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
476 * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
477 * or update the broadcast contents.
478 @@ -2654,20 +2803,40 @@ dnssdRegisterCallback(
480 dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
483 DNSServiceErrorType se; /* dnssd errors */
484 char *ipp_txt, /* IPP TXT record buffer */
485 *printer_txt, /* LPD TXT record buffer */
486 - name[1024], /* Service name */
487 - *nameptr; /* Pointer into name */
488 + name[1024]; /* Service name */
489 int ipp_len, /* IPP TXT record length */
490 printer_len, /* LPD TXT record length */
491 printer_port; /* LPD port number */
492 +#endif /* HAVE_DNSSD */
494 + int ret; /* Error code */
495 + AvahiStringList *ipp_txt, /* IPP TXT record */
496 + *printer_txt; /* LPD TXT record */
497 + char name[AVAHI_LABEL_MAX], /* Service name */
498 + fullsubtype[AVAHI_LABEL_MAX]; /* Full subtype */
499 + char *regtype_copy, /* Writeable copy of reg type */
500 + *subtype, /* Current service sub type */
501 + *nextsubtype; /* Next service sub type */
502 +#endif /* HAVE_AVAHI */
503 + char *nameptr; /* Pointer into name */
504 const char *regtype; /* Registration type */
511 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
512 !p->ipp_ref ? "new" : "update");
514 +#endif /* HAVE_DNSSD */
516 + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
517 + !p->avahi_group ? "new" : "update");
518 +#endif /* HAVE_AVAHI */
520 * If per-printer sharing was just disabled make sure we're not
521 * registered before returning.
522 @@ -2686,12 +2855,36 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
523 if (p->info && strlen(p->info) > 0)
525 if (DNSSDComputerName)
526 - snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
529 + * Make sure there is room for at least 15 characters of
530 + * DNSSDComputerName.
533 + assert(sizeof(name) >= 15 + 4);
534 + nameptr = name + strlcpy(name, p->info,
536 + strnlen(DNSSDComputerName, 15));
537 + nameptr += strlcpy(nameptr, " @ ", sizeof(name) - (nameptr - name));
538 + strlcpy(nameptr, DNSSDComputerName, sizeof(name) - (nameptr - name));
541 strlcpy(name, p->info, sizeof(name));
543 else if (DNSSDComputerName)
544 - snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
547 + * Make sure there is room for at least 15 characters of
548 + * DNSSDComputerName.
551 + assert(sizeof(name) >= 15 + 4);
552 + nameptr = name + strlcpy(name, p->info,
554 + strnlen(DNSSDComputerName, 15));
555 + nameptr += strlcpy(nameptr, " @ ", sizeof(name) - (nameptr - name));
556 + strlcpy(nameptr, DNSSDComputerName, sizeof(name) - (nameptr - name));
559 strlcpy(name, p->name, sizeof(name));
561 @@ -2712,6 +2905,7 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
562 * Register IPP and (optionally) LPD...
566 ipp_len = 0; /* anti-compiler-warning-code */
567 ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
569 @@ -2884,6 +3078,209 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
573 +#endif /* HAVE_DNSSD */
575 + if (!AvahiCupsClient)
577 + * Client not running yet. The client callback will call us again later.
581 + ipp_txt = dnssdBuildTxtRecord(NULL, p, 0);
582 + printer_txt = dnssdBuildTxtRecord(NULL, p, 1);
583 + regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : DNSSDRegType;
585 + if (p->avahi_group && p->ipp_txt && ipp_txt &&
586 + !avahi_string_list_equal (p->ipp_txt, ipp_txt))
589 + * Update the existing registration...
592 + avahi_string_list_free (p->ipp_txt);
594 + if (p->printer_txt)
595 + avahi_string_list_free (p->printer_txt);
598 + * Update the service group entry.
601 + regtype_copy = strdup (regtype);
602 + subtype = strchr (regtype_copy, ',');
606 + cupsdLogMessage (CUPSD_LOG_DEBUG,
607 + "Updating TXT record for %s (%s)", name, regtype_copy);
608 + ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group,
610 + AVAHI_PROTO_UNSPEC,
614 + free (regtype_copy);
617 + goto update_failed;
619 + p->ipp_txt = ipp_txt;
622 + if (BrowseLocalProtocols & BROWSE_LPD)
624 + ret = avahi_entry_group_update_service_txt_strlst (p->avahi_group,
626 + AVAHI_PROTO_UNSPEC,
628 + "_printer._tcp", NULL,
631 + goto update_failed;
633 + p->printer_txt = printer_txt;
634 + printer_txt = NULL;
637 + ret = avahi_entry_group_commit (p->avahi_group);
641 + cupsdLogMessage (CUPSD_LOG_ERROR,
642 + "Failed to update TXT record for %s: %d",
644 + avahi_entry_group_reset (p->avahi_group);
645 + avahi_entry_group_free (p->avahi_group);
646 + p->avahi_group = NULL;
647 + ipp_txt = p->ipp_txt;
652 + if (!p->avahi_group)
655 + * Initial registration. Use the _fax subtype for fax queues...
658 + p->avahi_group = avahi_entry_group_new (AvahiCupsClient,
659 + avahi_entry_group_cb,
662 + cupsdLogMessage(CUPSD_LOG_DEBUG,
663 + "Registering Avahi printer %s with name \"%s\" and "
664 + "type \"%s\"", p->name, name, regtype);
666 + if (!p->avahi_group)
673 + * Add each service type (DNSSDRegType may contain several,
674 + * separated by commas).
677 + subtype = regtype_copy = strdup (regtype);
678 + while (subtype && *subtype)
680 + nextsubtype = strchr (subtype, ',');
682 + *nextsubtype++ = '\0';
684 + if (subtype == regtype_copy)
690 + cupsdLogMessage (CUPSD_LOG_DEBUG,
691 + "Adding TXT record for %s (%s)", name, regtype_copy);
692 + ret = avahi_entry_group_add_service_strlst (p->avahi_group,
694 + AVAHI_PROTO_UNSPEC,
695 + 0, name, regtype_copy,
706 + snprintf (fullsubtype, sizeof(fullsubtype),
707 + "%s._sub.%s", subtype, regtype_copy);
708 + cupsdLogMessage (CUPSD_LOG_DEBUG,
709 + "Adding TXT record for %s (%s)", name, fullsubtype);
710 + ret = avahi_entry_group_add_service_subtype (p->avahi_group,
712 + AVAHI_PROTO_UNSPEC,
715 + NULL, fullsubtype);
720 + free (regtype_copy);
724 + subtype = nextsubtype;
727 + free (regtype_copy);
728 + p->ipp_txt = ipp_txt;
731 + if (BrowseLocalProtocols & BROWSE_LPD)
733 + cupsdLogMessage(CUPSD_LOG_DEBUG,
734 + "Registering Avahi printer %s with name \"%s\" and "
735 + "type \"_printer._tcp\"", p->name, name);
737 + ret = avahi_entry_group_add_service_strlst (p->avahi_group,
739 + AVAHI_PROTO_UNSPEC,
741 + "_printer._tcp", NULL, NULL,
747 + p->printer_txt = printer_txt;
748 + printer_txt = NULL;
751 + ret = avahi_entry_group_commit (p->avahi_group);
756 + cupsdLogMessage (CUPSD_LOG_ERROR,
757 + "Failed to add Avahi entry for %s: %d",
759 + if (p->avahi_group)
761 + avahi_entry_group_reset (p->avahi_group);
762 + avahi_entry_group_free (p->avahi_group);
763 + p->avahi_group = NULL;
765 + ipp_txt = p->ipp_txt;
771 + avahi_string_list_free (ipp_txt);
774 + avahi_string_list_free (printer_txt);
775 +#endif /* HAVE_AVAHI */
779 @@ -2896,6 +3293,10 @@ dnssdStop(void)
781 cupsd_printer_t *p; /* Current printer */
786 +#endif /* HAVE_DNSSD */
789 * De-register the individual printers
790 @@ -2906,6 +3307,7 @@ dnssdStop(void)
791 p = (cupsd_printer_t *)cupsArrayNext(Printers))
792 dnssdDeregisterPrinter(p);
796 * Shutdown the rest of the service refs...
798 @@ -2926,14 +3328,17 @@ dnssdStop(void)
800 DNSServiceRefDeallocate(DNSSDRef);
802 +#endif /* HAVE_DNSSD */
804 cupsArrayDelete(DNSSDPrinters);
805 DNSSDPrinters = NULL;
809 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
814 * 'dnssdUpdate()' - Handle DNS-SD queries.
816 @@ -2955,6 +3360,147 @@ dnssdUpdate(void)
817 #endif /* HAVE_DNSSD */
822 + * 'avahiPackTxtRecord()' - Pack an array of key/value pairs into an
826 +static AvahiStringList * /* O - new string list */
827 +avahiPackTxtRecord(char *keyvalue[][2], /* I - Table of key value pairs */
828 + int count) /* I - Number of items in table */
830 + AvahiStringList *strlst = NULL;
835 + elements = malloc ((1 + count) * sizeof (char *));
839 + for (i = 0; i < count; i++)
841 + len = (1 + strlen (keyvalue[i][0]) +
842 + (keyvalue[i][1] ? 1 + strlen (keyvalue[i][1]) : 1));
843 + elements[i] = malloc (len * sizeof (char));
847 + snprintf (elements[i], len, "%s=%s", keyvalue[i][0], keyvalue[i][1]);
850 + strlst = avahi_string_list_new_from_array ((const char **) elements, count);
854 + free (elements[i]);
862 + * 'avahi_entry_group_cb()' - Avahi entry group callback function.
865 +avahi_entry_group_cb (AvahiEntryGroup *group,
866 + AvahiEntryGroupState state,
872 + name = ((cupsd_printer_t *) userdata)->reg_name;
874 + name = "CUPS web interface";
878 + case AVAHI_ENTRY_GROUP_UNCOMMITED:
879 + case AVAHI_ENTRY_GROUP_REGISTERING:
882 + case AVAHI_ENTRY_GROUP_ESTABLISHED:
883 + cupsdLogMessage (CUPSD_LOG_DEBUG,
884 + "Avahi entry group established for %s", name);
888 + cupsdLogMessage (CUPSD_LOG_DEBUG,
889 + "Avahi entry group %s has state %d",
897 + * 'avahi_client_cb()' - Avahi client callback function.
900 +avahi_client_cb (AvahiClient *client,
901 + AvahiClientState state,
904 + cupsd_printer_t *printer;
907 + case AVAHI_CLIENT_S_RUNNING:
909 + * Avahi client started successfully.
911 + AvahiCupsClient = client;
912 + AvahiCupsClientConnecting = 0;
913 + cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client started");
915 + cupsdUpdateDNSSDName ();
917 + for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
919 + printer = (cupsd_printer_t *)cupsArrayNext(Printers))
920 + if (Browsing && (BrowseLocalProtocols & BROWSE_DNSSD) &&
921 + (!(printer->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_IMPLICIT |
922 + CUPS_PRINTER_SCANNER))) && printer->shared)
923 + dnssdRegisterPrinter (printer);
927 + case AVAHI_CLIENT_CONNECTING:
929 + * No Avahi daemon, client is waiting.
931 + AvahiCupsClientConnecting = 1;
932 + cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client connecting");
935 + case AVAHI_CLIENT_FAILURE:
937 + * Avahi client failed, close it to allow a clean restart.
939 + cupsdLogMessage (CUPSD_LOG_ERROR,
940 + "Avahi client failed, "
941 + "closing client to allow a clean restart");
943 + for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
945 + printer = (cupsd_printer_t *)cupsArrayNext(Printers))
946 + dnssdDeregisterPrinter (printer);
948 + avahi_client_free(client);
949 + AvahiCupsClientConnecting = 0;
950 + AvahiCupsClient = NULL;
955 + cupsdLogMessage (CUPSD_LOG_DEBUG, "Avahi client state: %d", state);
958 +#endif /* HAVE_AVAHI */
962 * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
964 diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h
965 index 99079bd..d53a179 100644
966 --- a/scheduler/dirsvc.h
967 +++ b/scheduler/dirsvc.h
969 # endif /* HAVE_LDAP_SSL_H */
970 #endif /* HAVE_LDAP */
973 +# include <avahi-client/publish.h>
974 +#endif /* HAVE_AVAHI */
977 * Browse protocols...
979 @@ -131,19 +135,22 @@ VAR int PollPipe VALUE(0);
980 VAR cupsd_statbuf_t *PollStatusBuffer VALUE(NULL);
981 /* Status buffer for pollers */
984 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
985 VAR char *DNSSDComputerName VALUE(NULL),
986 /* Computer/server name */
987 *DNSSDHostName VALUE(NULL),
989 *DNSSDRegType VALUE(NULL);
990 /* Bonjour registration type */
991 -VAR cups_array_t *DNSSDAlias VALUE(NULL);
992 - /* List of dynamic ServerAlias's */
993 VAR int DNSSDPort VALUE(0);
994 /* Port number to register */
995 VAR cups_array_t *DNSSDPrinters VALUE(NULL);
996 /* Printers we have registered */
997 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1000 +VAR cups_array_t *DNSSDAlias VALUE(NULL);
1001 + /* List of dynamic ServerAlias's */
1002 VAR DNSServiceRef DNSSDRef VALUE(NULL),
1003 /* Master DNS-SD service reference */
1004 WebIFRef VALUE(NULL),
1005 @@ -152,6 +159,17 @@ VAR DNSServiceRef DNSSDRef VALUE(NULL),
1006 /* Remote printer browse reference */
1007 #endif /* HAVE_DNSSD */
1010 +VAR AvahiCupsPoll *AvahiCupsPollHandle VALUE(NULL);
1011 + /* AvahiCupsPoll object */
1012 +VAR AvahiClient *AvahiCupsClient VALUE(NULL);
1013 + /* AvahiClient object */
1014 +VAR int AvahiCupsClientConnecting VALUE(0);
1015 + /* Is AvahiClient object connecting? */
1016 +VAR AvahiEntryGroup *AvahiWebIFGroup VALUE(NULL);
1017 + /* Web interface entry group */
1018 +#endif /* HAVE_AVAHI */
1021 VAR SLPHandle BrowseSLPHandle VALUE(NULL);
1022 /* SLP API handle */
1023 @@ -195,13 +213,14 @@ extern void cupsdRegisterPrinter(cupsd_printer_t *p);
1024 extern void cupsdRestartPolling(void);
1025 extern void cupsdSaveRemoteCache(void);
1026 extern void cupsdSendBrowseList(void);
1027 +extern void cupsdStartAvahiClient(void);
1028 extern void cupsdStartBrowsing(void);
1029 extern void cupsdStartPolling(void);
1030 extern void cupsdStopBrowsing(void);
1031 extern void cupsdStopPolling(void);
1033 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1034 extern void cupsdUpdateDNSSDName(void);
1035 -#endif /* HAVE_DNSSD */
1036 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1038 extern void cupsdUpdateLDAPBrowse(void);
1039 #endif /* HAVE_LDAP */
1040 diff --git a/scheduler/ipp.c b/scheduler/ipp.c
1041 index a048baa..9a3ab11 100644
1042 --- a/scheduler/ipp.c
1043 +++ b/scheduler/ipp.c
1044 @@ -6087,7 +6087,7 @@ copy_printer_attrs(
1045 ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time",
1046 ippTimeToDate(curtime));
1049 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1050 if (!ra || cupsArrayFind(ra, "printer-dns-sd-name"))
1052 if (printer->reg_name)
1053 @@ -6097,7 +6097,7 @@ copy_printer_attrs(
1054 ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_NOVALUE,
1055 "printer-dns-sd-name", 0);
1057 -#endif /* HAVE_DNSSD */
1058 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1060 if (!ra || cupsArrayFind(ra, "printer-error-policy"))
1061 ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
1062 diff --git a/scheduler/main.c b/scheduler/main.c
1063 index 1e60572..6c210e6 100644
1064 --- a/scheduler/main.c
1065 +++ b/scheduler/main.c
1066 @@ -120,6 +120,10 @@ main(int argc, /* I - Number of command-line args */
1067 cupsd_listener_t *lis; /* Current listener */
1068 time_t current_time, /* Current time */
1069 activity, /* Client activity timer */
1071 + avahi_client_time, /* Time for next Avahi client
1073 +#endif /* HAVE_AVAHI */
1074 browse_time, /* Next browse send time */
1075 senddoc_time, /* Send-Document time */
1076 expire_time, /* Subscription expire time */
1077 @@ -662,6 +666,9 @@ main(int argc, /* I - Number of command-line args */
1080 current_time = time(NULL);
1082 + avahi_client_time = current_time;
1083 +#endif /* HAVE_AVAHI */
1084 browse_time = current_time;
1085 event_time = current_time;
1086 expire_time = current_time;
1087 @@ -884,6 +891,16 @@ main(int argc, /* I - Number of command-line args */
1088 tmo = cupsdNextTimeout (&tmo_delay);
1089 if (tmo && tmo_delay == 0)
1090 cupsdRunTimeout (tmo);
1093 + * Try to restart the Avahi client every 10 seconds if needed...
1096 + if ((current_time - avahi_client_time) >= 10)
1098 + avahi_client_time = current_time;
1099 + cupsdStartAvahiClient();
1101 #endif /* HAVE_AVAHI */
1104 diff --git a/scheduler/printers.c b/scheduler/printers.c
1105 index 4686c4c..fac7bbc 100644
1106 --- a/scheduler/printers.c
1107 +++ b/scheduler/printers.c
1108 @@ -883,9 +883,9 @@ cupsdDeletePrinter(
1109 cupsdClearString(&p->alert);
1110 cupsdClearString(&p->alert_description);
1113 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1114 cupsdClearString(&p->pdl);
1115 -#endif /* HAVE_DNSSD */
1116 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1118 cupsArrayDelete(p->filetypes);
1120 @@ -3765,7 +3765,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */
1121 attr->values[i].string.text = _cupsStrAlloc(mimetype);
1125 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1127 char pdl[1024]; /* Buffer to build pdl list */
1128 mime_filter_t *filter; /* MIME filter looping var */
1129 @@ -3821,7 +3821,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */
1131 cupsdSetString(&p->pdl, pdl);
1133 -#endif /* HAVE_DNSSD */
1134 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1138 diff --git a/scheduler/printers.h b/scheduler/printers.h
1139 index 1751578..fb04651 100644
1140 --- a/scheduler/printers.h
1141 +++ b/scheduler/printers.h
1144 # include <dns_sd.h>
1145 #endif /* HAVE_DNSSD */
1147 +# include "avahi.h"
1148 +#endif /* HAVE_AVAHI */
1149 #include <cups/pwg-private.h>
1152 @@ -95,16 +98,23 @@ struct cupsd_printer_s
1153 time_t marker_time; /* Last time marker attributes were updated */
1154 _ppd_cache_t *pc; /* PPD cache and mapping data */
1157 +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
1158 char *reg_name, /* Name used for service registration */
1159 - *pdl, /* pdl value for TXT record */
1160 - *ipp_txt, /* IPP TXT record contents */
1161 + *pdl; /* pdl value for TXT record */
1162 +#endif /* defined(HAVE_DNSSD) || defined(HAVE_AVAHI) */
1164 + char *ipp_txt, /* IPP TXT record contents */
1165 *printer_txt; /* LPD TXT record contents */
1166 int ipp_len, /* IPP TXT record length */
1167 printer_len; /* LPD TXT record length */
1168 DNSServiceRef ipp_ref, /* Reference for _ipp._tcp,_cups */
1169 printer_ref; /* Reference for _printer._tcp */
1170 #endif /* HAVE_DNSSD */
1172 + AvahiStringList *ipp_txt, /* IPP TXT record */
1173 + *printer_txt; /* LPD TXT record */
1174 + AvahiEntryGroup *avahi_group; /* Avahi entry group */
1175 +#endif /* HAVE_AVAHI */