]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/dirsvc.c
0e5e3e6958dff88263307626be47ef221212b184
[thirdparty/cups.git] / scheduler / dirsvc.c
1 /*
2 * "$Id: dirsvc.c 7933 2008-09-11 00:44:58Z mike $"
3 *
4 * Directory services routines for the CUPS scheduler.
5 *
6 * Copyright 2007-2012 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
8 *
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/".
14 *
15 * Contents:
16 *
17 * cupsdDeregisterPrinter() - Stop sending broadcast information for a local
18 * printer and remove any pending references to
19 * remote printers.
20 * cupsdRegisterPrinter() - Start sending broadcast information for a
21 * printer or update the broadcast contents.
22 * cupsdStartBrowsing() - Start sending and receiving broadcast
23 * information.
24 * cupsdStopBrowsing() - Stop sending and receiving broadcast
25 * information.
26 * cupsdUpdateDNSSDName() - Update the computer name we use for
27 * browsing...
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.
44 */
45
46 /*
47 * Include necessary headers...
48 */
49
50 #include "cupsd.h"
51 #include <grp.h>
52
53 #if defined(HAVE_DNSSD) && defined(__APPLE__)
54 # include <nameser.h>
55 # include <CoreFoundation/CoreFoundation.h>
56 # include <SystemConfiguration/SystemConfiguration.h>
57 #endif /* HAVE_DNSSD && __APPLE__ */
58
59
60 /*
61 * Local functions...
62 */
63
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 */
68 #ifdef __APPLE__
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);
73
74
75 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
76 # ifdef __APPLE__
77 static void dnssdAddAlias(const void *key, const void *value,
78 void *context);
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,
83 int clear_name);
84 static const char *dnssdErrorString(int error);
85 static void dnssdFreeTxtRecord(cupsd_txt_t *txt);
86 # ifdef HAVE_DNSSD
87 static void dnssdRegisterCallback(DNSServiceRef sdRef,
88 DNSServiceFlags flags,
89 DNSServiceErrorType errorCode,
90 const char *name,
91 const char *regtype,
92 const char *domain,
93 void *context);
94 # else
95 static void dnssdRegisterCallback(AvahiEntryGroup *p,
96 AvahiEntryGroupState state,
97 void *context);
98 # endif /* HAVE_DNSSD */
99 static int dnssdRegisterInstance(cupsd_srv_t *srv,
100 cupsd_printer_t *p,
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);
106 # ifdef HAVE_DNSSD
107 static void dnssdUpdate(void);
108 # endif /* HAVE_DNSSD */
109 #endif /* HAVE_DNSSD || HAVE_AVAHI */
110
111
112 /*
113 * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
114 * local printer and remove any pending
115 * references to remote printers.
116 */
117
118 void
119 cupsdDeregisterPrinter(
120 cupsd_printer_t *p, /* I - Printer to register */
121 int removeit) /* I - Printer being permanently removed */
122 {
123 /*
124 * Only deregister if browsing is enabled and it's a local printer...
125 */
126
127 cupsdLogMessage(CUPSD_LOG_DEBUG,
128 "cupsdDeregisterPrinter(p=%p(%s), removeit=%d)", p, p->name,
129 removeit);
130
131 if (!Browsing || !p->shared ||
132 (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
133 return;
134
135 /*
136 * Announce the deletion...
137 */
138
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 */
143 }
144
145
146 /*
147 * 'cupsdRegisterPrinter()' - Start sending broadcast information for a
148 * printer or update the broadcast contents.
149 */
150
151 void
152 cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
153 {
154 cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p,
155 p->name);
156
157 if (!Browsing || !BrowseLocalProtocols ||
158 (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
159 return;
160
161 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
162 if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster)
163 dnssdRegisterPrinter(p);
164 #endif /* HAVE_DNSSD || HAVE_AVAHI */
165 }
166
167
168 /*
169 * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
170 */
171
172 void
173 cupsdStartBrowsing(void)
174 {
175 cupsd_printer_t *p; /* Current printer */
176
177
178 if (!Browsing || !BrowseLocalProtocols)
179 return;
180
181 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
182 if (BrowseLocalProtocols & BROWSE_DNSSD)
183 {
184 cupsd_listener_t *lis; /* Current listening socket */
185 # ifdef HAVE_DNSSD
186 DNSServiceErrorType error; /* Error from service creation */
187
188 /*
189 * First create a "master" connection for all registrations...
190 */
191
192 if ((error = DNSServiceCreateConnection(&DNSSDMaster))
193 != kDNSServiceErr_NoError)
194 {
195 cupsdLogMessage(CUPSD_LOG_ERROR,
196 "Unable to create master DNS-SD reference: %d", error);
197
198 if (FatalErrors & CUPSD_FATAL_BROWSE)
199 cupsdEndProcess(getpid(), 0);
200 }
201 else
202 {
203 /*
204 * Add the master connection to the select list...
205 */
206
207 int fd = DNSServiceRefSockFD(DNSSDMaster);
208
209 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
210
211 cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
212 }
213
214 # else /* HAVE_AVAHI */
215 if ((DNSSDMaster = avahi_threaded_poll_new()) == NULL)
216 {
217 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create DNS-SD thread.");
218
219 if (FatalErrors & CUPSD_FATAL_BROWSE)
220 cupsdEndProcess(getpid(), 0);
221 }
222 else
223 {
224 int error; /* Error code, if any */
225
226 DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), 0,
227 NULL, NULL, &error);
228
229 if (DNSSDClient == NULL)
230 {
231 cupsdLogMessage(CUPSD_LOG_ERROR,
232 "Unable to communicate with avahi-daemon: %s",
233 dnssdErrorString(error));
234
235 if (FatalErrors & CUPSD_FATAL_BROWSE)
236 cupsdEndProcess(getpid(), 0);
237
238 avahi_threaded_poll_free(DNSSDMaster);
239 DNSSDMaster = NULL;
240 }
241 else
242 avahi_threaded_poll_start(DNSSDMaster);
243 }
244 # endif /* HAVE_DNSSD */
245
246 /*
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
249 * Bonjour...
250 */
251
252 DNSSDPort = 0;
253
254 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
255 lis;
256 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
257 {
258 if (httpAddrLocalhost(&(lis->address)))
259 continue;
260
261 DNSSDPort = _httpAddrPort(&(lis->address));
262 break;
263 }
264
265 /*
266 * Set the computer name and register the web interface...
267 */
268
269 cupsdUpdateDNSSDName();
270 }
271 #endif /* HAVE_DNSSD || HAVE_AVAHI */
272
273 /*
274 * Enable LPD and SMB printer sharing as needed through external programs...
275 */
276
277 if (BrowseLocalProtocols & BROWSE_LPD)
278 update_lpd(1);
279
280 if (BrowseLocalProtocols & BROWSE_SMB)
281 update_smb(1);
282
283 /*
284 * Register the individual printers
285 */
286
287 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
288 p;
289 p = (cupsd_printer_t *)cupsArrayNext(Printers))
290 if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
291 cupsdRegisterPrinter(p);
292 }
293
294
295 /*
296 * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information.
297 */
298
299 void
300 cupsdStopBrowsing(void)
301 {
302 cupsd_printer_t *p; /* Current printer */
303
304
305 if (!Browsing || !BrowseLocalProtocols)
306 return;
307
308 /*
309 * De-register the individual printers
310 */
311
312 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
313 p;
314 p = (cupsd_printer_t *)cupsArrayNext(Printers))
315 if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
316 cupsdDeregisterPrinter(p, 1);
317
318 /*
319 * Shut down browsing sockets...
320 */
321
322 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
323 if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster)
324 dnssdStop();
325 #endif /* HAVE_DNSSD || HAVE_AVAHI */
326
327 /*
328 * Disable LPD and SMB printer sharing as needed through external programs...
329 */
330
331 if (BrowseLocalProtocols & BROWSE_LPD)
332 update_lpd(0);
333
334 if (BrowseLocalProtocols & BROWSE_SMB)
335 update_smb(0);
336 }
337
338
339 #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
340 /*
341 * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
342 */
343
344 void
345 cupsdUpdateDNSSDName(void)
346 {
347 char webif[1024]; /* Web interface share name */
348 # ifdef __APPLE__
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__ */
355
356
357 /*
358 * Only share the web interface and printers when non-local listening is
359 * enabled...
360 */
361
362 if (!DNSSDPort)
363 return;
364
365 /*
366 * Get the computer name as a c-string...
367 */
368
369 # ifdef __APPLE__
370 sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
371
372 if (sc)
373 {
374 /*
375 * Get the computer name from the dynamic store...
376 */
377
378 cupsdClearString(&DNSSDComputerName);
379
380 if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL)
381 {
382 if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
383 kCFStringEncodingUTF8))
384 {
385 cupsdLogMessage(CUPSD_LOG_DEBUG,
386 "Dynamic store computer name is \"%s\".", nameBuffer);
387 cupsdSetString(&DNSSDComputerName, nameBuffer);
388 }
389
390 CFRelease(nameRef);
391 }
392
393 if (!DNSSDComputerName)
394 {
395 /*
396 * Use the ServerName instead...
397 */
398
399 cupsdLogMessage(CUPSD_LOG_DEBUG,
400 "Using ServerName \"%s\" as computer name.", ServerName);
401 cupsdSetString(&DNSSDComputerName, ServerName);
402 }
403
404 /*
405 * Get the local hostname from the dynamic store...
406 */
407
408 cupsdClearString(&DNSSDHostName);
409
410 if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL)
411 {
412 if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
413 kCFStringEncodingUTF8))
414 {
415 cupsdLogMessage(CUPSD_LOG_DEBUG,
416 "Dynamic store host name is \"%s\".", nameBuffer);
417 cupsdSetString(&DNSSDHostName, nameBuffer);
418 }
419
420 CFRelease(nameRef);
421 }
422
423 if (!DNSSDHostName)
424 {
425 /*
426 * Use the ServerName instead...
427 */
428
429 cupsdLogMessage(CUPSD_LOG_DEBUG,
430 "Using ServerName \"%s\" as host name.", ServerName);
431 cupsdSetString(&DNSSDHostName, ServerName);
432 }
433
434 /*
435 * Get any Back-to-My-Mac domains and add them as aliases...
436 */
437
438 cupsdFreeAliases(DNSSDAlias);
439 DNSSDAlias = NULL;
440
441 btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac"));
442 if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID())
443 {
444 cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.",
445 (int)CFDictionaryGetCount(btmm));
446 CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL);
447 }
448 else if (btmm)
449 cupsdLogMessage(CUPSD_LOG_ERROR,
450 "Bad Back to My Mac data in dynamic store!");
451 else
452 cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add.");
453
454 if (btmm)
455 CFRelease(btmm);
456
457 CFRelease(sc);
458 }
459 else
460 # endif /* __APPLE__ */
461 # ifdef HAVE_AVAHI
462 {
463 const char *host_name = avahi_client_get_host_name(DNSSDClient);
464 const char *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient);
465
466 cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName);
467
468 if (host_fqdn)
469 cupsdSetString(&DNSSDHostName, host_fqdn);
470 else if (strchr(ServerName, '.'))
471 cupsdSetString(&DNSSDHostName, ServerName);
472 else
473 cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName);
474 }
475 # else /* HAVE_DNSSD */
476 {
477 cupsdSetString(&DNSSDComputerName, ServerName);
478
479 if (strchr(ServerName, '.'))
480 cupsdSetString(&DNSSDHostName, ServerName);
481 else
482 cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName);
483 }
484 # endif /* HAVE_AVAHI */
485
486 /*
487 * Then (re)register the web interface if enabled...
488 */
489
490 if (BrowseWebIF)
491 {
492 if (DNSSDComputerName)
493 snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName);
494 else
495 strlcpy(webif, "CUPS", sizeof(webif));
496
497 dnssdDeregisterInstance(&WebIFSrv);
498 dnssdRegisterInstance(&WebIFSrv, NULL, webif, "_http._tcp", "_printer",
499 DNSSDPort, NULL, 1);
500 }
501 }
502
503
504 # ifdef __APPLE__
505 /*
506 * 'dnssdAddAlias()' - Add a DNS-SD alias name.
507 */
508
509 static void
510 dnssdAddAlias(const void *key, /* I - Key */
511 const void *value, /* I - Value (domain) */
512 void *context) /* I - Unused */
513 {
514 char valueStr[1024], /* Domain string */
515 hostname[1024], /* Complete hostname */
516 *hostptr; /* Pointer into hostname */
517
518
519 (void)key;
520 (void)context;
521
522 if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() &&
523 CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr),
524 kCFStringEncodingUTF8))
525 {
526 snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr);
527 hostptr = hostname + strlen(hostname) - 1;
528 if (*hostptr == '.')
529 *hostptr = '\0'; /* Strip trailing dot */
530
531 if (!DNSSDAlias)
532 DNSSDAlias = cupsArrayNew(NULL, NULL);
533
534 cupsdAddAlias(DNSSDAlias, hostname);
535 cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s",
536 hostname);
537 }
538 else
539 cupsdLogMessage(CUPSD_LOG_ERROR,
540 "Bad Back to My Mac domain in dynamic store!");
541 }
542 # endif /* __APPLE__ */
543
544
545 /*
546 * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
547 */
548
549 static cupsd_txt_t /* O - TXT record */
550 dnssdBuildTxtRecord(
551 cupsd_printer_t *p, /* I - Printer information */
552 int for_lpd) /* I - 1 = LPD, 0 = IPP */
553 {
554 int i, /* Looping var */
555 count; /* Count of key/value pairs */
556 char admin_hostname[256], /* .local hostname for admin page */
557 adminurl_str[256], /* URL for the admin page */
558 type_str[32], /* Type to string buffer */
559 state_str[32], /* State to string buffer */
560 rp_str[1024], /* Queue name string buffer */
561 air_str[1024], /* auth-info-required string buffer */
562 *keyvalue[32][2]; /* Table of key/value pairs */
563 cupsd_txt_t txt; /* TXT record */
564
565
566 /*
567 * Load up the key value pairs...
568 */
569
570 count = 0;
571
572 if (!for_lpd || (BrowseLocalProtocols & BROWSE_LPD))
573 {
574 keyvalue[count ][0] = "txtvers";
575 keyvalue[count++][1] = "1";
576
577 keyvalue[count ][0] = "qtotal";
578 keyvalue[count++][1] = "1";
579
580 keyvalue[count ][0] = "rp";
581 keyvalue[count++][1] = rp_str;
582 if (for_lpd)
583 strlcpy(rp_str, p->name, sizeof(rp_str));
584 else
585 snprintf(rp_str, sizeof(rp_str), "%s/%s",
586 (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
587 p->name);
588
589 keyvalue[count ][0] = "ty";
590 keyvalue[count++][1] = p->make_model ? p->make_model : "Unknown";
591
592 if (strstr(DNSSDHostName, ".local"))
593 strlcpy(admin_hostname, DNSSDHostName, sizeof(admin_hostname));
594 else
595 snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.",
596 DNSSDHostName);
597 httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
598 # ifdef HAVE_SSL
599 "https",
600 # else
601 "http",
602 # endif /* HAVE_SSL */
603 NULL, admin_hostname, DNSSDPort, "/%s/%s",
604 (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
605 p->name);
606 keyvalue[count ][0] = "adminurl";
607 keyvalue[count++][1] = adminurl_str;
608
609 if (p->location)
610 {
611 keyvalue[count ][0] = "note";
612 keyvalue[count++][1] = p->location;
613 }
614
615 keyvalue[count ][0] = "priority";
616 keyvalue[count++][1] = for_lpd ? "100" : "0";
617
618 keyvalue[count ][0] = "product";
619 keyvalue[count++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown";
620
621 keyvalue[count ][0] = "pdl";
622 keyvalue[count++][1] = p->pdl ? p->pdl : "application/postscript";
623
624 if (get_auth_info_required(p, air_str, sizeof(air_str)))
625 {
626 keyvalue[count ][0] = "air";
627 keyvalue[count++][1] = air_str;
628 }
629
630 keyvalue[count ][0] = "UUID";
631 keyvalue[count++][1] = p->uuid + 9;
632
633 #ifdef HAVE_SSL
634 keyvalue[count ][0] = "TLS";
635 keyvalue[count++][1] = "1.2";
636 #endif /* HAVE_SSL */
637
638 if (p->type & CUPS_PRINTER_FAX)
639 {
640 keyvalue[count ][0] = "Fax";
641 keyvalue[count++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F";
642 }
643
644 if (p->type & CUPS_PRINTER_COLOR)
645 {
646 keyvalue[count ][0] = "Color";
647 keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F";
648 }
649
650 if (p->type & CUPS_PRINTER_DUPLEX)
651 {
652 keyvalue[count ][0] = "Duplex";
653 keyvalue[count++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F";
654 }
655
656 if (p->type & CUPS_PRINTER_STAPLE)
657 {
658 keyvalue[count ][0] = "Staple";
659 keyvalue[count++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F";
660 }
661
662 if (p->type & CUPS_PRINTER_COPIES)
663 {
664 keyvalue[count ][0] = "Copies";
665 keyvalue[count++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F";
666 }
667
668 if (p->type & CUPS_PRINTER_COLLATE)
669 {
670 keyvalue[count ][0] = "Collate";
671 keyvalue[count++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F";
672 }
673
674 if (p->type & CUPS_PRINTER_PUNCH)
675 {
676 keyvalue[count ][0] = "Punch";
677 keyvalue[count++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F";
678 }
679
680 if (p->type & CUPS_PRINTER_BIND)
681 {
682 keyvalue[count ][0] = "Bind";
683 keyvalue[count++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F";
684 }
685
686 if (p->type & CUPS_PRINTER_SORT)
687 {
688 keyvalue[count ][0] = "Sort";
689 keyvalue[count++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F";
690 }
691
692 if (p->type & CUPS_PRINTER_MFP)
693 {
694 keyvalue[count ][0] = "Scan";
695 keyvalue[count++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F";
696 }
697
698 snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
699 snprintf(state_str, sizeof(state_str), "%d", p->state);
700
701 keyvalue[count ][0] = "printer-state";
702 keyvalue[count++][1] = state_str;
703
704 keyvalue[count ][0] = "printer-type";
705 keyvalue[count++][1] = type_str;
706 }
707
708 /*
709 * Then pack them into a proper txt record...
710 */
711
712 # ifdef HAVE_DNSSD
713 TXTRecordCreate(&txt, 0, NULL);
714
715 for (i = 0; i < count; i ++)
716 {
717 size_t len = strlen(keyvalue[i][1]);
718
719 if (len < 256)
720 TXTRecordSetValue(&txt, keyvalue[i][0], (uint8_t)len, keyvalue[i][1]);
721 }
722
723 # else
724 for (i = 0, txt = NULL; i < count; i ++)
725 txt = avahi_string_list_add_printf(txt, "%s=%s", keyvalue[i][0],
726 keyvalue[i][1]);
727 # endif /* HAVE_DNSSD */
728
729 return (txt);
730 }
731
732
733 /*
734 * 'dnssdDeregisterInstance()' - Deregister a DNS-SD service instance.
735 */
736
737 static void
738 dnssdDeregisterInstance(
739 cupsd_srv_t *srv) /* I - Service */
740 {
741 if (!srv || !*srv)
742 return;
743
744 # ifdef HAVE_DNSSD
745 DNSServiceRefDeallocate(*srv);
746
747 # else /* HAVE_AVAHI */
748 avahi_threaded_poll_lock(DNSSDMaster);
749 avahi_entry_group_free(*srv);
750 avahi_threaded_poll_unlock(DNSSDMaster);
751 # endif /* HAVE_DNSSD */
752
753 *srv = NULL;
754 }
755
756
757 /*
758 * 'dnssdDeregisterPrinter()' - Deregister all services for a printer.
759 */
760
761 static void
762 dnssdDeregisterPrinter(
763 cupsd_printer_t *p, /* I - Printer */
764 int clear_name) /* I - Clear the name? */
765
766 {
767 cupsdLogMessage(CUPSD_LOG_DEBUG2,
768 "dnssdDeregisterPrinter(p=%p(%s), clear_name=%d)", p, p->name,
769 clear_name);
770
771 if (p->ipp_srv)
772 {
773 dnssdDeregisterInstance(&p->ipp_srv);
774
775 # ifdef HAVE_DNSSD
776 # ifdef HAVE_SSL
777 dnssdDeregisterInstance(&p->ipps_srv);
778 # endif /* HAVE_SSL */
779 dnssdDeregisterInstance(&p->printer_srv);
780 # endif /* HAVE_DNSSD */
781 }
782
783 /*
784 * Remove the printer from the array of DNS-SD printers but keep the
785 * registered name...
786 */
787
788 cupsArrayRemove(DNSSDPrinters, p);
789
790 /*
791 * Optionally clear the service name...
792 */
793
794 if (clear_name)
795 cupsdClearString(&p->reg_name);
796 }
797
798
799 /*
800 * 'dnssdErrorString()' - Return an error string for an error code.
801 */
802
803 static const char * /* O - Error message */
804 dnssdErrorString(int error) /* I - Error number */
805 {
806 # ifdef HAVE_DNSSD
807 switch (error)
808 {
809 case kDNSServiceErr_NoError :
810 return ("OK.");
811
812 default :
813 case kDNSServiceErr_Unknown :
814 return ("Unknown error.");
815
816 case kDNSServiceErr_NoSuchName :
817 return ("Service not found.");
818
819 case kDNSServiceErr_NoMemory :
820 return ("Out of memory.");
821
822 case kDNSServiceErr_BadParam :
823 return ("Bad parameter.");
824
825 case kDNSServiceErr_BadReference :
826 return ("Bad service reference.");
827
828 case kDNSServiceErr_BadState :
829 return ("Bad state.");
830
831 case kDNSServiceErr_BadFlags :
832 return ("Bad flags.");
833
834 case kDNSServiceErr_Unsupported :
835 return ("Unsupported.");
836
837 case kDNSServiceErr_NotInitialized :
838 return ("Not initialized.");
839
840 case kDNSServiceErr_AlreadyRegistered :
841 return ("Already registered.");
842
843 case kDNSServiceErr_NameConflict :
844 return ("Name conflict.");
845
846 case kDNSServiceErr_Invalid :
847 return ("Invalid name.");
848
849 case kDNSServiceErr_Firewall :
850 return ("Firewall prevents registration.");
851
852 case kDNSServiceErr_Incompatible :
853 return ("Client library incompatible.");
854
855 case kDNSServiceErr_BadInterfaceIndex :
856 return ("Bad interface index.");
857
858 case kDNSServiceErr_Refused :
859 return ("Server prevents registration.");
860
861 case kDNSServiceErr_NoSuchRecord :
862 return ("Record not found.");
863
864 case kDNSServiceErr_NoAuth :
865 return ("Authentication required.");
866
867 case kDNSServiceErr_NoSuchKey :
868 return ("Encryption key not found.");
869
870 case kDNSServiceErr_NATTraversal :
871 return ("Unable to traverse NAT boundary.");
872
873 case kDNSServiceErr_DoubleNAT :
874 return ("Unable to traverse double-NAT boundary.");
875
876 case kDNSServiceErr_BadTime :
877 return ("Bad system time.");
878
879 case kDNSServiceErr_BadSig :
880 return ("Bad signature.");
881
882 case kDNSServiceErr_BadKey :
883 return ("Bad encryption key.");
884
885 case kDNSServiceErr_Transient :
886 return ("Transient error occurred - please try again.");
887
888 case kDNSServiceErr_ServiceNotRunning :
889 return ("Server not running.");
890
891 case kDNSServiceErr_NATPortMappingUnsupported :
892 return ("NAT doesn't support NAT-PMP or UPnP.");
893
894 case kDNSServiceErr_NATPortMappingDisabled :
895 return ("NAT supports NAT-PNP or UPnP but it is disabled.");
896
897 case kDNSServiceErr_NoRouter :
898 return ("No Internet/default router configured.");
899
900 case kDNSServiceErr_PollingMode :
901 return ("Service polling mode error.");
902
903 case kDNSServiceErr_Timeout :
904 return ("Service timeout.");
905 }
906
907 # else /* HAVE_AVAHI */
908 return (avahi_strerror(error));
909 # endif /* HAVE_DNSSD */
910 }
911
912
913 /*
914 * 'dnssdRegisterCallback()' - Free a TXT record.
915 */
916
917 static void
918 dnssdFreeTxtRecord(cupsd_txt_t *txt) /* I - TXT record */
919 {
920 # ifdef HAVE_DNSSD
921 TXTRecordDeallocate(txt);
922
923 # else /* HAVE_AVAHI */
924 avahi_string_list_free(*txt);
925 *txt = NULL;
926 # endif /* HAVE_DNSSD */
927 }
928
929
930 /*
931 * 'dnssdRegisterCallback()' - DNSServiceRegister callback.
932 */
933
934 # ifdef HAVE_DNSSD
935 static void
936 dnssdRegisterCallback(
937 DNSServiceRef sdRef, /* I - DNS Service reference */
938 DNSServiceFlags flags, /* I - Reserved for future use */
939 DNSServiceErrorType errorCode, /* I - Error code */
940 const char *name, /* I - Service name */
941 const char *regtype, /* I - Service type */
942 const char *domain, /* I - Domain. ".local" for now */
943 void *context) /* I - Printer */
944 {
945 cupsd_printer_t *p = (cupsd_printer_t *)context;
946 /* Current printer */
947
948
949 (void)sdRef;
950 (void)flags;
951 (void)domain;
952
953 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)",
954 name, regtype, p ? p->name : "Web Interface",
955 p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
956
957 if (errorCode)
958 {
959 cupsdLogMessage(CUPSD_LOG_ERROR,
960 "DNSServiceRegister failed with error %d", (int)errorCode);
961 return;
962 }
963 else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name)))
964 {
965 cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"",
966 name, p->name);
967
968 cupsArrayRemove(DNSSDPrinters, p);
969 cupsdSetString(&p->reg_name, name);
970 cupsArrayAdd(DNSSDPrinters, p);
971
972 LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
973 }
974 }
975
976 # else /* HAVE_AVAHI */
977 static void
978 dnssdRegisterCallback(
979 AvahiEntryGroup *srv, /* I - Service */
980 AvahiEntryGroupState state, /* I - Registration state */
981 void *context) /* I - Printer */
982 {
983 cupsd_printer_t *p = (cupsd_printer_t *)context;
984 /* Current printer */
985
986 cupsdLogMessage(CUPSD_LOG_DEBUG2,
987 "dnssdRegisterCallback(srv=%p, state=%d, context=%p) "
988 "for %s (%s)", srv, state, context,
989 p ? p->name : "Web Interface",
990 p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
991
992 /* TODO: Handle collisions with avahi_alternate_service_name(p->reg_name)? */
993 }
994 # endif /* HAVE_DNSSD */
995
996
997 /*
998 * 'dnssdRegisterInstance()' - Register an instance of a printer service.
999 */
1000
1001 static int /* O - 1 on success, 0 on failure */
1002 dnssdRegisterInstance(
1003 cupsd_srv_t *srv, /* O - Service */
1004 cupsd_printer_t *p, /* I - Printer */
1005 char *name, /* I - DNS-SD service name */
1006 const char *type, /* I - DNS-SD service type */
1007 const char *subtypes, /* I - Subtypes to register or NULL */
1008 int port, /* I - Port number or 0 */
1009 cupsd_txt_t *txt, /* I - TXT record */
1010 int commit) /* I - Commit registration? */
1011 {
1012 char temp[256], /* Temporary string */
1013 *ptr; /* Pointer into string */
1014 int error; /* Any error */
1015
1016
1017 cupsdLogMessage(CUPSD_LOG_DEBUG,
1018 "Registering \"%s\" with DNS-SD type \"%s\".", name, type);
1019
1020 if (p && !srv)
1021 {
1022 /*
1023 * Assign the correct pointer for "srv"...
1024 */
1025
1026 # ifdef HAVE_DNSSD
1027 if (!strcmp(type, "_printer._tcp"))
1028 srv = &p->printer_srv; /* Target LPD service */
1029 # ifdef HAVE_SSL
1030 else if (!strcmp(type, "_ipps._tcp"))
1031 srv = &p->ipps_srv; /* Target IPPS service */
1032 # endif /* HAVE_SSL */
1033 else
1034 srv = &p->ipp_srv; /* Target IPP service */
1035
1036 # else /* HAVE_AVAHI */
1037 srv = &p->ipp_srv; /* Target service group */
1038 # endif /* HAVE_DNSSD */
1039 }
1040
1041 # ifdef HAVE_DNSSD
1042 (void)commit;
1043
1044 # else /* HAVE_AVAHI */
1045 avahi_threaded_poll_lock(DNSSDMaster);
1046
1047 if (!*srv)
1048 *srv = avahi_entry_group_new(DNSSDClient, dnssdRegisterCallback, NULL);
1049 if (!*srv)
1050 {
1051 avahi_threaded_poll_unlock(DNSSDMaster);
1052
1053 cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s",
1054 name, dnssdErrorString(avahi_client_errno(DNSSDClient)));
1055 return (0);
1056 }
1057 # endif /* HAVE_DNSSD */
1058
1059 /*
1060 * Make sure the name is <= 63 octets, and when we truncate be sure to
1061 * properly truncate any UTF-8 characters...
1062 */
1063
1064 ptr = name + strlen(name);
1065 while ((ptr - name) > 63)
1066 {
1067 do
1068 {
1069 ptr --;
1070 }
1071 while (ptr > name && (*ptr & 0xc0) == 0x80);
1072
1073 if (ptr > name)
1074 *ptr = '\0';
1075 }
1076
1077 /*
1078 * Register the service...
1079 */
1080
1081 # ifdef HAVE_DNSSD
1082 if (subtypes)
1083 snprintf(temp, sizeof(temp), "%s,%s", type, subtypes);
1084 else
1085 strlcpy(temp, type, sizeof(temp));
1086
1087 *srv = DNSSDMaster;
1088 error = DNSServiceRegister(srv, kDNSServiceFlagsShareConnection,
1089 0, name, temp, NULL, NULL, htons(port),
1090 txt ? TXTRecordGetLength(txt) : 0,
1091 txt ? TXTRecordGetBytesPtr(txt) : NULL,
1092 dnssdRegisterCallback, p);
1093
1094 # else /* HAVE_AVAHI */
1095 if (txt)
1096 {
1097 AvahiStringList *temptxt;
1098 for (temptxt = *txt; temptxt; temptxt = temptxt->next)
1099 cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS_SD \"%s\" %s", name, temptxt->text);
1100 }
1101
1102 error = avahi_entry_group_add_service_strlst(*srv, AVAHI_IF_UNSPEC,
1103 AVAHI_PROTO_UNSPEC, 0, name,
1104 type, NULL, NULL, port,
1105 txt ? *txt : NULL);
1106 if (error)
1107 cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD service add for \"%s\" failed.",
1108 name);
1109
1110 if (!error && subtypes)
1111 {
1112 /*
1113 * Register all of the subtypes...
1114 */
1115
1116 char *start, /* Start of subtype */
1117 subtype[256]; /* Subtype string */
1118
1119 strlcpy(temp, subtypes, sizeof(temp));
1120
1121 for (start = temp; *start; start = ptr)
1122 {
1123 /*
1124 * Skip leading whitespace...
1125 */
1126
1127 while (*start && isspace(*start & 255))
1128 start ++;
1129
1130 /*
1131 * Grab everything up to the next comma or the end of the string...
1132 */
1133
1134 for (ptr = start; *ptr && *ptr != ','; ptr ++);
1135
1136 if (*ptr)
1137 *ptr++ = '\0';
1138
1139 if (!*start)
1140 break;
1141
1142 /*
1143 * Register the subtype...
1144 */
1145
1146 snprintf(subtype, sizeof(subtype), "%s._sub.%s", start, type);
1147
1148 error = avahi_entry_group_add_service_subtype(*srv, AVAHI_IF_UNSPEC,
1149 AVAHI_PROTO_UNSPEC, 0,
1150 name, type, NULL, subtype);
1151 if (error)
1152 {
1153 cupsdLogMessage(CUPSD_LOG_DEBUG,
1154 "DNS-SD subtype %s registration for \"%s\" failed." ,
1155 subtype, name);
1156 break;
1157 }
1158 }
1159 }
1160
1161 if (!error && commit)
1162 {
1163 if ((error = avahi_entry_group_commit(*srv)) != 0)
1164 cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD commit of \"%s\" failed.",
1165 name);
1166 }
1167
1168 avahi_threaded_poll_unlock(DNSSDMaster);
1169 # endif /* HAVE_DNSSD */
1170
1171 if (error)
1172 {
1173 cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s",
1174 name, dnssdErrorString(error));
1175 cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD type: %s", type);
1176 if (subtypes)
1177 cupsdLogMessage(CUPSD_LOG_DEBUG, "DNS-SD sub-types: %s", subtypes);
1178 }
1179
1180 return (!error);
1181 }
1182
1183
1184 /*
1185 * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
1186 * or update the broadcast contents.
1187 */
1188
1189 static void
1190 dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
1191 {
1192 char name[256]; /* Service name */
1193 int printer_port; /* LPD port number */
1194 int status; /* Registration status */
1195 cupsd_txt_t ipp_txt, /* IPP(S) TXT record */
1196 printer_txt; /* LPD TXT record */
1197
1198 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
1199 !p->ipp_srv ? "new" : "update");
1200
1201 /*
1202 * Remove the current registrations if we have them and then return if
1203 * per-printer sharing was just disabled...
1204 */
1205
1206 dnssdDeregisterPrinter(p, 0);
1207
1208 if (!p->shared)
1209 return;
1210
1211 /*
1212 * Set the registered name as needed; the registered name takes the form of
1213 * "<printer-info> @ <computer name>"...
1214 */
1215
1216 if (!p->reg_name)
1217 {
1218 if (p->info && strlen(p->info) > 0)
1219 {
1220 if (DNSSDComputerName)
1221 snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
1222 else
1223 strlcpy(name, p->info, sizeof(name));
1224 }
1225 else if (DNSSDComputerName)
1226 snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
1227 else
1228 strlcpy(name, p->name, sizeof(name));
1229 }
1230 else
1231 strlcpy(name, p->reg_name, sizeof(name));
1232
1233 /*
1234 * Register IPP and LPD...
1235 *
1236 * We always must register the "_printer" service type in order to reserve
1237 * our name, but use port number 0 if we haven't actually configured cups-lpd
1238 * to share via LPD...
1239 */
1240
1241 ipp_txt = dnssdBuildTxtRecord(p, 0);
1242 printer_txt = dnssdBuildTxtRecord(p, 1);
1243
1244 if (BrowseLocalProtocols & BROWSE_LPD)
1245 printer_port = 515;
1246 else
1247 printer_port = 0;
1248
1249 status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL,
1250 printer_port, &printer_txt, 0);
1251
1252 # ifdef HAVE_SSL
1253 if (status)
1254 dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes,
1255 DNSSDPort, &ipp_txt, 0);
1256 # endif /* HAVE_SSL */
1257
1258 if (status)
1259 {
1260 /*
1261 * Use the "_fax-ipp" service type for fax queues, otherwise use "_ipp"...
1262 */
1263
1264 if (p->type & CUPS_PRINTER_FAX)
1265 status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp",
1266 DNSSDSubTypes, DNSSDPort, &ipp_txt, 1);
1267 else
1268 status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes,
1269 DNSSDPort, &ipp_txt, 1);
1270 }
1271
1272 dnssdFreeTxtRecord(&ipp_txt);
1273 dnssdFreeTxtRecord(&printer_txt);
1274
1275 if (status)
1276 {
1277 /*
1278 * Save the registered name and add the printer to the array of DNS-SD
1279 * printers...
1280 */
1281
1282 cupsdSetString(&p->reg_name, name);
1283 cupsArrayAdd(DNSSDPrinters, p);
1284 }
1285 else
1286 {
1287 /*
1288 * Registration failed for this printer...
1289 */
1290
1291 dnssdDeregisterInstance(&p->ipp_srv);
1292
1293 # ifdef HAVE_DNSSD
1294 # ifdef HAVE_SSL
1295 dnssdDeregisterInstance(&p->ipps_srv);
1296 # endif /* HAVE_SSL */
1297 dnssdDeregisterInstance(&p->printer_srv);
1298 # endif /* HAVE_DNSSD */
1299 }
1300 }
1301
1302
1303 /*
1304 * 'dnssdStop()' - Stop all DNS-SD registrations.
1305 */
1306
1307 static void
1308 dnssdStop(void)
1309 {
1310 cupsd_printer_t *p; /* Current printer */
1311
1312
1313 /*
1314 * De-register the individual printers
1315 */
1316
1317 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
1318 p;
1319 p = (cupsd_printer_t *)cupsArrayNext(Printers))
1320 dnssdDeregisterPrinter(p, 1);
1321
1322 /*
1323 * Shutdown the rest of the service refs...
1324 */
1325
1326 dnssdDeregisterInstance(&WebIFSrv);
1327
1328 # ifdef HAVE_DNSSD
1329 cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDMaster));
1330
1331 DNSServiceRefDeallocate(DNSSDMaster);
1332 DNSSDMaster = NULL;
1333
1334 # else /* HAVE_AVAHI */
1335 avahi_client_free(DNSSDClient);
1336 DNSSDClient = NULL;
1337
1338 avahi_threaded_poll_free(DNSSDMaster);
1339 DNSSDMaster = NULL;
1340 # endif /* HAVE_DNSSD */
1341
1342 cupsArrayDelete(DNSSDPrinters);
1343 DNSSDPrinters = NULL;
1344
1345 DNSSDPort = 0;
1346 }
1347
1348
1349 # ifdef HAVE_DNSSD
1350 /*
1351 * 'dnssdUpdate()' - Handle DNS-SD queries.
1352 */
1353
1354 static void
1355 dnssdUpdate(void)
1356 {
1357 DNSServiceErrorType sdErr; /* Service discovery error */
1358
1359
1360 if ((sdErr = DNSServiceProcessResult(DNSSDMaster)) != kDNSServiceErr_NoError)
1361 {
1362 cupsdLogMessage(CUPSD_LOG_ERROR,
1363 "DNS Service Discovery registration error %d!",
1364 sdErr);
1365 dnssdStop();
1366 }
1367 }
1368 # endif /* HAVE_DNSSD */
1369
1370
1371 /*
1372 * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
1373 */
1374
1375 static char * /* O - String or NULL if none */
1376 get_auth_info_required(
1377 cupsd_printer_t *p, /* I - Printer */
1378 char *buffer, /* I - Value buffer */
1379 size_t bufsize) /* I - Size of value buffer */
1380 {
1381 cupsd_location_t *auth; /* Pointer to authentication element */
1382 char resource[1024]; /* Printer/class resource path */
1383
1384
1385 /*
1386 * If auth-info-required is set for this printer, return that...
1387 */
1388
1389 if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none"))
1390 {
1391 int i; /* Looping var */
1392 char *bufptr; /* Pointer into buffer */
1393
1394 for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++)
1395 {
1396 if (bufptr >= (buffer + bufsize - 2))
1397 break;
1398
1399 if (i)
1400 *bufptr++ = ',';
1401
1402 strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer));
1403 bufptr += strlen(bufptr);
1404 }
1405
1406 return (buffer);
1407 }
1408
1409 /*
1410 * Figure out the authentication data requirements to advertise...
1411 */
1412
1413 if (p->type & CUPS_PRINTER_CLASS)
1414 snprintf(resource, sizeof(resource), "/classes/%s", p->name);
1415 else
1416 snprintf(resource, sizeof(resource), "/printers/%s", p->name);
1417
1418 if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
1419 auth->type == CUPSD_AUTH_NONE)
1420 auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
1421
1422 if (auth)
1423 {
1424 int auth_type; /* Authentication type */
1425
1426 if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
1427 auth_type = cupsdDefaultAuthType();
1428
1429 switch (auth_type)
1430 {
1431 case CUPSD_AUTH_NONE :
1432 return (NULL);
1433
1434 case CUPSD_AUTH_NEGOTIATE :
1435 strlcpy(buffer, "negotiate", bufsize);
1436 break;
1437
1438 default :
1439 strlcpy(buffer, "username,password", bufsize);
1440 break;
1441 }
1442
1443 return (buffer);
1444 }
1445
1446 return ("none");
1447 }
1448 #endif /* HAVE_DNSSD || HAVE_AVAHI */
1449
1450
1451 #ifdef __APPLE__
1452 /*
1453 * 'get_hostconfig()' - Get an /etc/hostconfig service setting.
1454 */
1455
1456 static int /* O - 1 for YES or AUTOMATIC, 0 for NO */
1457 get_hostconfig(const char *name) /* I - Name of service */
1458 {
1459 cups_file_t *fp; /* Hostconfig file */
1460 char line[1024], /* Line from file */
1461 *ptr; /* Pointer to value */
1462 int state = 1; /* State of service */
1463
1464
1465 /*
1466 * Try opening the /etc/hostconfig file; if we can't open it, assume that
1467 * the service is enabled/auto.
1468 */
1469
1470 if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL)
1471 {
1472 /*
1473 * Read lines from the file until we find the service...
1474 */
1475
1476 while (cupsFileGets(fp, line, sizeof(line)))
1477 {
1478 if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL)
1479 continue;
1480
1481 *ptr++ = '\0';
1482
1483 if (!_cups_strcasecmp(line, name))
1484 {
1485 /*
1486 * Found the service, see if it is set to "-NO-"...
1487 */
1488
1489 if (!_cups_strncasecmp(ptr, "-NO-", 4))
1490 state = 0;
1491 break;
1492 }
1493 }
1494
1495 cupsFileClose(fp);
1496 }
1497
1498 return (state);
1499 }
1500 #endif /* __APPLE__ */
1501
1502
1503 /*
1504 * 'update_lpd()' - Update the LPD configuration as needed.
1505 */
1506
1507 static void
1508 update_lpd(int onoff) /* - 1 = turn on, 0 = turn off */
1509 {
1510 if (!LPDConfigFile)
1511 return;
1512
1513 #ifdef __APPLE__
1514 /*
1515 * Allow /etc/hostconfig CUPS_LPD service setting to override cupsd.conf
1516 * setting for backwards-compatibility.
1517 */
1518
1519 if (onoff && !get_hostconfig("CUPS_LPD"))
1520 onoff = 0;
1521 #endif /* __APPLE__ */
1522
1523 if (!strncmp(LPDConfigFile, "xinetd:///", 10))
1524 {
1525 /*
1526 * Enable/disable LPD via the xinetd.d config file for cups-lpd...
1527 */
1528
1529 char newfile[1024]; /* New cups-lpd.N file */
1530 cups_file_t *ofp, /* Original file pointer */
1531 *nfp; /* New file pointer */
1532 char line[1024]; /* Line from file */
1533
1534
1535 snprintf(newfile, sizeof(newfile), "%s.N", LPDConfigFile + 9);
1536
1537 if ((ofp = cupsFileOpen(LPDConfigFile + 9, "r")) == NULL)
1538 {
1539 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s",
1540 LPDConfigFile + 9, strerror(errno));
1541 return;
1542 }
1543
1544 if ((nfp = cupsFileOpen(newfile, "w")) == NULL)
1545 {
1546 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s",
1547 newfile, strerror(errno));
1548 cupsFileClose(ofp);
1549 return;
1550 }
1551
1552 /*
1553 * Copy all of the lines from the cups-lpd file...
1554 */
1555
1556 while (cupsFileGets(ofp, line, sizeof(line)))
1557 {
1558 if (line[0] == '{')
1559 {
1560 cupsFilePrintf(nfp, "%s\n", line);
1561 snprintf(line, sizeof(line), "\tdisable = %s",
1562 onoff ? "no" : "yes");
1563 }
1564 else if (!strstr(line, "disable ="))
1565 cupsFilePrintf(nfp, "%s\n", line);
1566 }
1567
1568 cupsFileClose(nfp);
1569 cupsFileClose(ofp);
1570 rename(newfile, LPDConfigFile + 9);
1571 }
1572 #ifdef __APPLE__
1573 else if (!strncmp(LPDConfigFile, "launchd:///", 11))
1574 {
1575 /*
1576 * Enable/disable LPD via the launchctl command...
1577 */
1578
1579 char *argv[5], /* Arguments for command */
1580 *envp[MAX_ENV]; /* Environment for command */
1581 int pid; /* Process ID */
1582
1583
1584 cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
1585 argv[0] = (char *)"launchctl";
1586 argv[1] = (char *)(onoff ? "load" : "unload");
1587 argv[2] = (char *)"-w";
1588 argv[3] = LPDConfigFile + 10;
1589 argv[4] = NULL;
1590
1591 cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1,
1592 NULL, NULL, &pid);
1593 }
1594 #endif /* __APPLE__ */
1595 else
1596 cupsdLogMessage(CUPSD_LOG_INFO, "Unknown LPDConfigFile scheme!");
1597 }
1598
1599
1600 /*
1601 * 'update_smb()' - Update the SMB configuration as needed.
1602 */
1603
1604 static void
1605 update_smb(int onoff) /* I - 1 = turn on, 0 = turn off */
1606 {
1607 if (!SMBConfigFile)
1608 return;
1609
1610 if (!strncmp(SMBConfigFile, "samba:///", 9))
1611 {
1612 /*
1613 * Enable/disable SMB via the specified smb.conf config file...
1614 */
1615
1616 char newfile[1024]; /* New smb.conf.N file */
1617 cups_file_t *ofp, /* Original file pointer */
1618 *nfp; /* New file pointer */
1619 char line[1024]; /* Line from file */
1620 int in_printers; /* In [printers] section? */
1621
1622
1623 snprintf(newfile, sizeof(newfile), "%s.N", SMBConfigFile + 8);
1624
1625 if ((ofp = cupsFileOpen(SMBConfigFile + 8, "r")) == NULL)
1626 {
1627 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s",
1628 SMBConfigFile + 8, strerror(errno));
1629 return;
1630 }
1631
1632 if ((nfp = cupsFileOpen(newfile, "w")) == NULL)
1633 {
1634 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s",
1635 newfile, strerror(errno));
1636 cupsFileClose(ofp);
1637 return;
1638 }
1639
1640 /*
1641 * Copy all of the lines from the smb.conf file...
1642 */
1643
1644 in_printers = 0;
1645
1646 while (cupsFileGets(ofp, line, sizeof(line)))
1647 {
1648 if (in_printers && strstr(line, "printable ="))
1649 snprintf(line, sizeof(line), " printable = %s",
1650 onoff ? "yes" : "no");
1651
1652 cupsFilePrintf(nfp, "%s\n", line);
1653
1654 if (line[0] == '[')
1655 in_printers = !strcmp(line, "[printers]");
1656 }
1657
1658 cupsFileClose(nfp);
1659 cupsFileClose(ofp);
1660 rename(newfile, SMBConfigFile + 8);
1661 }
1662 else
1663 cupsdLogMessage(CUPSD_LOG_INFO, "Unknown SMBConfigFile scheme!");
1664 }
1665
1666
1667 /*
1668 * End of "$Id: dirsvc.c 7933 2008-09-11 00:44:58Z mike $".
1669 */