]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/dirsvc.c
Merge changes from CUPS 1.6svn-r10188, including changes for <rdar://problem/10127258...
[thirdparty/cups.git] / scheduler / dirsvc.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: dirsvc.c 7933 2008-09-11 00:44:58Z mike $"
ef416fc2 3 *
10d09e33 4 * Directory services routines for the CUPS scheduler.
ef416fc2 5 *
e60ec91f 6 * Copyright 2007-2011 by Apple Inc.
b86bc4cf 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
ef416fc2 14 *
15 * Contents:
16 *
a2326b5b
MS
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 browsing...
27 * dnssdAddAlias() - Add a DNS-SD alias name.
28 * dnssdBuildTxtRecord() - Build a TXT record from printer info.
29 * dnssdDeregisterPrinter() - Stop sending broadcast information for a
30 * printer.
31 * dnssdPackTxtRecord() - Pack an array of key/value pairs into the TXT
32 * record format.
33 * dnssdRegisterCallback() - DNSServiceRegister callback.
34 * dnssdRegisterPrinter() - Start sending broadcast information for a
35 * printer or update the broadcast contents.
36 * dnssdStop() - Stop all DNS-SD registrations.
37 * dnssdUpdate() - Handle DNS-SD queries.
38 * get_auth_info_required() - Get the auth-info-required value to advertise.
39 * get_hostconfig() - Get an /etc/hostconfig service setting.
40 * update_lpd() - Update the LPD configuration as needed.
41 * update_smb() - Update the SMB configuration as needed.
ef416fc2 42 */
43
44/*
45 * Include necessary headers...
46 */
47
48#include "cupsd.h"
49#include <grp.h>
50
f7deaa1a 51#ifdef HAVE_DNSSD
52# include <dns_sd.h>
cc0d019f
MS
53# ifdef __APPLE__
54# include <nameser.h>
55# ifdef HAVE_COREFOUNDATION
56# include <CoreFoundation/CoreFoundation.h>
57# endif /* HAVE_COREFOUNDATION */
58# ifdef HAVE_SYSTEMCONFIGURATION
59# include <SystemConfiguration/SystemConfiguration.h>
60# endif /* HAVE_SYSTEMCONFIGURATION */
61# endif /* __APPLE__ */
f7deaa1a 62#endif /* HAVE_DNSSD */
63
ef416fc2 64
65/*
e00b005a 66 * Local functions...
ef416fc2 67 */
68
dcb445bc 69#ifdef HAVE_DNSSD
178cb736
MS
70static char *get_auth_info_required(cupsd_printer_t *p, char *buffer,
71 size_t bufsize);
dcb445bc 72#endif /* HAVE_DNSSD */
a603edef
MS
73#ifdef __APPLE__
74static int get_hostconfig(const char *name);
75#endif /* __APPLE__ */
2e4ff8af 76static void update_lpd(int onoff);
2e4ff8af 77static void update_smb(int onoff);
f899b121 78
e00b005a 79
7a14d768 80#ifdef HAVE_DNSSD
e07d4801
MS
81# ifdef HAVE_COREFOUNDATION
82static void dnssdAddAlias(const void *key, const void *value,
83 void *context);
84# endif /* HAVE_COREFOUNDATION */
7a14d768
MS
85static char *dnssdBuildTxtRecord(int *txt_len, cupsd_printer_t *p,
86 int for_lpd);
7a14d768
MS
87static void dnssdDeregisterPrinter(cupsd_printer_t *p);
88static char *dnssdPackTxtRecord(int *txt_len, char *keyvalue[][2],
89 int count);
90static void dnssdRegisterCallback(DNSServiceRef sdRef,
88f9aafc 91 DNSServiceFlags flags,
7a14d768
MS
92 DNSServiceErrorType errorCode,
93 const char *name, const char *regtype,
94 const char *domain, void *context);
95static void dnssdRegisterPrinter(cupsd_printer_t *p);
f0ab5bff 96static void dnssdStop(void);
75bd9771 97static void dnssdUpdate(void);
7a14d768
MS
98#endif /* HAVE_DNSSD */
99
f7deaa1a 100
101/*
88f9aafc 102 * 'cupsdDeregisterPrinter()' - Stop sending broadcast information for a
f7deaa1a 103 * local printer and remove any pending
104 * references to remote printers.
105 */
106
107void
108cupsdDeregisterPrinter(
109 cupsd_printer_t *p, /* I - Printer to register */
110 int removeit) /* I - Printer being permanently removed */
111{
112 /*
7a14d768 113 * Only deregister if browsing is enabled and it's a local printer...
f7deaa1a 114 */
115
745129be
MS
116 cupsdLogMessage(CUPSD_LOG_DEBUG,
117 "cupsdDeregisterPrinter(p=%p(%s), removeit=%d)", p, p->name,
118 removeit);
119
f7deaa1a 120 if (!Browsing || !p->shared ||
a2326b5b 121 (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
f7deaa1a 122 return;
123
124 /*
125 * Announce the deletion...
126 */
127
a2326b5b
MS
128#ifdef HAVE_DNSSD
129 if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
130 dnssdDeregisterPrinter(p);
131#endif /* HAVE_DNSSD */
132}
f7deaa1a 133
f7deaa1a 134
a2326b5b
MS
135/*
136 * 'cupsdRegisterPrinter()' - Start sending broadcast information for a
137 * printer or update the broadcast contents.
138 */
f7deaa1a 139
a2326b5b
MS
140void
141cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
142{
143 cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdRegisterPrinter(p=%p(%s))", p,
144 p->name);
f7deaa1a 145
a2326b5b
MS
146 if (!Browsing || !BrowseLocalProtocols ||
147 (p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
148 return;
749b1e90 149
f7deaa1a 150#ifdef HAVE_DNSSD
a2326b5b
MS
151 if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
152 dnssdRegisterPrinter(p);
f7deaa1a 153#endif /* HAVE_DNSSD */
154}
155
ef416fc2 156
157/*
a2326b5b 158 * 'cupsdStartBrowsing()' - Start sending and receiving broadcast information.
ef416fc2 159 */
160
161void
a2326b5b 162cupsdStartBrowsing(void)
ef416fc2 163{
ef416fc2 164 cupsd_printer_t *p; /* Current printer */
411affcf 165
411affcf 166
a2326b5b 167 if (!Browsing || !BrowseLocalProtocols)
ef416fc2 168 return;
169
a2326b5b
MS
170#ifdef HAVE_DNSSD
171 if (BrowseLocalProtocols & BROWSE_DNSSD)
172 {
173 DNSServiceErrorType error; /* Error from service creation */
174 cupsd_listener_t *lis; /* Current listening socket */
ef416fc2 175
ef416fc2 176
ef416fc2 177 /*
a2326b5b 178 * First create a "master" connection for all registrations...
ef416fc2 179 */
180
a2326b5b
MS
181 if ((error = DNSServiceCreateConnection(&DNSSDRef))
182 != kDNSServiceErr_NoError)
ef416fc2 183 {
184 cupsdLogMessage(CUPSD_LOG_ERROR,
a2326b5b 185 "Unable to create master DNS-SD reference: %d", error);
bd7854cb 186
a2326b5b
MS
187 if (FatalErrors & CUPSD_FATAL_BROWSE)
188 cupsdEndProcess(getpid(), 0);
ef416fc2 189 }
a2326b5b 190 else
b423cd4c 191 {
192 /*
a2326b5b 193 * Add the master connection to the select list...
b423cd4c 194 */
195
a2326b5b 196 int fd = DNSServiceRefSockFD(DNSSDRef);
b423cd4c 197
a2326b5b 198 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
b423cd4c 199
a2326b5b 200 cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL);
ef416fc2 201
ef416fc2 202 /*
a2326b5b
MS
203 * Then get the port we use for registrations. If we are not listening
204 * on any non-local ports, there is no sense sharing local printers via
205 * Bonjour...
ef416fc2 206 */
207
a2326b5b 208 DNSSDPort = 0;
ef416fc2 209
a2326b5b
MS
210 for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
211 lis;
212 lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
ef416fc2 213 {
a2326b5b
MS
214 if (httpAddrLocalhost(&(lis->address)))
215 continue;
ef416fc2 216
a2326b5b
MS
217 DNSSDPort = _httpAddrPort(&(lis->address));
218 break;
ef416fc2 219 }
ef416fc2 220
ef416fc2 221 /*
a2326b5b 222 * Set the computer name and register the web interface...
ef416fc2 223 */
224
a2326b5b 225 cupsdUpdateDNSSDName();
ef416fc2 226 }
227 }
a2326b5b
MS
228#endif /* HAVE_DNSSD */
229
230 /*
231 * Enable LPD and SMB printer sharing as needed through external programs...
232 */
233
234 if (BrowseLocalProtocols & BROWSE_LPD)
235 update_lpd(1);
ef416fc2 236
a2326b5b
MS
237 if (BrowseLocalProtocols & BROWSE_SMB)
238 update_smb(1);
ef416fc2 239
240 /*
a2326b5b 241 * Register the individual printers
ef416fc2 242 */
243
a2326b5b
MS
244 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
245 p;
246 p = (cupsd_printer_t *)cupsArrayNext(Printers))
247 if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
248 cupsdRegisterPrinter(p);
ef416fc2 249}
250
251
f7deaa1a 252/*
a2326b5b 253 * 'cupsdStopBrowsing()' - Stop sending and receiving broadcast information.
f7deaa1a 254 */
255
256void
a2326b5b 257cupsdStopBrowsing(void)
f7deaa1a 258{
a2326b5b 259 cupsd_printer_t *p; /* Current printer */
745129be 260
a2326b5b
MS
261
262 if (!Browsing || !BrowseLocalProtocols)
f7deaa1a 263 return;
264
a2326b5b
MS
265 /*
266 * De-register the individual printers
267 */
268
269 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
270 p;
271 p = (cupsd_printer_t *)cupsArrayNext(Printers))
272 if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER)))
273 cupsdDeregisterPrinter(p, 1);
274
275 /*
276 * Shut down browsing sockets...
277 */
f7deaa1a 278
279#ifdef HAVE_DNSSD
bdd6c45b 280 if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDRef)
a2326b5b 281 dnssdStop();
f7deaa1a 282#endif /* HAVE_DNSSD */
d09495fa 283
a2326b5b
MS
284 /*
285 * Disable LPD and SMB printer sharing as needed through external programs...
286 */
d09495fa 287
a2326b5b
MS
288 if (BrowseLocalProtocols & BROWSE_LPD)
289 update_lpd(0);
d09495fa 290
a2326b5b
MS
291 if (BrowseLocalProtocols & BROWSE_SMB)
292 update_smb(0);
d09495fa 293}
294
295
a2326b5b 296#ifdef HAVE_DNSSD
ef416fc2 297/*
a2326b5b 298 * 'cupsdUpdateDNSSDName()' - Update the computer name we use for browsing...
ef416fc2 299 */
300
301void
a2326b5b 302cupsdUpdateDNSSDName(void)
ef416fc2 303{
a2326b5b
MS
304 DNSServiceErrorType error; /* Error from service creation */
305 char webif[1024]; /* Web interface share name */
306# ifdef HAVE_SYSTEMCONFIGURATION
307 SCDynamicStoreRef sc; /* Context for dynamic store */
308 CFDictionaryRef btmm; /* Back-to-My-Mac domains */
309 CFStringEncoding nameEncoding; /* Encoding of computer name */
310 CFStringRef nameRef; /* Host name CFString */
311 char nameBuffer[1024]; /* C-string buffer */
312# endif /* HAVE_SYSTEMCONFIGURATION */
ef416fc2 313
ef416fc2 314
315 /*
a2326b5b
MS
316 * Only share the web interface and printers when non-local listening is
317 * enabled...
318 */
ef416fc2 319
a2326b5b 320 if (!DNSSDPort)
ef416fc2 321 return;
ef416fc2 322
e00b005a 323 /*
a2326b5b 324 * Get the computer name as a c-string...
e00b005a 325 */
ef416fc2 326
a2326b5b
MS
327# ifdef HAVE_SYSTEMCONFIGURATION
328 sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL);
ef416fc2 329
a2326b5b 330 if (sc)
ef416fc2 331 {
332 /*
a2326b5b 333 * Get the computer name from the dynamic store...
ef416fc2 334 */
335
a2326b5b 336 cupsdClearString(&DNSSDComputerName);
ef416fc2 337
a2326b5b 338 if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL)
58dc1933 339 {
a2326b5b
MS
340 if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
341 kCFStringEncodingUTF8))
342 {
343 cupsdLogMessage(CUPSD_LOG_DEBUG,
344 "Dynamic store computer name is \"%s\".", nameBuffer);
345 cupsdSetString(&DNSSDComputerName, nameBuffer);
346 }
e00b005a 347
a2326b5b
MS
348 CFRelease(nameRef);
349 }
e00b005a 350
a2326b5b
MS
351 if (!DNSSDComputerName)
352 {
353 /*
354 * Use the ServerName instead...
355 */
e00b005a 356
a2326b5b
MS
357 cupsdLogMessage(CUPSD_LOG_DEBUG,
358 "Using ServerName \"%s\" as computer name.", ServerName);
359 cupsdSetString(&DNSSDComputerName, ServerName);
360 }
e00b005a 361
362 /*
a2326b5b 363 * Get the local hostname from the dynamic store...
e00b005a 364 */
365
a2326b5b 366 cupsdClearString(&DNSSDHostName);
e00b005a 367
a2326b5b
MS
368 if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL)
369 {
370 if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer),
371 kCFStringEncodingUTF8))
372 {
373 cupsdLogMessage(CUPSD_LOG_DEBUG,
374 "Dynamic store host name is \"%s\".", nameBuffer);
375 cupsdSetString(&DNSSDHostName, nameBuffer);
376 }
e00b005a 377
a2326b5b
MS
378 CFRelease(nameRef);
379 }
e00b005a 380
a2326b5b 381 if (!DNSSDHostName)
ef416fc2 382 {
383 /*
a2326b5b 384 * Use the ServerName instead...
ef416fc2 385 */
386
a2326b5b
MS
387 cupsdLogMessage(CUPSD_LOG_DEBUG,
388 "Using ServerName \"%s\" as host name.", ServerName);
389 cupsdSetString(&DNSSDHostName, ServerName);
ef416fc2 390 }
e00b005a 391
392 /*
a2326b5b 393 * Get any Back-to-My-Mac domains and add them as aliases...
e00b005a 394 */
395
a2326b5b
MS
396 cupsdFreeAliases(DNSSDAlias);
397 DNSSDAlias = NULL;
ef416fc2 398
a2326b5b
MS
399 btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac"));
400 if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID())
ef416fc2 401 {
a2326b5b
MS
402 cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.",
403 (int)CFDictionaryGetCount(btmm));
404 CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL);
ef416fc2 405 }
a2326b5b
MS
406 else if (btmm)
407 cupsdLogMessage(CUPSD_LOG_ERROR,
408 "Bad Back to My Mac data in dynamic store!");
409 else
410 cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add.");
749b1e90 411
a2326b5b
MS
412 if (btmm)
413 CFRelease(btmm);
321d8d57 414
a2326b5b
MS
415 CFRelease(sc);
416 }
417 else
418# endif /* HAVE_SYSTEMCONFIGURATION */
419 {
420 cupsdSetString(&DNSSDComputerName, ServerName);
421 cupsdSetString(&DNSSDHostName, ServerName);
422 }
321d8d57 423
749b1e90 424 /*
a2326b5b 425 * Then (re)register the web interface if enabled...
749b1e90
MS
426 */
427
a2326b5b
MS
428 if (BrowseWebIF)
429 {
430 if (DNSSDComputerName)
431 snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName);
432 else
433 strlcpy(webif, "CUPS Web Interface", sizeof(webif));
749b1e90 434
a2326b5b
MS
435 if (WebIFRef)
436 DNSServiceRefDeallocate(WebIFRef);
749b1e90 437
a2326b5b
MS
438 WebIFRef = DNSSDRef;
439 if ((error = DNSServiceRegister(&WebIFRef,
440 kDNSServiceFlagsShareConnection,
441 0, webif, "_http._tcp", NULL,
442 NULL, htons(DNSSDPort), 7,
443 "\006path=/", dnssdRegisterCallback,
444 NULL)) != kDNSServiceErr_NoError)
445 cupsdLogMessage(CUPSD_LOG_ERROR,
446 "DNS-SD web interface registration failed: %d", error);
447 }
749b1e90 448}
a2326b5b 449#endif /* HAVE_DNSSD */
749b1e90 450
749b1e90 451
a2326b5b
MS
452#ifdef HAVE_DNSSD
453# ifdef HAVE_COREFOUNDATION
749b1e90 454/*
a2326b5b 455 * 'dnssdAddAlias()' - Add a DNS-SD alias name.
749b1e90
MS
456 */
457
a2326b5b
MS
458static void
459dnssdAddAlias(const void *key, /* I - Key */
460 const void *value, /* I - Value (domain) */
461 void *context) /* I - Unused */
749b1e90 462{
a2326b5b 463 char valueStr[1024], /* Domain string */
dcb445bc
MS
464 hostname[1024], /* Complete hostname */
465 *hostptr; /* Pointer into hostname */
749b1e90 466
749b1e90 467
a2326b5b
MS
468 (void)key;
469 (void)context;
749b1e90 470
a2326b5b
MS
471 if (CFGetTypeID((CFStringRef)value) == CFStringGetTypeID() &&
472 CFStringGetCString((CFStringRef)value, valueStr, sizeof(valueStr),
473 kCFStringEncodingUTF8))
474 {
475 snprintf(hostname, sizeof(hostname), "%s.%s", DNSSDHostName, valueStr);
dcb445bc
MS
476 hostptr = hostname + strlen(hostname) - 1;
477 if (*hostptr == '.')
478 *hostptr = '\0'; /* Strip trailing dot */
479
a2326b5b
MS
480 if (!DNSSDAlias)
481 DNSSDAlias = cupsArrayNew(NULL, NULL);
749b1e90 482
a2326b5b
MS
483 cupsdAddAlias(DNSSDAlias, hostname);
484 cupsdLogMessage(CUPSD_LOG_DEBUG, "Added Back to My Mac ServerAlias %s",
485 hostname);
749b1e90 486 }
a2326b5b
MS
487 else
488 cupsdLogMessage(CUPSD_LOG_ERROR,
489 "Bad Back to My Mac domain in dynamic store!");
749b1e90 490}
a2326b5b 491# endif /* HAVE_COREFOUNDATION */
749b1e90
MS
492
493
749b1e90 494/*
a2326b5b 495 * 'dnssdBuildTxtRecord()' - Build a TXT record from printer info.
749b1e90
MS
496 */
497
a2326b5b
MS
498static char * /* O - TXT record */
499dnssdBuildTxtRecord(
500 int *txt_len, /* O - TXT record length */
501 cupsd_printer_t *p, /* I - Printer information */
502 int for_lpd) /* I - 1 = LPD, 0 = IPP */
ef416fc2 503{
e00b005a 504 int i; /* Looping var */
a2326b5b
MS
505 char admin_hostname[256], /* .local hostname for admin page */
506 adminurl_str[256], /* URL for the admin page */
507 type_str[32], /* Type to string buffer */
508 state_str[32], /* State to string buffer */
509 rp_str[1024], /* Queue name string buffer */
510 air_str[1024], /* auth-info-required string buffer */
511 *keyvalue[32][2]; /* Table of key/value pairs */
749b1e90 512
749b1e90
MS
513
514 /*
a2326b5b 515 * Load up the key value pairs...
749b1e90
MS
516 */
517
a2326b5b 518 i = 0;
749b1e90 519
a2326b5b
MS
520 keyvalue[i ][0] = "txtvers";
521 keyvalue[i++][1] = "1";
749b1e90 522
a2326b5b
MS
523 keyvalue[i ][0] = "qtotal";
524 keyvalue[i++][1] = "1";
749b1e90 525
a2326b5b
MS
526 keyvalue[i ][0] = "rp";
527 keyvalue[i++][1] = rp_str;
528 if (for_lpd)
529 strlcpy(rp_str, p->name, sizeof(rp_str));
530 else
531 snprintf(rp_str, sizeof(rp_str), "%s/%s",
532 (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers", p->name);
88f9aafc 533
a2326b5b
MS
534 keyvalue[i ][0] = "ty";
535 keyvalue[i++][1] = p->make_model ? p->make_model : "Unknown";
749b1e90 536
a2326b5b
MS
537 snprintf(admin_hostname, sizeof(admin_hostname), "%s.local.", DNSSDHostName);
538 httpAssembleURIf(HTTP_URI_CODING_ALL, adminurl_str, sizeof(adminurl_str),
539 "http", NULL, admin_hostname, DNSSDPort, "/%s/%s",
540 (p->type & CUPS_PRINTER_CLASS) ? "classes" : "printers",
541 p->name);
542 keyvalue[i ][0] = "adminurl";
543 keyvalue[i++][1] = adminurl_str;
749b1e90 544
a2326b5b
MS
545 keyvalue[i ][0] = "note";
546 keyvalue[i++][1] = p->location ? p->location : "";
749b1e90 547
a2326b5b
MS
548 keyvalue[i ][0] = "priority";
549 keyvalue[i++][1] = for_lpd ? "100" : "0";
749b1e90 550
a2326b5b
MS
551 keyvalue[i ][0] = "product";
552 keyvalue[i++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown";
749b1e90 553
a2326b5b
MS
554 keyvalue[i ][0] = "pdl";
555 keyvalue[i++][1] = p->pdl ? p->pdl : "application/postscript";
556
557 if (get_auth_info_required(p, air_str, sizeof(air_str)))
749b1e90 558 {
a2326b5b
MS
559 keyvalue[i ][0] = "air";
560 keyvalue[i++][1] = air_str;
561 }
749b1e90 562
a2326b5b
MS
563 keyvalue[i ][0] = "UUID";
564 keyvalue[i++][1] = p->uuid + 9;
749b1e90 565
a2326b5b
MS
566#ifdef HAVE_SSL
567 keyvalue[i ][0] = "TLS";
568 keyvalue[i++][1] = "1.2";
569#endif /* HAVE_SSL */
749b1e90 570
a2326b5b
MS
571 keyvalue[i ][0] = "Transparent";
572 keyvalue[i++][1] = "F";
749b1e90 573
a2326b5b
MS
574 keyvalue[i ][0] = "Binary";
575 keyvalue[i++][1] = "F";
749b1e90 576
a2326b5b
MS
577 keyvalue[i ][0] = "Fax";
578 keyvalue[i++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F";
749b1e90 579
a2326b5b
MS
580 keyvalue[i ][0] = "Color";
581 keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLOR) ? "T" : "F";
749b1e90 582
a2326b5b
MS
583 keyvalue[i ][0] = "Duplex";
584 keyvalue[i++][1] = (p->type & CUPS_PRINTER_DUPLEX) ? "T" : "F";
749b1e90 585
a2326b5b
MS
586 keyvalue[i ][0] = "Staple";
587 keyvalue[i++][1] = (p->type & CUPS_PRINTER_STAPLE) ? "T" : "F";
749b1e90 588
a2326b5b
MS
589 keyvalue[i ][0] = "Copies";
590 keyvalue[i++][1] = (p->type & CUPS_PRINTER_COPIES) ? "T" : "F";
749b1e90 591
a2326b5b
MS
592 keyvalue[i ][0] = "Collate";
593 keyvalue[i++][1] = (p->type & CUPS_PRINTER_COLLATE) ? "T" : "F";
749b1e90 594
a2326b5b
MS
595 keyvalue[i ][0] = "Punch";
596 keyvalue[i++][1] = (p->type & CUPS_PRINTER_PUNCH) ? "T" : "F";
749b1e90 597
a2326b5b
MS
598 keyvalue[i ][0] = "Bind";
599 keyvalue[i++][1] = (p->type & CUPS_PRINTER_BIND) ? "T" : "F";
e1d6a774 600
a2326b5b
MS
601 keyvalue[i ][0] = "Sort";
602 keyvalue[i++][1] = (p->type & CUPS_PRINTER_SORT) ? "T" : "F";
e1d6a774 603
a2326b5b
MS
604 keyvalue[i ][0] = "Scan";
605 keyvalue[i++][1] = (p->type & CUPS_PRINTER_MFP) ? "T" : "F";
749b1e90 606
a2326b5b
MS
607 snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE);
608 snprintf(state_str, sizeof(state_str), "%d", p->state);
749b1e90 609
a2326b5b
MS
610 keyvalue[i ][0] = "printer-state";
611 keyvalue[i++][1] = state_str;
749b1e90 612
a2326b5b
MS
613 keyvalue[i ][0] = "printer-type";
614 keyvalue[i++][1] = type_str;
749b1e90 615
e1d6a774 616 /*
a2326b5b 617 * Then pack them into a proper txt record...
e1d6a774 618 */
619
a2326b5b
MS
620 return (dnssdPackTxtRecord(txt_len, keyvalue, i));
621}
e1d6a774 622
e1d6a774 623
a2326b5b
MS
624/*
625 * 'dnssdDeregisterPrinter()' - Stop sending broadcast information for a
626 * printer.
627 */
749b1e90 628
a2326b5b
MS
629static void
630dnssdDeregisterPrinter(
631 cupsd_printer_t *p) /* I - Printer */
632{
633 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdDeregisterPrinter(%s)", p->name);
749b1e90
MS
634
635 /*
a2326b5b 636 * Closing the socket deregisters the service
749b1e90
MS
637 */
638
a2326b5b 639 if (p->ipp_ref)
749b1e90 640 {
a2326b5b
MS
641 DNSServiceRefDeallocate(p->ipp_ref);
642 p->ipp_ref = NULL;
749b1e90
MS
643 }
644
a2326b5b 645 if (p->ipp_txt)
e1d6a774 646 {
647 /*
a2326b5b 648 * p->ipp_txt is malloc'd, not _cupsStrAlloc'd...
749b1e90
MS
649 */
650
a2326b5b
MS
651 free(p->ipp_txt);
652 p->ipp_txt = NULL;
653 }
749b1e90 654
a2326b5b
MS
655 if (p->printer_ref)
656 {
657 DNSServiceRefDeallocate(p->printer_ref);
658 p->printer_ref = NULL;
e1d6a774 659 }
a2326b5b
MS
660
661 if (p->printer_txt)
e1d6a774 662 {
663 /*
a2326b5b 664 * p->printer_txt is malloc'd, not _cupsStrAlloc'd...
e1d6a774 665 */
666
a2326b5b
MS
667 free(p->printer_txt);
668 p->printer_txt = NULL;
e1d6a774 669 }
749b1e90 670
a2326b5b
MS
671 /*
672 * Remove the printer from the array of DNS-SD printers, then clear the
673 * registered name...
674 */
675
676 cupsArrayRemove(DNSSDPrinters, p);
677 cupsdClearString(&p->reg_name);
e1d6a774 678}
749b1e90
MS
679
680
681/*
a2326b5b
MS
682 * 'dnssdPackTxtRecord()' - Pack an array of key/value pairs into the
683 * TXT record format.
749b1e90
MS
684 */
685
a2326b5b
MS
686static char * /* O - TXT record */
687dnssdPackTxtRecord(int *txt_len, /* O - TXT record length */
688 char *keyvalue[][2], /* I - Table of key value pairs */
689 int count) /* I - Items in table */
749b1e90 690{
a2326b5b
MS
691 int i; /* Looping var */
692 int length; /* Length of TXT record */
693 int length2; /* Length of value */
694 char *txtRecord; /* TXT record buffer */
695 char *cursor; /* Looping pointer */
749b1e90 696
749b1e90
MS
697
698 /*
a2326b5b 699 * Calculate the buffer size
749b1e90
MS
700 */
701
a2326b5b
MS
702 if (count <= 0)
703 return (NULL);
704
705 for (length = i = 0; i < count; i++)
706 length += 1 + strlen(keyvalue[i][0]) +
707 (keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0);
749b1e90
MS
708
709 /*
a2326b5b 710 * Allocate and fill it
749b1e90
MS
711 */
712
a2326b5b
MS
713 txtRecord = malloc(length);
714 if (txtRecord)
749b1e90 715 {
a2326b5b 716 *txt_len = length;
749b1e90 717
a2326b5b
MS
718 for (cursor = txtRecord, i = 0; i < count; i++)
719 {
720 /*
721 * Drop in the p-string style length byte followed by the data
722 */
723
724 length = strlen(keyvalue[i][0]);
725 length2 = keyvalue[i][1] ? 1 + strlen(keyvalue[i][1]) : 0;
726
727 *cursor++ = (unsigned char)(length + length2);
728
729 memcpy(cursor, keyvalue[i][0], length);
730 cursor += length;
749b1e90 731
a2326b5b
MS
732 if (length2)
733 {
734 length2 --;
735 *cursor++ = '=';
736 memcpy(cursor, keyvalue[i][1], length2);
737 cursor += length2;
738 }
749b1e90
MS
739 }
740 }
a2326b5b
MS
741
742 return (txtRecord);
749b1e90
MS
743}
744
745
ef55b745 746/*
a2326b5b 747 * 'dnssdRegisterCallback()' - DNSServiceRegister callback.
ef55b745
MS
748 */
749
749b1e90 750static void
a2326b5b
MS
751dnssdRegisterCallback(
752 DNSServiceRef sdRef, /* I - DNS Service reference */
753 DNSServiceFlags flags, /* I - Reserved for future use */
754 DNSServiceErrorType errorCode, /* I - Error code */
755 const char *name, /* I - Service name */
756 const char *regtype, /* I - Service type */
757 const char *domain, /* I - Domain. ".local" for now */
758 void *context) /* I - User-defined context */
749b1e90 759{
a2326b5b
MS
760 cupsd_printer_t *p = (cupsd_printer_t *)context;
761 /* Current printer */
749b1e90
MS
762
763
a2326b5b
MS
764 (void)sdRef;
765 (void)flags;
766 (void)domain;
749b1e90 767
a2326b5b
MS
768 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterCallback(%s, %s) for %s (%s)",
769 name, regtype, p ? p->name : "Web Interface",
770 p ? (p->reg_name ? p->reg_name : "(null)") : "NA");
749b1e90 771
a2326b5b 772 if (errorCode)
749b1e90 773 {
a2326b5b
MS
774 cupsdLogMessage(CUPSD_LOG_ERROR,
775 "DNSServiceRegister failed with error %d", (int)errorCode);
749b1e90
MS
776 return;
777 }
a2326b5b 778 else if (p && (!p->reg_name || _cups_strcasecmp(name, p->reg_name)))
749b1e90 779 {
a2326b5b
MS
780 cupsdLogMessage(CUPSD_LOG_INFO, "Using service name \"%s\" for \"%s\"",
781 name, p->name);
749b1e90 782
a2326b5b
MS
783 cupsArrayRemove(DNSSDPrinters, p);
784 cupsdSetString(&p->reg_name, name);
785 cupsArrayAdd(DNSSDPrinters, p);
749b1e90 786
a2326b5b 787 LastEvent |= CUPSD_EVENT_PRINTER_MODIFIED;
749b1e90
MS
788 }
789}
e1d6a774 790
791
e1d6a774 792/*
a2326b5b
MS
793 * 'dnssdRegisterPrinter()' - Start sending broadcast information for a printer
794 * or update the broadcast contents.
e1d6a774 795 */
796
797static void
a2326b5b 798dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */
e1d6a774 799{
a2326b5b
MS
800 DNSServiceErrorType se; /* dnssd errors */
801 char *ipp_txt, /* IPP TXT record buffer */
802 *printer_txt, /* LPD TXT record buffer */
803 name[1024], /* Service name */
804 *nameptr; /* Pointer into name */
805 int ipp_len, /* IPP TXT record length */
806 printer_len, /* LPD TXT record length */
807 printer_port; /* LPD port number */
808 const char *regtype; /* Registration type */
e1d6a774 809
e1d6a774 810
a2326b5b
MS
811 cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name,
812 !p->ipp_ref ? "new" : "update");
e1d6a774 813
814 /*
a2326b5b
MS
815 * If per-printer sharing was just disabled make sure we're not
816 * registered before returning.
e1d6a774 817 */
818
a2326b5b 819 if (!p->shared)
e1d6a774 820 {
a2326b5b
MS
821 dnssdDeregisterPrinter(p);
822 return;
e1d6a774 823 }
824
a2326b5b
MS
825 /*
826 * The registered name takes the form of "<printer-info> @ <computer name>"...
827 */
e1d6a774 828
a2326b5b 829 if (p->info && strlen(p->info) > 0)
e1d6a774 830 {
a2326b5b
MS
831 if (DNSSDComputerName)
832 snprintf(name, sizeof(name), "%s @ %s", p->info, DNSSDComputerName);
e1d6a774 833 else
a2326b5b 834 strlcpy(name, p->info, sizeof(name));
e1d6a774 835 }
a2326b5b
MS
836 else if (DNSSDComputerName)
837 snprintf(name, sizeof(name), "%s @ %s", p->name, DNSSDComputerName);
838 else
839 strlcpy(name, p->name, sizeof(name));
e1d6a774 840
841 /*
a2326b5b 842 * If an existing printer was renamed, unregister it and start over...
e1d6a774 843 */
844
a2326b5b
MS
845 if (p->reg_name && strcmp(p->reg_name, name))
846 dnssdDeregisterPrinter(p);
e1d6a774 847
a2326b5b 848 if (!p->reg_name)
e1d6a774 849 {
a2326b5b
MS
850 cupsdSetString(&p->reg_name, name);
851 cupsArrayAdd(DNSSDPrinters, p);
e1d6a774 852 }
853
e1d6a774 854 /*
a2326b5b 855 * Register IPP and (optionally) LPD...
e1d6a774 856 */
857
a2326b5b
MS
858 ipp_len = 0; /* anti-compiler-warning-code */
859 ipp_txt = dnssdBuildTxtRecord(&ipp_len, p, 0);
e1d6a774 860
a2326b5b
MS
861 if (p->ipp_ref &&
862 (ipp_len != p->ipp_len || memcmp(ipp_txt, p->ipp_txt, ipp_len)))
863 {
864 /*
865 * Update the existing registration...
866 */
ef416fc2 867
a2326b5b
MS
868 /* A TTL of 0 means use record's original value (Radar 3176248) */
869 if ((se = DNSServiceUpdateRecord(p->ipp_ref, NULL, 0, ipp_len, ipp_txt,
870 0)) == kDNSServiceErr_NoError)
871 {
872 if (p->ipp_txt)
873 free(p->ipp_txt);
ef416fc2 874
a2326b5b
MS
875 p->ipp_txt = ipp_txt;
876 p->ipp_len = ipp_len;
877 ipp_txt = NULL;
878 }
879 else
880 {
881 /*
882 * Failed to update record, lets close this reference and move on...
883 */
ef416fc2 884
a2326b5b
MS
885 cupsdLogMessage(CUPSD_LOG_ERROR,
886 "Unable to update IPP DNS-SD record for %s - %d", p->name,
887 se);
ef416fc2 888
a2326b5b
MS
889 DNSServiceRefDeallocate(p->ipp_ref);
890 p->ipp_ref = NULL;
891 }
892 }
ef416fc2 893
a2326b5b
MS
894 if (!p->ipp_ref)
895 {
896 /*
897 * Initial registration. Use the _fax-ipp regtype for fax queues...
898 */
ef416fc2 899
a2326b5b 900 regtype = (p->type & CUPS_PRINTER_FAX) ? "_fax-ipp._tcp" : DNSSDRegType;
ef416fc2 901
a2326b5b
MS
902 cupsdLogMessage(CUPSD_LOG_DEBUG,
903 "Registering DNS-SD printer %s with name \"%s\" and "
904 "type \"%s\"", p->name, name, regtype);
ef416fc2 905
a2326b5b
MS
906 /*
907 * Register the queue, dropping characters as needed until we succeed...
908 */
ef416fc2 909
a2326b5b 910 nameptr = name + strlen(name);
ef416fc2 911
a2326b5b
MS
912 do
913 {
914 p->ipp_ref = DNSSDRef;
915 if ((se = DNSServiceRegister(&p->ipp_ref, kDNSServiceFlagsShareConnection,
916 0, name, regtype, NULL, NULL,
917 htons(DNSSDPort), ipp_len, ipp_txt,
918 dnssdRegisterCallback,
919 p)) == kDNSServiceErr_BadParam)
920 {
921 /*
922 * Name is too long, drop trailing characters, taking into account
923 * UTF-8 encoding...
924 */
ef416fc2 925
a2326b5b 926 nameptr --;
ef416fc2 927
a2326b5b
MS
928 while (nameptr > name && (*nameptr & 0xc0) == 0x80)
929 nameptr --;
ef416fc2 930
a2326b5b
MS
931 if (nameptr > name)
932 *nameptr = '\0';
933 }
934 }
935 while (se == kDNSServiceErr_BadParam && nameptr > name);
ef416fc2 936
a2326b5b
MS
937 if (se == kDNSServiceErr_NoError)
938 {
939 p->ipp_txt = ipp_txt;
940 p->ipp_len = ipp_len;
941 ipp_txt = NULL;
942 }
943 else
944 cupsdLogMessage(CUPSD_LOG_WARN,
945 "DNS-SD IPP registration of \"%s\" failed: %d",
946 p->name, se);
947 }
ef416fc2 948
a2326b5b
MS
949 if (ipp_txt)
950 free(ipp_txt);
ef416fc2 951
a2326b5b 952 if (BrowseLocalProtocols & BROWSE_LPD)
ef416fc2 953 {
a2326b5b
MS
954 printer_len = 0; /* anti-compiler-warning-code */
955 printer_port = 515;
956 printer_txt = dnssdBuildTxtRecord(&printer_len, p, 1);
957 }
958 else
959 {
960 printer_len = 0;
961 printer_port = 0;
962 printer_txt = NULL;
963 }
ef416fc2 964
a2326b5b
MS
965 if (p->printer_ref &&
966 (printer_len != p->printer_len ||
967 memcmp(printer_txt, p->printer_txt, printer_len)))
968 {
ef416fc2 969 /*
a2326b5b 970 * Update the existing registration...
ef416fc2 971 */
972
a2326b5b
MS
973 /* A TTL of 0 means use record's original value (Radar 3176248) */
974 if ((se = DNSServiceUpdateRecord(p->printer_ref, NULL, 0, printer_len,
975 printer_txt,
976 0)) == kDNSServiceErr_NoError)
977 {
978 if (p->printer_txt)
979 free(p->printer_txt);
ef416fc2 980
a2326b5b
MS
981 p->printer_txt = printer_txt;
982 p->printer_len = printer_len;
983 printer_txt = NULL;
984 }
985 else
ef416fc2 986 {
987 /*
a2326b5b 988 * Failed to update record, lets close this reference and move on...
ef416fc2 989 */
990
a2326b5b
MS
991 cupsdLogMessage(CUPSD_LOG_ERROR,
992 "Unable to update LPD DNS-SD record for %s - %d",
993 p->name, se);
ef416fc2 994
a2326b5b
MS
995 DNSServiceRefDeallocate(p->printer_ref);
996 p->printer_ref = NULL;
ef416fc2 997 }
998 }
999
a2326b5b
MS
1000 if (!p->printer_ref)
1001 {
1002 /*
1003 * Initial registration...
1004 */
ef416fc2 1005
a2326b5b
MS
1006 cupsdLogMessage(CUPSD_LOG_DEBUG,
1007 "Registering DNS-SD printer %s with name \"%s\" and "
1008 "type \"_printer._tcp\"", p->name, name);
ef416fc2 1009
a2326b5b
MS
1010 p->printer_ref = DNSSDRef;
1011 if ((se = DNSServiceRegister(&p->printer_ref,
1012 kDNSServiceFlagsShareConnection,
1013 0, name, "_printer._tcp", NULL, NULL,
1014 htons(printer_port), printer_len, printer_txt,
1015 dnssdRegisterCallback,
1016 p)) == kDNSServiceErr_NoError)
1017 {
1018 p->printer_txt = printer_txt;
1019 p->printer_len = printer_len;
1020 printer_txt = NULL;
1021 }
1022 else
1023 cupsdLogMessage(CUPSD_LOG_WARN,
1024 "DNS-SD LPD registration of \"%s\" failed: %d",
1025 p->name, se);
1026 }
ef416fc2 1027
a2326b5b
MS
1028 if (printer_txt)
1029 free(printer_txt);
ef416fc2 1030}
1031
1032
1033/*
a2326b5b 1034 * 'dnssdStop()' - Stop all DNS-SD registrations.
ef416fc2 1035 */
1036
a2326b5b
MS
1037static void
1038dnssdStop(void)
ef416fc2 1039{
a2326b5b 1040 cupsd_printer_t *p; /* Current printer */
ef416fc2 1041
1042
1043 /*
a2326b5b 1044 * De-register the individual printers
ef416fc2 1045 */
1046
a2326b5b
MS
1047 for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
1048 p;
1049 p = (cupsd_printer_t *)cupsArrayNext(Printers))
1050 dnssdDeregisterPrinter(p);
ef416fc2 1051
1052 /*
a2326b5b 1053 * Shutdown the rest of the service refs...
ef416fc2 1054 */
1055
a2326b5b
MS
1056 if (WebIFRef)
1057 {
1058 DNSServiceRefDeallocate(WebIFRef);
1059 WebIFRef = NULL;
1060 }
ef416fc2 1061
a2326b5b 1062 cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDRef));
ef416fc2 1063
a2326b5b
MS
1064 DNSServiceRefDeallocate(DNSSDRef);
1065 DNSSDRef = NULL;
ef416fc2 1066
a2326b5b
MS
1067 cupsArrayDelete(DNSSDPrinters);
1068 DNSSDPrinters = NULL;
ef416fc2 1069
a2326b5b
MS
1070 DNSSDPort = 0;
1071}
ef416fc2 1072
ef416fc2 1073
a2326b5b
MS
1074/*
1075 * 'dnssdUpdate()' - Handle DNS-SD queries.
1076 */
ef416fc2 1077
a2326b5b
MS
1078static void
1079dnssdUpdate(void)
1080{
1081 DNSServiceErrorType sdErr; /* Service discovery error */
ef416fc2 1082
ef416fc2 1083
a2326b5b
MS
1084 if ((sdErr = DNSServiceProcessResult(DNSSDRef)) != kDNSServiceErr_NoError)
1085 {
1086 cupsdLogMessage(CUPSD_LOG_ERROR,
1087 "DNS Service Discovery registration error %d!",
1088 sdErr);
1089 dnssdStop();
1090 }
ef416fc2 1091}
ef416fc2 1092
1093
1094/*
a2326b5b 1095 * 'get_auth_info_required()' - Get the auth-info-required value to advertise.
f899b121 1096 */
1097
a2326b5b
MS
1098static char * /* O - String or NULL if none */
1099get_auth_info_required(
1100 cupsd_printer_t *p, /* I - Printer */
1101 char *buffer, /* I - Value buffer */
1102 size_t bufsize) /* I - Size of value buffer */
f899b121 1103{
a2326b5b
MS
1104 cupsd_location_t *auth; /* Pointer to authentication element */
1105 char resource[1024]; /* Printer/class resource path */
f899b121 1106
1107
1108 /*
a2326b5b 1109 * If auth-info-required is set for this printer, return that...
f899b121 1110 */
1111
a2326b5b 1112 if (p->num_auth_info_required > 0 && strcmp(p->auth_info_required[0], "none"))
f899b121 1113 {
a2326b5b
MS
1114 int i; /* Looping var */
1115 char *bufptr; /* Pointer into buffer */
f899b121 1116
a2326b5b 1117 for (i = 0, bufptr = buffer; i < p->num_auth_info_required; i ++)
f899b121 1118 {
a2326b5b
MS
1119 if (bufptr >= (buffer + bufsize - 2))
1120 break;
7a14d768 1121
a2326b5b
MS
1122 if (i)
1123 *bufptr++ = ',';
f899b121 1124
a2326b5b
MS
1125 strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer));
1126 bufptr += strlen(bufptr);
f899b121 1127 }
1128
a2326b5b 1129 return (buffer);
f899b121 1130 }
1131
f899b121 1132 /*
a2326b5b 1133 * Figure out the authentication data requirements to advertise...
f899b121 1134 */
1135
a2326b5b
MS
1136 if (p->type & CUPS_PRINTER_CLASS)
1137 snprintf(resource, sizeof(resource), "/classes/%s", p->name);
f899b121 1138 else
a2326b5b 1139 snprintf(resource, sizeof(resource), "/printers/%s", p->name);
f899b121 1140
a2326b5b
MS
1141 if ((auth = cupsdFindBest(resource, HTTP_POST)) == NULL ||
1142 auth->type == CUPSD_AUTH_NONE)
1143 auth = cupsdFindPolicyOp(p->op_policy_ptr, IPP_PRINT_JOB);
f899b121 1144
a2326b5b 1145 if (auth)
f899b121 1146 {
a2326b5b 1147 int auth_type; /* Authentication type */
f899b121 1148
a2326b5b 1149 if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT)
dcb445bc 1150 auth_type = cupsdDefaultAuthType();
f899b121 1151
a2326b5b
MS
1152 switch (auth_type)
1153 {
1154 case CUPSD_AUTH_NONE :
1155 return (NULL);
f899b121 1156
a2326b5b
MS
1157 case CUPSD_AUTH_NEGOTIATE :
1158 strlcpy(buffer, "negotiate", bufsize);
1159 break;
f899b121 1160
a2326b5b
MS
1161 default :
1162 strlcpy(buffer, "username,password", bufsize);
1163 break;
1164 }
f899b121 1165
a2326b5b
MS
1166 return (buffer);
1167 }
f899b121 1168
a2326b5b
MS
1169 return ("none");
1170}
dcb445bc 1171#endif /* HAVE_DNSSD */
f899b121 1172
f899b121 1173
a2326b5b
MS
1174#ifdef __APPLE__
1175/*
1176 * 'get_hostconfig()' - Get an /etc/hostconfig service setting.
1177 */
f899b121 1178
a2326b5b
MS
1179static int /* O - 1 for YES or AUTOMATIC, 0 for NO */
1180get_hostconfig(const char *name) /* I - Name of service */
1181{
1182 cups_file_t *fp; /* Hostconfig file */
1183 char line[1024], /* Line from file */
1184 *ptr; /* Pointer to value */
1185 int state = 1; /* State of service */
f899b121 1186
f899b121 1187
1188 /*
a2326b5b
MS
1189 * Try opening the /etc/hostconfig file; if we can't open it, assume that
1190 * the service is enabled/auto.
f899b121 1191 */
1192
a2326b5b 1193 if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL)
f899b121 1194 {
1195 /*
a2326b5b 1196 * Read lines from the file until we find the service...
f899b121 1197 */
1198
a2326b5b 1199 while (cupsFileGets(fp, line, sizeof(line)))
f899b121 1200 {
a2326b5b
MS
1201 if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL)
1202 continue;
f899b121 1203
a2326b5b 1204 *ptr++ = '\0';
f899b121 1205
a2326b5b 1206 if (!_cups_strcasecmp(line, name))
f899b121 1207 {
a2326b5b
MS
1208 /*
1209 * Found the service, see if it is set to "-NO-"...
1210 */
f899b121 1211
a2326b5b
MS
1212 if (!_cups_strncasecmp(ptr, "-NO-", 4))
1213 state = 0;
1214 break;
f899b121 1215 }
1216 }
f899b121 1217
a2326b5b 1218 cupsFileClose(fp);
f899b121 1219 }
1220
a2326b5b 1221 return (state);
f899b121 1222}
a2326b5b 1223#endif /* __APPLE__ */
f899b121 1224
1225
2e4ff8af
MS
1226/*
1227 * 'update_lpd()' - Update the LPD configuration as needed.
1228 */
1229
1230static void
1231update_lpd(int onoff) /* - 1 = turn on, 0 = turn off */
1232{
1233 if (!LPDConfigFile)
1234 return;
1235
a603edef
MS
1236#ifdef __APPLE__
1237 /*
1238 * Allow /etc/hostconfig CUPS_LPD service setting to override cupsd.conf
1239 * setting for backwards-compatibility.
1240 */
1241
1242 if (onoff && !get_hostconfig("CUPS_LPD"))
1243 onoff = 0;
1244#endif /* __APPLE__ */
1245
2e4ff8af
MS
1246 if (!strncmp(LPDConfigFile, "xinetd:///", 10))
1247 {
1248 /*
1249 * Enable/disable LPD via the xinetd.d config file for cups-lpd...
1250 */
1251
1252 char newfile[1024]; /* New cups-lpd.N file */
1253 cups_file_t *ofp, /* Original file pointer */
1254 *nfp; /* New file pointer */
1255 char line[1024]; /* Line from file */
1256
1257
1258 snprintf(newfile, sizeof(newfile), "%s.N", LPDConfigFile + 9);
1259
1260 if ((ofp = cupsFileOpen(LPDConfigFile + 9, "r")) == NULL)
1261 {
1262 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s",
1263 LPDConfigFile + 9, strerror(errno));
1264 return;
1265 }
1266
1267 if ((nfp = cupsFileOpen(newfile, "w")) == NULL)
1268 {
1269 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s",
1270 newfile, strerror(errno));
1271 cupsFileClose(ofp);
1272 return;
1273 }
1274
1275 /*
1276 * Copy all of the lines from the cups-lpd file...
1277 */
1278
1279 while (cupsFileGets(ofp, line, sizeof(line)))
1280 {
1281 if (line[0] == '{')
1282 {
1283 cupsFilePrintf(nfp, "%s\n", line);
1284 snprintf(line, sizeof(line), "\tdisable = %s",
1285 onoff ? "no" : "yes");
1286 }
568fa3fa
MS
1287 else if (!strstr(line, "disable ="))
1288 cupsFilePrintf(nfp, "%s\n", line);
2e4ff8af
MS
1289 }
1290
1291 cupsFileClose(nfp);
1292 cupsFileClose(ofp);
1293 rename(newfile, LPDConfigFile + 9);
1294 }
568fa3fa 1295#ifdef __APPLE__
2e4ff8af
MS
1296 else if (!strncmp(LPDConfigFile, "launchd:///", 11))
1297 {
1298 /*
1299 * Enable/disable LPD via the launchctl command...
1300 */
1301
1302 char *argv[5], /* Arguments for command */
1303 *envp[MAX_ENV]; /* Environment for command */
1304 int pid; /* Process ID */
1305
1306
1307 cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
1308 argv[0] = (char *)"launchctl";
1309 argv[1] = (char *)(onoff ? "load" : "unload");
1310 argv[2] = (char *)"-w";
1311 argv[3] = LPDConfigFile + 10;
1312 argv[4] = NULL;
1313
a4924f6c 1314 cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1,
38e73f87 1315 NULL, NULL, &pid);
2e4ff8af 1316 }
568fa3fa
MS
1317#endif /* __APPLE__ */
1318 else
1319 cupsdLogMessage(CUPSD_LOG_INFO, "Unknown LPDConfigFile scheme!");
2e4ff8af
MS
1320}
1321
1322
f899b121 1323/*
2e4ff8af
MS
1324 * 'update_smb()' - Update the SMB configuration as needed.
1325 */
1326
1327static void
1328update_smb(int onoff) /* I - 1 = turn on, 0 = turn off */
1329{
1330 if (!SMBConfigFile)
1331 return;
1332
1333 if (!strncmp(SMBConfigFile, "samba:///", 9))
1334 {
1335 /*
1336 * Enable/disable SMB via the specified smb.conf config file...
1337 */
1338
1339 char newfile[1024]; /* New smb.conf.N file */
1340 cups_file_t *ofp, /* Original file pointer */
1341 *nfp; /* New file pointer */
1342 char line[1024]; /* Line from file */
1343 int in_printers; /* In [printers] section? */
1344
1345
1346 snprintf(newfile, sizeof(newfile), "%s.N", SMBConfigFile + 8);
1347
1348 if ((ofp = cupsFileOpen(SMBConfigFile + 8, "r")) == NULL)
1349 {
1350 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s",
1351 SMBConfigFile + 8, strerror(errno));
1352 return;
1353 }
1354
1355 if ((nfp = cupsFileOpen(newfile, "w")) == NULL)
1356 {
1357 cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s",
1358 newfile, strerror(errno));
1359 cupsFileClose(ofp);
1360 return;
1361 }
1362
1363 /*
1364 * Copy all of the lines from the smb.conf file...
1365 */
1366
1367 in_printers = 0;
1368
1369 while (cupsFileGets(ofp, line, sizeof(line)))
1370 {
1371 if (in_printers && strstr(line, "printable ="))
1372 snprintf(line, sizeof(line), " printable = %s",
1373 onoff ? "yes" : "no");
1374
1375 cupsFilePrintf(nfp, "%s\n", line);
1376
1377 if (line[0] == '[')
1378 in_printers = !strcmp(line, "[printers]");
1379 }
1380
1381 cupsFileClose(nfp);
1382 cupsFileClose(ofp);
1383 rename(newfile, SMBConfigFile + 8);
1384 }
568fa3fa
MS
1385 else
1386 cupsdLogMessage(CUPSD_LOG_INFO, "Unknown SMBConfigFile scheme!");
2e4ff8af
MS
1387}
1388
1389
1390/*
b19ccc9e 1391 * End of "$Id: dirsvc.c 7933 2008-09-11 00:44:58Z mike $".
ef416fc2 1392 */