2
* "$Id: dirsvc.c 11193 2013-07-26 03:12:37Z msweet $"
4
* Directory services routines for the CUPS scheduler.
6
* Copyright 2007-2013 by Apple Inc.
7
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
9
* These coded instructions, statements, and computer programs are the
10
* property of Apple Inc. and are protected by Federal copyright
11
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
12
* which should have been included with this file. If this file is
13
* file is missing or damaged, see the license at "http://www.cups.org/".
17
* cupsdDeregisterPrinter() - Stop sending broadcast information for a local
18
* printer and remove any pending references to
20
* cupsdRegisterPrinter() - Start sending broadcast information for a
21
* printer or update the broadcast contents.
22
* cupsdStartBrowsing() - Start sending and receiving broadcast
24
* cupsdStopBrowsing() - Stop sending and receiving broadcast
26
* cupsdUpdateDNSSDName() - Update the computer name we use for
28
* dnssdAddAlias() - Add a DNS-SD alias name.
29
* dnssdBuildTxtRecord() - Build a TXT record from printer info.
30
* dnssdDeregisterInstance() - Deregister a DNS-SD service instance.
31
* dnssdDeregisterPrinter() - Deregister all services for a printer.
32
* dnssdErrorString() - Return an error string for an error code.
33
* dnssdRegisterCallback() - Free a TXT record.
34
* dnssdRegisterCallback() - DNSServiceRegister callback.
35
* dnssdRegisterInstance() - Register an instance of a printer service.
36
* dnssdRegisterPrinter() - Start sending broadcast information for a
37
* printer or update the broadcast contents.
38
* dnssdStop() - Stop all DNS-SD registrations.
39
* dnssdUpdate() - Handle DNS-SD queries.
40
* get_auth_info_required() - Get the auth-info-required value to advertise.
41
* get_hostconfig() - Get an /etc/hostconfig service setting.
42
* update_lpd() - Update the LPD configuration as needed.
43
* update_smb() - Update the SMB configuration as needed.
47
* Include necessary headers...
53
#if defined(HAVE_DNSSD) && defined(__APPLE__)
55
# include <CoreFoundation/CoreFoundation.h>
56
# include <SystemConfiguration/SystemConfiguration.h>
57
#endif /* HAVE_DNSSD && __APPLE__ */
64
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
65
static char *get_auth_info_required(cupsd_printer_t *p,
66
char *buffer, size_t bufsize);
67
#endif /* HAVE_DNSSD || HAVE_AVAHI */
69
static int get_hostconfig(const char *name);
70
#endif /* __APPLE__ */
71
static void update_lpd(int onoff);
72
static void update_smb(int onoff);
75
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
77
static void dnssdAddAlias(const void *key, const void *value,
79
# endif /* __APPLE__ */
80
static cupsd_txt_t dnssdBuildTxtRecord(cupsd_printer_t *p, int for_lpd);
81
static void dnssdDeregisterInstance(cupsd_srv_t *srv);
82
static void dnssdDeregisterPrinter(cupsd_printer_t *p,
84
static const char *dnssdErrorString(int error);
85
static void dnssdFreeTxtRecord(cupsd_txt_t *txt);
87
static void dnssdRegisterCallback(DNSServiceRef sdRef,
88
DNSServiceFlags flags,
89
DNSServiceErrorType errorCode,
95
static void dnssdRegisterCallback(AvahiEntryGroup *p,
96
AvahiEntryGroupState state,
98
# endif /* HAVE_DNSSD */
99
static int dnssdRegisterInstance(cupsd_srv_t *srv,
101
char *name, const char *type,
102
const char *subtypes, int port,
103
cupsd_txt_t *txt, int commit);
104
static void dnssdRegisterPrinter(cupsd_printer_t *p);
105
static void dnssdStop(void);
107
static void dnssdUpdate(void);
108
# endif /* HAVE_DNSSD */
109
#endif /* HAVE_DNSSD || HAVE_AVAHI */
113
* 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
114
* local printer and remove any pending
115
* references to remote printers.
119
cupsdDeregisterPrinter(
120
cupsd_printer_t *p, /* I - Printer to register */
121
int removeit) /* I - Printer being permanently removed */
124
* Only deregister if browsing is enabled and it's a local printer...
127
cupsdLogMessage(CUPSD_LOG_DEBUG,
128
"cupsdDeregisterPrinter(p=%p(%s), removeit=%d)", p, p->name,
131
if (!Browsing || !p->shared ||
132
(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
136
* Announce the deletion...
139
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
140
if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster)
141
dnssdDeregisterPrinter(p, 1);
142
#endif /* HAVE_DNSSD || HAVE_AVAHI */
147
* 'cupsdRegisterPrinter()' - Start sending broadcast information for a
148
* printer or update the broadcast contents.
152
cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
154
cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p,
157
if (!Browsing || !BrowseLocalProtocols ||
158
(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
161
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
162
if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster)
163
dnssdRegisterPrinter(p);
164
#endif /* HAVE_DNSSD || HAVE_AVAHI */
169
* 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
173
cupsdStartBrowsing(void)
175
cupsd_printer_t *p; /* Current printer */
178
if (!Browsing || !BrowseLocalProtocols)
181
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
182
if (BrowseLocalProtocols & BROWSE_DNSSD)
184
cupsd_listener_t *lis; /* Current listening socket */
186
DNSServiceErrorType error; /* Error from service creation */
189
* First create a "master" connection for all registrations...
192
if ((error = DNSServiceCreateConnection(&DNSSDMaster))
193
!= kDNSServiceErr_NoError)
195
cupsdLogMessage(CUPSD_LOG_ERROR,
196
"Unable to create master DNS-SD reference: %d", error);
198
if (FatalErrors & CUPSD_FATAL_BROWSE)
199
cupsdEndProcess(getpid(), 0);
204
* Add the master connection to the select list...
207
int fd = DNSServiceRefSockFD(DNSSDMaster);
209
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
211
cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
214
# else /* HAVE_AVAHI */
215
if ((DNSSDMaster = avahi_threaded_poll_new()) == NULL)
217
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create DNS-SD thread.");
219
if (FatalErrors & CUPSD_FATAL_BROWSE)
220
cupsdEndProcess(getpid(), 0);
224
int error; /* Error code, if any */
226
DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), 0,
229
if (DNSSDClient == NULL)
231
cupsdLogMessage(CUPSD_LOG_ERROR,
232
"Unable to communicate with avahi-daemon: %s",
233
dnssdErrorString(error));
235
if (FatalErrors & CUPSD_FATAL_BROWSE)
236
cupsdEndProcess(getpid(), 0);
238
avahi_threaded_poll_free(DNSSDMaster);
242
avahi_threaded_poll_start(DNSSDMaster);
244
# endif /* HAVE_DNSSD */
247
* Then get the port we use for registrations. If we are not listening
248
* on any non-local ports, there is no sense sharing local printers via
254
for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
256
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
258
if (httpAddrLocalhost(&(lis->address)))
261
DNSSDPort = httpAddrPort(&(lis->address));
266
* Set the computer name and register the web interface...
269
cupsdUpdateDNSSDName();
271
#endif /* HAVE_DNSSD || HAVE_AVAHI */
274
* Enable LPD and SMB printer sharing as needed through external programs...
277
if (BrowseLocalProtocols & BROWSE_LPD)
280
if (BrowseLocalProtocols & BROWSE_SMB)
284
* Register the individual printers
287
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
289
p = (cupsd_printer_t *)cupsArrayNext(Printers))
290
if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
291
cupsdRegisterPrinter(p);
296
* 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information.
300
cupsdStopBrowsing(void)
302
cupsd_printer_t *p; /* Current printer */
305
if (!Browsing || !BrowseLocalProtocols)
309
* De-register the individual printers
312
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
314
p = (cupsd_printer_t *)cupsArrayNext(Printers))
315
if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
316
cupsdDeregisterPrinter(p, 1);
319
* Shut down browsing sockets...
322
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
323
if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster)
325
#endif /* HAVE_DNSSD || HAVE_AVAHI */
328
* Disable LPD and SMB printer sharing as needed through external programs...
331
if (BrowseLocalProtocols & BROWSE_LPD)
334
if (BrowseLocalProtocols & BROWSE_SMB)
339
#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
341
* 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
345
cupsdUpdateDNSSDName(void)
347
char webif[1024]; /* Web interface share name */
349
SCDynamicStoreRef sc; /* Context for dynamic store */
350
CFDictionaryRef btmm; /* Back-to-My-Mac domains */
351
CFStringEncoding nameEncoding; /* Encoding of computer name */
352
CFStringRef nameRef; /* Host name CFString */
353
char nameBuffer[1024]; /* C-string buffer */
354
# endif /* __APPLE__ */
358
* Only share the web interface and printers when non-local listening is
366
* Get the computer name as a c-string...
370
sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
375
* Get the computer name from the dynamic store...
378
cupsdClearString(&DNSSDComputerName);
380
if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL)
382
if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
383
kCFStringEncodingUTF8))
385
cupsdLogMessage(CUPSD_LOG_DEBUG,
386
"Dynamic store computer name is \"%s\".", nameBuffer);
387
cupsdSetString(&DNSSDComputerName, nameBuffer);
393
if (!DNSSDComputerName)
396
* Use the ServerName instead...
399
cupsdLogMessage(CUPSD_LOG_DEBUG,
400
"Using ServerName \"%s\" as computer name.", ServerName);
401
cupsdSetString(&DNSSDComputerName, ServerName);
405
* Get the local hostname from the dynamic store...
408
cupsdClearString(&DNSSDHostName);
410
if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL)
412
if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
413
kCFStringEncodingUTF8))
415
cupsdLogMessage(CUPSD_LOG_DEBUG,
416
"Dynamic store host name is \"%s\".", nameBuffer);
417
cupsdSetString(&DNSSDHostName, nameBuffer);
426
* Use the ServerName instead...
429
cupsdLogMessage(CUPSD_LOG_DEBUG,
430
"Using ServerName \"%s\" as host name.", ServerName);
431
cupsdSetString(&DNSSDHostName, ServerName);
435
* Get any Back-to-My-Mac domains and add them as aliases...
438
cupsdFreeAliases(DNSSDAlias);
441
btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac"));
442
if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID())
444
cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.",
445
(int)CFDictionaryGetCount(btmm));
446
CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL);
449
cupsdLogMessage(CUPSD_LOG_ERROR,
450
"Bad Back to My Mac data in dynamic store!");
452
cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add.");
460
# endif /* __APPLE__ */
464
const char *host_name = avahi_client_get_host_name(DNSSDClient);
465
const char *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient);
467
cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName);
470
cupsdSetString(&DNSSDHostName, host_fqdn);
471
else if (strchr(ServerName, '.'))
472
cupsdSetString(&DNSSDHostName, ServerName);
474
cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName);
477
# endif /* HAVE_AVAHI */
479
cupsdSetString(&DNSSDComputerName, ServerName);
481
if (strchr(ServerName, '.'))
482
cupsdSetString(&DNSSDHostName, ServerName);
484
cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName);
488
* Then (re)register the web interface if enabled...
493
if (DNSSDComputerName)
494
snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName);
496
strlcpy(webif, "CUPS", sizeof(webif));
498
dnssdDeregisterInstance(&WebIFSrv);
499
dnssdRegisterInstance(&WebIFSrv, NULL, webif, "_http._tcp", "_printer",
507
* 'dnssdAddAlias()' - Add a DNS-SD alias name.
511
dnssdAddAlias(const void *key, /* I - Key */
512
const void *value, /* I - Value (domain) */
513
void *context) /* I - Unused */
515
char valueStr[1024], /* Domain string */
516
hostname[1024], /* Complete hostname */
517
*hostptr; /* Pointer into hostname */
523
if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() &&
524
CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr),
525
kCFStringEncodingUTF8))
527
snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr);
528
hostptr = hostname + strlen(hostname) - 1;
530
*hostptr = '\0'; /* Strip trailing dot */
533
DNSSDAlias = cupsArrayNew(NULL, NULL);
535
cupsdAddAlias(DNSSDAlias, hostname);
536
cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s",
540
cupsdLogMessage(CUPSD_LOG_ERROR,
541
"Bad Back to My Mac domain in dynamic store!");
543
# endif /* __APPLE__ */
547
* 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
550
static cupsd_txt_t /* O - TXT record */
552
cupsd_printer_t *p, /* I - Printer information */
553
int for_lpd) /* I - 1 = LPD, 0 = IPP */
555
int i, /* Looping var */
556
count; /* Count of key/value pairs */
557
char admin_hostname[256], /* .local hostname for admin page */
558
adminurl_str[256], /* URL for the admin page */
559
type_str[32], /* Type to string buffer */
560
state_str[32], /* State to string buffer */
561
rp_str[1024], /* Queue name string buffer */
562
air_str[1024], /* auth-info-required string buffer */
563
*keyvalue[32][2]; /* Table of key/value pairs */
564
cupsd_txt_t txt; /* TXT record */
568
* Load up the key value pairs...
573
if (!for_lpd || (BrowseLocalProtocols & BROWSE_LPD))
575
keyvalue[count ][0] = "txtvers";
576
keyvalue[count++][1] = "1";
578
keyvalue[count ][0] = "qtotal";
579
keyvalue[count++][1] = "1";
581
keyvalue[count ][0] = "rp";
582
keyvalue[count++][1] = rp_str;
584
strlcpy(rp_str, p->name, sizeof(rp_str));
586
snprintf(rp_str, sizeof(rp_str), "%s/%s",
587
(p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
590
keyvalue[count ][0] = "ty";
591
keyvalue[count++][1] = p->make_model ? p->make_model : "Unknown";
593
if (strstr(DNSSDHostName, ".local"))
594
strlcpy(admin_hostname, DNSSDHostName, sizeof(admin_hostname));
596
snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.",
598
httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
603
# endif /* HAVE_SSL */
604
NULL, admin_hostname, DNSSDPort, "/%s/%s",
605
(p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
607
keyvalue[count ][0] = "adminurl";
608
keyvalue[count++][1] = adminurl_str;
612
keyvalue[count ][0] = "note";
613
keyvalue[count++][1] = p->location;
616
keyvalue[count ][0] = "priority";
617
keyvalue[count++][1] = for_lpd ? "100" : "0";
619
keyvalue[count ][0] = "product";
620
keyvalue[count++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown";
622
keyvalue[count ][0] = "pdl";
623
keyvalue[count++][1] = p->pdl ? p->pdl : "application/postscript";
625
/* iOS 6 does not accept this printer as AirPrint printer if there is
626
no URF txt record or "URF=none", "DM3" is the minimum needed found
628
keyvalue[count ][0] = "URF";
629
keyvalue[count++][1] = "DM3";
631
if (get_auth_info_required(p, air_str, sizeof(air_str)))
633
keyvalue[count ][0] = "air";
634
keyvalue[count++][1] = air_str;
637
keyvalue[count ][0] = "UUID";
638
keyvalue[count++][1] = p->uuid + 9;
641
keyvalue[count ][0] = "TLS";
642
keyvalue[count++][1] = "1.2";
643
#endif /* HAVE_SSL */
645
if (p->type & CUPS_PRINTER_FAX)
647
keyvalue[count ][0] = "Fax";
648
keyvalue[count++][1] = "T";
649
keyvalue[count ][0] = "rfo";
650
keyvalue[count++][1] = rp_str;
653
if (p->type & CUPS_PRINTER_COLOR)
655
keyvalue[count ][0] = "Color";
656
keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F";
659
if (p->type & CUPS_PRINTER_DUPLEX)
661
keyvalue[count ][0] = "Duplex";
662
keyvalue[count++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F";
665
if (p->type & CUPS_PRINTER_STAPLE)
667
keyvalue[count ][0] = "Staple";
668
keyvalue[count++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F";
671
if (p->type & CUPS_PRINTER_COPIES)
673
keyvalue[count ][0] = "Copies";
674
keyvalue[count++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F";
677
if (p->type & CUPS_PRINTER_COLLATE)
679
keyvalue[count ][0] = "Collate";
680
keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F";
683
if (p->type & CUPS_PRINTER_PUNCH)
685
keyvalue[count ][0] = "Punch";
686
keyvalue[count++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F";
689
if (p->type & CUPS_PRINTER_BIND)
691
keyvalue[count ][0] = "Bind";
692
keyvalue[count++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F";
695
if (p->type & CUPS_PRINTER_SORT)
697
keyvalue[count ][0] = "Sort";
698
keyvalue[count++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F";
701
if (p->type & CUPS_PRINTER_MFP)
703
keyvalue[count ][0] = "Scan";
704
keyvalue[count++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F";
707
snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
708
snprintf(state_str, sizeof(state_str), "%d", p->state);
710
keyvalue[count ][0] = "printer-state";
711
keyvalue[count++][1] = state_str;
713
keyvalue[count ][0] = "printer-type";
714
keyvalue[count++][1] = type_str;
718
* Then pack them into a proper txt record...
722
TXTRecordCreate(&txt, 0, NULL);
724
for (i = 0; i < count; i ++)
726
size_t len = strlen(keyvalue[i][1]);
729
TXTRecordSetValue(&txt, keyvalue[i][0], (uint8_t)len, keyvalue[i][1]);
733
for (i = 0, txt = NULL; i < count; i ++)
734
txt = avahi_string_list_add_printf(txt, "%s=%s", keyvalue[i][0],
736
# endif /* HAVE_DNSSD */
743
* 'dnssdDeregisterInstance()' - Deregister a DNS-SD service instance.
747
dnssdDeregisterInstance(
748
cupsd_srv_t *srv) /* I - Service */
754
DNSServiceRefDeallocate(*srv);
756
# else /* HAVE_AVAHI */
757
avahi_threaded_poll_lock(DNSSDMaster);
758
avahi_entry_group_free(*srv);
759
avahi_threaded_poll_unlock(DNSSDMaster);
760
# endif /* HAVE_DNSSD */
767
* 'dnssdDeregisterPrinter()' - Deregister all services for a printer.
771
dnssdDeregisterPrinter(
772
cupsd_printer_t *p, /* I - Printer */
773
int clear_name) /* I - Clear the name? */
776
cupsdLogMessage(CUPSD_LOG_DEBUG2,
777
"dnssdDeregisterPrinter(p=%p(%s), clear_name=%d)", p, p->name,
782
dnssdDeregisterInstance(&p->ipp_srv);
786
dnssdDeregisterInstance(&p->ipps_srv);
787
# endif /* HAVE_SSL */
788
dnssdDeregisterInstance(&p->printer_srv);
789
# endif /* HAVE_DNSSD */
793
* Remove the printer from the array of DNS-SD printers but keep the
797
cupsArrayRemove(DNSSDPrinters, p);
800
* Optionally clear the service name...
804
cupsdClearString(&p->reg_name);
809
* 'dnssdErrorString()' - Return an error string for an error code.
812
static const char * /* O - Error message */
813
dnssdErrorString(int error) /* I - Error number */
818
case kDNSServiceErr_NoError :
822
case kDNSServiceErr_Unknown :
823
return ("Unknown error.");
825
case kDNSServiceErr_NoSuchName :
826
return ("Service not found.");
828
case kDNSServiceErr_NoMemory :
829
return ("Out of memory.");
831
case kDNSServiceErr_BadParam :
832
return ("Bad parameter.");
834
case kDNSServiceErr_BadReference :
835
return ("Bad service reference.");
837
case kDNSServiceErr_BadState :
838
return ("Bad state.");
840
case kDNSServiceErr_BadFlags :
841
return ("Bad flags.");
843
case kDNSServiceErr_Unsupported :
844
return ("Unsupported.");
846
case kDNSServiceErr_NotInitialized :
847
return ("Not initialized.");
849
case kDNSServiceErr_AlreadyRegistered :
850
return ("Already registered.");
852
case kDNSServiceErr_NameConflict :
853
return ("Name conflict.");
855
case kDNSServiceErr_Invalid :
856
return ("Invalid name.");
858
case kDNSServiceErr_Firewall :
859
return ("Firewall prevents registration.");
861
case kDNSServiceErr_Incompatible :
862
return ("Client library incompatible.");
864
case kDNSServiceErr_BadInterfaceIndex :
865
return ("Bad interface index.");
867
case kDNSServiceErr_Refused :
868
return ("Server prevents registration.");
870
case kDNSServiceErr_NoSuchRecord :
871
return ("Record not found.");
873
case kDNSServiceErr_NoAuth :
874
return ("Authentication required.");
876
case kDNSServiceErr_NoSuchKey :
877
return ("Encryption key not found.");
879
case kDNSServiceErr_NATTraversal :
880
return ("Unable to traverse NAT boundary.");
882
case kDNSServiceErr_DoubleNAT :
883
return ("Unable to traverse double-NAT boundary.");
885
case kDNSServiceErr_BadTime :
886
return ("Bad system time.");
888
case kDNSServiceErr_BadSig :
889
return ("Bad signature.");
891
case kDNSServiceErr_BadKey :
892
return ("Bad encryption key.");
894
case kDNSServiceErr_Transient :
895
return ("Transient error occurred - please try again.");
897
case kDNSServiceErr_ServiceNotRunning :
898
return ("Server not running.");
900
case kDNSServiceErr_NATPortMappingUnsupported :
901
return ("NAT doesn't support NAT-PMP or UPnP.");
903
case kDNSServiceErr_NATPortMappingDisabled :
904
return ("NAT supports NAT-PNP or UPnP but it is disabled.");
906
case kDNSServiceErr_NoRouter :
907
return ("No Internet/default router configured.");
909
case kDNSServiceErr_PollingMode :
910
return ("Service polling mode error.");
912
case kDNSServiceErr_Timeout :
913
return ("Service timeout.");
916
# else /* HAVE_AVAHI */
917
return (avahi_strerror(error));
918
# endif /* HAVE_DNSSD */
923
* 'dnssdRegisterCallback()' - Free a TXT record.
927
dnssdFreeTxtRecord(cupsd_txt_t *txt) /* I - TXT record */
930
TXTRecordDeallocate(txt);
932
# else /* HAVE_AVAHI */
933
avahi_string_list_free(*txt);
935
# endif /* HAVE_DNSSD */
940
* 'dnssdRegisterCallback()' - DNSServiceRegister callback.
945
dnssdRegisterCallback(
946
DNSServiceRef sdRef, /* I - DNS Service reference */
947
DNSServiceFlags flags, /* I - Reserved for future use */
948
DNSServiceErrorType errorCode, /* I - Error code */
949
const char *name, /* I - Service name */
950
const char *regtype, /* I - Service type */
951
const char *domain, /* I - Domain. ".local" for now */
952
void *context) /* I - Printer */
954
cupsd_printer_t *p = (cupsd_printer_t *)context;
955
/* Current printer */
962
cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)",
963
name, regtype, p ? p->name : "Web Interface",
964
p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
968
cupsdLogMessage(CUPSD_LOG_ERROR,
969
"DNSServiceRegister failed with error %d", (int)errorCode);
972
else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name)))
974
cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"",
977
cupsArrayRemove(DNSSDPrinters, p);
978
cupsdSetString(&p->reg_name, name);
979
cupsArrayAdd(DNSSDPrinters, p);
981
LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
985
# else /* HAVE_AVAHI */
987
dnssdRegisterCallback(
988
AvahiEntryGroup *srv, /* I - Service */
989
AvahiEntryGroupState state, /* I - Registration state */
990
void *context) /* I - Printer */
992
cupsd_printer_t *p = (cupsd_printer_t *)context;
993
/* Current printer */
995
cupsdLogMessage(CUPSD_LOG_DEBUG2,
996
"dnssdRegisterCallback(srv=%p, state=%d, context=%p) "
997
"for %s (%s)", srv, state, context,
998
p ? p->name : "Web Interface",
999
p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
1001
/* TODO: Handle collisions with avahi_alternate_service_name(p->reg_name)? */
1003
# endif /* HAVE_DNSSD */
1007
* 'dnssdRegisterInstance()' - Register an instance of a printer service.
1010
static int /* O - 1 on success, 0 on failure */
1011
dnssdRegisterInstance(
1012
cupsd_srv_t *srv, /* O - Service */
1013
cupsd_printer_t *p, /* I - Printer */
1014
char *name, /* I - DNS-SD service name */
1015
const char *type, /* I - DNS-SD service type */
1016
const char *subtypes, /* I - Subtypes to register or NULL */
1017
int port, /* I - Port number or 0 */
1018
cupsd_txt_t *txt, /* I - TXT record */
1019
int commit) /* I - Commit registration? */
1021
char temp[256], /* Temporary string */
1022
*ptr; /* Pointer into string */
1023
int error; /* Any error */
1026
cupsdLogMessage(CUPSD_LOG_DEBUG,
1027
"Registering \"%s\" with DNS-SD type \"%s\".", name, type);
1032
* Assign the correct pointer for "srv"...
1036
if (!strcmp(type, "_printer._tcp"))
1037
srv = &p->printer_srv; /* Target LPD service */
1039
else if (!strcmp(type, "_ipps._tcp"))
1040
srv = &p->ipps_srv; /* Target IPPS service */
1041
# endif /* HAVE_SSL */
1043
srv = &p->ipp_srv; /* Target IPP service */
1045
# else /* HAVE_AVAHI */
1046
srv = &p->ipp_srv; /* Target service group */
1047
# endif /* HAVE_DNSSD */
1053
# else /* HAVE_AVAHI */
1054
avahi_threaded_poll_lock(DNSSDMaster);
1057
*srv = avahi_entry_group_new(DNSSDClient, dnssdRegisterCallback, NULL);
1060
avahi_threaded_poll_unlock(DNSSDMaster);
1062
cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s",
1063
name, dnssdErrorString(avahi_client_errno(DNSSDClient)));
1066
# endif /* HAVE_DNSSD */
1069
* Make sure the name is <= 63 octets, and when we truncate be sure to
1070
* properly truncate any UTF-8 characters...
1073
ptr = name + strlen(name);
1074
while ((ptr - name) > 63)
1080
while (ptr > name && (*ptr & 0xc0) == 0x80);
1087
* Register the service...
1092
snprintf(temp, sizeof(temp), "%s,%s", type, subtypes);
1094
strlcpy(temp, type, sizeof(temp));
1097
error = DNSServiceRegister(srv, kDNSServiceFlagsShareConnection,
1098
0, name, temp, NULL, NULL, htons(port),
1099
txt ? TXTRecordGetLength(txt) : 0,
1100
txt ? TXTRecordGetBytesPtr(txt) : NULL,
1101
dnssdRegisterCallback, p);
1103
# else /* HAVE_AVAHI */
1106
AvahiStringList *temptxt;
1107
for (temptxt = *txt; temptxt; temptxt = temptxt->next)
1108
cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS_SD \"%s\" %s", name, temptxt->text);
1111
error = avahi_entry_group_add_service_strlst(*srv, AVAHI_IF_UNSPEC,
1112
AVAHI_PROTO_UNSPEC, 0, name,
1113
type, NULL, NULL, port,
1116
cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD service add for \"%s\" failed.",
1119
if (!error && subtypes)
1122
* Register all of the subtypes...
1125
char *start, /* Start of subtype */
1126
subtype[256]; /* Subtype string */
1128
strlcpy(temp, subtypes, sizeof(temp));
1130
for (start = temp; *start; start = ptr)
1133
* Skip leading whitespace...
1136
while (*start && isspace(*start & 255))
1140
* Grab everything up to the next comma or the end of the string...
1143
for (ptr = start; *ptr && *ptr != ','; ptr ++);
1152
* Register the subtype...
1155
snprintf(subtype, sizeof(subtype), "%s._sub.%s", start, type);
1157
error = avahi_entry_group_add_service_subtype(*srv, AVAHI_IF_UNSPEC,
1158
AVAHI_PROTO_UNSPEC, 0,
1159
name, type, NULL, subtype);
1162
cupsdLogMessage(CUPSD_LOG_DEBUG,
1163
"DNS-SD subtype %s registration for \"%s\" failed." ,
1170
if (!error && commit)
1172
if ((error = avahi_entry_group_commit(*srv)) != 0)
1173
cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD commit of \"%s\" failed.",
1177
avahi_threaded_poll_unlock(DNSSDMaster);
1178
# endif /* HAVE_DNSSD */
1182
cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s",
1183
name, dnssdErrorString(error));
1184
cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD type: %s", type);
1186
cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD sub-types: %s", subtypes);
1194
* 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
1195
* or update the broadcast contents.
1199
dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
1201
char name[256]; /* Service name */
1202
int printer_port; /* LPD port number */
1203
int status; /* Registration status */
1204
cupsd_txt_t ipp_txt, /* IPP(S) TXT record */
1205
printer_txt; /* LPD TXT record */
1207
cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
1208
!p->ipp_srv ? "new" : "update");
1211
* Remove the current registrations if we have them and then return if
1212
* per-printer sharing was just disabled...
1215
dnssdDeregisterPrinter(p, 0);
1221
* Set the registered name as needed; the registered name takes the form of
1222
* "<printer-info> @ <computer name>"...
1227
if (p->info && strlen(p->info) > 0)
1229
if (DNSSDComputerName)
1230
snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
1232
strlcpy(name, p->info, sizeof(name));
1234
else if (DNSSDComputerName)
1235
snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
1237
strlcpy(name, p->name, sizeof(name));
1240
strlcpy(name, p->reg_name, sizeof(name));
1243
* Register IPP and LPD...
1245
* We always must register the "_printer" service type in order to reserve
1246
* our name, but use port number 0 if we haven't actually configured cups-lpd
1247
* to share via LPD...
1250
ipp_txt = dnssdBuildTxtRecord(p, 0);
1251
printer_txt = dnssdBuildTxtRecord(p, 1);
1253
if (BrowseLocalProtocols & BROWSE_LPD)
1258
status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL,
1259
printer_port, &printer_txt, 0);
1263
dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes,
1264
DNSSDPort, &ipp_txt, 0);
1265
# endif /* HAVE_SSL */
1270
* Use the "_fax-ipp" service type for fax queues, otherwise use "_ipp"...
1273
if (p->type & CUPS_PRINTER_FAX)
1274
status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp",
1275
DNSSDSubTypes, DNSSDPort, &ipp_txt, 1);
1277
status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes,
1278
DNSSDPort, &ipp_txt, 1);
1281
dnssdFreeTxtRecord(&ipp_txt);
1282
dnssdFreeTxtRecord(&printer_txt);
1287
* Save the registered name and add the printer to the array of DNS-SD
1291
cupsdSetString(&p->reg_name, name);
1292
cupsArrayAdd(DNSSDPrinters, p);
1297
* Registration failed for this printer...
1300
dnssdDeregisterInstance(&p->ipp_srv);
1304
dnssdDeregisterInstance(&p->ipps_srv);
1305
# endif /* HAVE_SSL */
1306
dnssdDeregisterInstance(&p->printer_srv);
1307
# endif /* HAVE_DNSSD */
1313
* 'dnssdStop()' - Stop all DNS-SD registrations.
1319
cupsd_printer_t *p; /* Current printer */
1323
* De-register the individual printers
1326
for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
1328
p = (cupsd_printer_t *)cupsArrayNext(Printers))
1329
dnssdDeregisterPrinter(p, 1);
1332
* Shutdown the rest of the service refs...
1335
dnssdDeregisterInstance(&WebIFSrv);
1338
cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDMaster));
1340
DNSServiceRefDeallocate(DNSSDMaster);
1343
# else /* HAVE_AVAHI */
1344
avahi_threaded_poll_stop(DNSSDMaster);
1346
avahi_client_free(DNSSDClient);
1349
avahi_threaded_poll_free(DNSSDMaster);
1351
# endif /* HAVE_DNSSD */
1353
cupsArrayDelete(DNSSDPrinters);
1354
DNSSDPrinters = NULL;
1362
* 'dnssdUpdate()' - Handle DNS-SD queries.
1368
DNSServiceErrorType sdErr; /* Service discovery error */
1371
if ((sdErr = DNSServiceProcessResult(DNSSDMaster)) != kDNSServiceErr_NoError)
1373
cupsdLogMessage(CUPSD_LOG_ERROR,
1374
"DNS Service Discovery registration error %d!",
1379
# endif /* HAVE_DNSSD */
1383
* 'get_auth_info_required()' - Get the auth-info-required value to advertise.
1386
static char * /* O - String or NULL if none */
1387
get_auth_info_required(
1388
cupsd_printer_t *p, /* I - Printer */
1389
char *buffer, /* I - Value buffer */
1390
size_t bufsize) /* I - Size of value buffer */
1392
cupsd_location_t *auth; /* Pointer to authentication element */
1393
char resource[1024]; /* Printer/class resource path */
1397
* If auth-info-required is set for this printer, return that...
1400
if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none"))
1402
int i; /* Looping var */
1403
char *bufptr; /* Pointer into buffer */
1405
for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++)
1407
if (bufptr >= (buffer + bufsize - 2))
1413
strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer));
1414
bufptr += strlen(bufptr);
1421
* Figure out the authentication data requirements to advertise...
1424
if (p->type & CUPS_PRINTER_CLASS)
1425
snprintf(resource, sizeof(resource), "/classes/%s", p->name);
1427
snprintf(resource, sizeof(resource), "/printers/%s", p->name);
1429
if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
1430
auth->type == CUPSD_AUTH_NONE)
1431
auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
1435
int auth_type; /* Authentication type */
1437
if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
1438
auth_type = cupsdDefaultAuthType();
1442
case CUPSD_AUTH_NONE :
1445
case CUPSD_AUTH_NEGOTIATE :
1446
strlcpy(buffer, "negotiate", bufsize);
1450
strlcpy(buffer, "username,password", bufsize);
1459
#endif /* HAVE_DNSSD || HAVE_AVAHI */
1464
* 'get_hostconfig()' - Get an /etc/hostconfig service setting.
1467
static int /* O - 1 for YES or AUTOMATIC, 0 for NO */
1468
get_hostconfig(const char *name) /* I - Name of service */
1470
cups_file_t *fp; /* Hostconfig file */
1471
char line[1024], /* Line from file */
1472
*ptr; /* Pointer to value */
1473
int state = 1; /* State of service */
1477
* Try opening the /etc/hostconfig file; if we can't open it, assume that
1478
* the service is enabled/auto.
1481
if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL)
1484
* Read lines from the file until we find the service...
1487
while (cupsFileGets(fp, line, sizeof(line)))
1489
if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL)
1494
if (!_cups_strcasecmp(line, name))
1497
* Found the service, see if it is set to "-NO-"...
1500
if (!_cups_strncasecmp(ptr, "-NO-", 4))
1511
#endif /* __APPLE__ */
1515
* 'update_lpd()' - Update the LPD configuration as needed.
1519
update_lpd(int onoff) /* - 1 = turn on, 0 = turn off */
1526
* Allow /etc/hostconfig CUPS_LPD service setting to override cupsd.conf
1527
* setting for backwards-compatibility.
1530
if (onoff && !get_hostconfig("CUPS_LPD"))
1532
#endif /* __APPLE__ */
1534
if (!strncmp(LPDConfigFile, "xinetd:///", 10))
1537
* Enable/disable LPD via the xinetd.d config file for cups-lpd...
1540
char newfile[1024]; /* New cups-lpd.N file */
1541
cups_file_t *ofp, /* Original file pointer */
1542
*nfp; /* New file pointer */
1543
char line[1024]; /* Line from file */
1546
snprintf(newfile, sizeof(newfile), "%s.N", LPDConfigFile + 9);
1548
if ((ofp = cupsFileOpen(LPDConfigFile + 9, "r")) == NULL)
1550
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s",
1551
LPDConfigFile + 9, strerror(errno));
1555
if ((nfp = cupsFileOpen(newfile, "w")) == NULL)
1557
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s",
1558
newfile, strerror(errno));
1564
* Copy all of the lines from the cups-lpd file...
1567
while (cupsFileGets(ofp, line, sizeof(line)))
1571
cupsFilePrintf(nfp, "%s\n", line);
1572
snprintf(line, sizeof(line), "\tdisable = %s",
1573
onoff ? "no" : "yes");
1575
else if (!strstr(line, "disable ="))
1576
cupsFilePrintf(nfp, "%s\n", line);
1581
rename(newfile, LPDConfigFile + 9);
1584
else if (!strncmp(LPDConfigFile, "launchd:///", 11))
1587
* Enable/disable LPD via the launchctl command...
1590
char *argv[5], /* Arguments for command */
1591
*envp[MAX_ENV]; /* Environment for command */
1592
int pid; /* Process ID */
1595
cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
1596
argv[0] = (char *)"launchctl";
1597
argv[1] = (char *)(onoff ? "load" : "unload");
1598
argv[2] = (char *)"-w";
1599
argv[3] = LPDConfigFile + 10;
1602
cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1,
1605
#endif /* __APPLE__ */
1607
cupsdLogMessage(CUPSD_LOG_INFO, "Unknown LPDConfigFile scheme!");
1612
* 'update_smb()' - Update the SMB configuration as needed.
1616
update_smb(int onoff) /* I - 1 = turn on, 0 = turn off */
1621
if (!strncmp(SMBConfigFile, "samba:///", 9))
1624
* Enable/disable SMB via the specified smb.conf config file...
1627
char newfile[1024]; /* New smb.conf.N file */
1628
cups_file_t *ofp, /* Original file pointer */
1629
*nfp; /* New file pointer */
1630
char line[1024]; /* Line from file */
1631
int in_printers; /* In [printers] section? */
1634
snprintf(newfile, sizeof(newfile), "%s.N", SMBConfigFile + 8);
1636
if ((ofp = cupsFileOpen(SMBConfigFile + 8, "r")) == NULL)
1638
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s",
1639
SMBConfigFile + 8, strerror(errno));
1643
if ((nfp = cupsFileOpen(newfile, "w")) == NULL)
1645
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s",
1646
newfile, strerror(errno));
1652
* Copy all of the lines from the smb.conf file...
1657
while (cupsFileGets(ofp, line, sizeof(line)))
1659
if (in_printers && strstr(line, "printable ="))
1660
snprintf(line, sizeof(line), " printable = %s",
1661
onoff ? "yes" : "no");
1663
cupsFilePrintf(nfp, "%s\n", line);
1666
in_printers = !strcmp(line, "[printers]");
1671
rename(newfile, SMBConfigFile + 8);
1674
cupsdLogMessage(CUPSD_LOG_INFO, "Unknown SMBConfigFile scheme!");
1679
* End of "$Id: dirsvc.c 11193 2013-07-26 03:12:37Z msweet $".