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