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