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