]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/dirsvc.c
Merge changes from 1.1.x into 1.2 devel.
[thirdparty/cups.git] / scheduler / dirsvc.c
CommitLineData
a129ddbd 1/*
753453e4 2 * "$Id: dirsvc.c,v 1.73.2.3 2001/12/26 16:52:52 mike Exp $"
a129ddbd 3 *
d6de4648 4 * Directory services routines for the Common UNIX Printing System (CUPS).
a129ddbd 5 *
d2935a0f 6 * Copyright 1997-2001 by Easy Software Products, all rights reserved.
a129ddbd 7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
8784b6a6 17 * 44141 Airport View Drive, Suite 204
a129ddbd 18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
753453e4 26 * ProcessBrowseData() - Process new browse data.
27 * SendBrowseList() - Send new browsing information as necessary.
28 * SendCUPSBrowse() - Send new browsing information using the CUPS protocol.
29 * StartBrowsing() - Start sending and receiving broadcast information.
30 * StartPolling() - Start polling servers as needed.
31 * StopBrowsing() - Stop sending and receiving broadcast information.
32 * StopPolling() - Stop polling servers as needed.
33 * UpdateCUPSBrowse() - Update the browse lists using the CUPS protocol.
34 * RegReportCallback() - Empty SLPRegReport.
35 * SendSLPBrowse() - Register the specified printer with SLP.
36 * SLPDeregPrinter() - SLPDereg() the specified printer
37 * GetSlpAttrVal() - Get an attribute from an SLP registration.
38 * AttrCallback() - SLP attribute callback
39 * SrvUrlCallback() - SLP service url callback
40 * UpdateSLPBrowse() - Get browsing information via SLP.
a129ddbd 41 */
42
43/*
44 * Include necessary headers...
45 */
46
fd8b1cf8 47#include "cupsd.h"
7a91f14b 48#include <grp.h>
fd8b1cf8 49
50
753453e4 51/*
52 * 'ProcessBrowseData()' - Process new browse data.
53 */
54
55void
56ProcessBrowseData(const char *uri, /* I - URI of printer/class */
57 cups_ptype_t type, /* I - Printer type */
58 ipp_pstate_t state, /* I - Printer state */
59 const char *location,/* I - Printer location */
60 const char *info, /* I - Printer information */
61 const char *make_model) /* I - Printer make and model */
62{
63 int i; /* Looping var */
64 int update; /* Update printer attributes? */
65 char method[HTTP_MAX_URI], /* Method portion of URI */
66 username[HTTP_MAX_URI], /* Username portion of URI */
67 host[HTTP_MAX_URI], /* Host portion of URI */
68 resource[HTTP_MAX_URI]; /* Resource portion of URI */
69 int port; /* Port portion of URI */
70 char name[IPP_MAX_NAME], /* Name of printer */
71 *hptr, /* Pointer into hostname */
72 *sptr; /* Pointer into ServerName */
73 char local_make_model[IPP_MAX_NAME];
74 /* Local make and model */
75 printer_t *p, /* Printer information */
76 *pclass, /* Printer class */
77 *first, /* First printer in class */
78 *next; /* Next printer in list */
79 int offset, /* Offset of name */
80 len; /* Length of name */
81
82
83 /*
84 * Pull the URI apart to see if this is a local or remote printer...
85 */
86
87 httpSeparate(uri, method, username, host, &port, resource);
88
89 /*
90 * OK, this isn't a local printer; see if we already have it listed in
91 * the Printers list, and add it if not...
92 */
93
94 update = 0;
95 hptr = strchr(host, '.');
96 sptr = strchr(ServerName, '.');
97
98 if (sptr != NULL && hptr != NULL)
99 {
100 /*
101 * Strip the common domain name components...
102 */
103
104 while (hptr != NULL)
105 {
106 if (strcasecmp(hptr, sptr) == 0)
107 {
108 *hptr = '\0';
109 break;
110 }
111 else
112 hptr = strchr(hptr + 1, '.');
113 }
114 }
115
116 if (type & CUPS_PRINTER_CLASS)
117 {
118 /*
119 * Remote destination is a class...
120 */
121
122 if (strncmp(resource, "/classes/", 9) == 0)
123 snprintf(name, sizeof(name), "%s@%s", resource + 9, host);
124 else
125 return;
126
127 if ((p = FindClass(name)) == NULL && BrowseShortNames)
128 {
129 if ((p = FindClass(resource + 9)) != NULL)
130 {
131 if (strcasecmp(p->hostname, host) != 0 && p->hostname[0])
132 {
133 /*
134 * Nope, this isn't the same host; if the hostname isn't the local host,
135 * add it to the other class and then find a class using the full host
136 * name...
137 */
138
139 if (p->type & CUPS_PRINTER_REMOTE)
140 {
141 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
142 strncat(p->name, "@", sizeof(p->name) - 1);
143 strncat(p->name, p->hostname, sizeof(p->name) - 1);
144 SetPrinterAttrs(p);
145 SortPrinters();
146 }
147
148 p = NULL;
149 }
150 else if (!p->hostname[0])
151 {
152 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
153 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
154 strncpy(p->uri, uri, sizeof(p->uri) - 1);
155 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
156 update = 1;
157 }
158 }
159 else
160 {
161 strncpy(name, resource + 9, sizeof(name) - 1);
162 name[sizeof(name) - 1] = '\0';
163 }
164 }
165 else if (p != NULL && !p->hostname[0])
166 {
167 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
168 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
169 strncpy(p->uri, uri, sizeof(p->uri) - 1);
170 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
171 update = 1;
172 }
173
174 if (p == NULL)
175 {
176 /*
177 * Class doesn't exist; add it...
178 */
179
180 p = AddClass(name);
181
182 LogMessage(L_INFO, "Added remote class \"%s\"...", name);
183
184 /*
185 * Force the URI to point to the real server...
186 */
187
188 p->type = type;
189 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
190 strncpy(p->uri, uri, sizeof(p->uri) - 1);
191 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
192 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
193
194 update = 1;
195 }
196 }
197 else
198 {
199 /*
200 * Remote destination is a printer...
201 */
202
203 if (strncmp(resource, "/printers/", 10) == 0)
204 snprintf(name, sizeof(name), "%s@%s", resource + 10, host);
205 else
206 return;
207
208 if ((p = FindPrinter(name)) == NULL && BrowseShortNames)
209 {
210 if ((p = FindPrinter(resource + 10)) != NULL)
211 {
212 if (strcasecmp(p->hostname, host) != 0 && p->hostname[0])
213 {
214 /*
215 * Nope, this isn't the same host; if the hostname isn't the local host,
216 * add it to the other printer and then find a printer using the full host
217 * name...
218 */
219
220 if (p->type & CUPS_PRINTER_REMOTE)
221 {
222 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
223 strncat(p->name, "@", sizeof(p->name) - 1);
224 strncat(p->name, p->hostname, sizeof(p->name) - 1);
225 SetPrinterAttrs(p);
226 SortPrinters();
227 }
228
229 p = NULL;
230 }
231 else if (!p->hostname[0])
232 {
233 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
234 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
235 strncpy(p->uri, uri, sizeof(p->uri) - 1);
236 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
237 update = 1;
238 }
239 }
240 else
241 {
242 strncpy(name, resource + 10, sizeof(name) - 1);
243 name[sizeof(name) - 1] = '\0';
244 }
245 }
246 else if (p != NULL && !p->hostname[0])
247 {
248 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
249 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
250 strncpy(p->uri, uri, sizeof(p->uri) - 1);
251 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
252 update = 1;
253 }
254
255 if (p == NULL)
256 {
257 /*
258 * Printer doesn't exist; add it...
259 */
260
261 p = AddPrinter(name);
262
263 LogMessage(L_INFO, "Added remote printer \"%s\"...", name);
264
265 /*
266 * Force the URI to point to the real server...
267 */
268
269 p->type = type;
270 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
271 strncpy(p->hostname, host, sizeof(p->hostname) - 1);
272 strncpy(p->uri, uri, sizeof(p->uri) - 1);
273 strncpy(p->device_uri, uri, sizeof(p->device_uri) - 1);
274
275 update = 1;
276 }
277 }
278
279 /*
280 * Update the state...
281 */
282
283 p->state = state;
284 p->accepting = state != IPP_PRINTER_STOPPED;
285 p->browse_time = time(NULL);
286
287 if (p->type != type)
288 {
289 p->type = type;
290 update = 1;
291 }
292
293 if (strcmp(p->location, location))
294 {
295 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
296 strncpy(p->location, location, sizeof(p->location) - 1);
297 update = 1;
298 }
299
300 if (strcmp(p->info, info))
301 {
302 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
303 strncpy(p->info, info, sizeof(p->info) - 1);
304 update = 1;
305 }
306
307 if (!make_model[0])
308 {
309 if (type & CUPS_PRINTER_CLASS)
310 snprintf(local_make_model, sizeof(local_make_model),
311 "Remote Class on %s", host);
312 else
313 snprintf(local_make_model, sizeof(local_make_model),
314 "Remote Printer on %s", host);
315 }
316 else
317 snprintf(local_make_model, sizeof(local_make_model),
318 "%s on %s", make_model, host);
319
320 if (strcmp(p->make_model, local_make_model))
321 {
322 /* No "p->var[sizeof(p->var) - 1] = '\0';" because p is zeroed */
323 strncpy(p->make_model, local_make_model, sizeof(p->make_model) - 1);
324 update = 1;
325 }
326
327 if (update)
328 SetPrinterAttrs(p);
329
330 /*
331 * See if we have a default printer... If not, make the first printer the
332 * default.
333 */
334
335 if (DefaultPrinter == NULL && Printers != NULL)
336 DefaultPrinter = Printers;
337
338 /*
339 * Do auto-classing if needed...
340 */
341
342 if (ImplicitClasses)
343 {
344 /*
345 * Loop through all available printers and create classes as needed...
346 */
347
348 for (p = Printers, len = 0, offset = 0, first = NULL;
349 p != NULL;
350 p = next)
351 {
352 /*
353 * Get next printer in list...
354 */
355
356 next = p->next;
357
358 /*
359 * Skip classes...
360 */
361
362 if (p->type & (CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_CLASS))
363 {
364 len = 0;
365 continue;
366 }
367
368 /*
369 * If len == 0, get the length of this printer name up to the "@"
370 * sign (if any).
371 */
372
373 if (len > 0 &&
374 strncasecmp(p->name, name + offset, len) == 0 &&
375 (p->name[len] == '\0' || p->name[len] == '@'))
376 {
377 /*
378 * We have more than one printer with the same name; see if
379 * we have a class, and if this printer is a member...
380 */
381
382 if ((pclass = FindPrinter(name)) == NULL)
383 {
384 /*
385 * Need to add the class...
386 */
387
388 pclass = AddPrinter(name);
389 pclass->type |= CUPS_PRINTER_IMPLICIT;
390 pclass->accepting = 1;
391 pclass->state = IPP_PRINTER_IDLE;
392
393 SetPrinterAttrs(pclass);
394
395 LogMessage(L_INFO, "Added implicit class \"%s\"...", name);
396 }
397
398 if (first != NULL)
399 {
400 for (i = 0; i < pclass->num_printers; i ++)
401 if (pclass->printers[i] == first)
402 break;
403
404 if (i >= pclass->num_printers)
405 AddPrinterToClass(pclass, first);
406
407 first = NULL;
408 }
409
410 for (i = 0; i < pclass->num_printers; i ++)
411 if (pclass->printers[i] == p)
412 break;
413
414 if (i >= pclass->num_printers)
415 AddPrinterToClass(pclass, p);
416 }
417 else
418 {
419 /*
420 * First time around; just get name length and mark it as first
421 * in the list...
422 */
423
424 if ((hptr = strchr(p->name, '@')) != NULL)
425 len = hptr - p->name;
426 else
427 len = strlen(p->name);
428
429 strncpy(name, p->name, len);
430 name[len] = '\0';
431 offset = 0;
432
433 if ((pclass = FindPrinter(name)) != NULL &&
434 !(pclass->type & CUPS_PRINTER_IMPLICIT))
435 {
436 /*
437 * Can't use same name as a local printer; add "Any" to the
438 * front of the name, unless we have explicitly disabled
439 * the "ImplicitAnyClasses"...
440 */
441
442 if (ImplicitAnyClasses)
443 {
444 /*
445 * Add "Any" to the class name...
446 */
447
448 strcpy(name, "Any");
449 strncpy(name + 3, p->name, len);
450 name[len + 3] = '\0';
451 offset = 3;
452 }
453 else
454 {
455 /*
456 * Don't create an implicit class if we have a local printer
457 * with the same name...
458 */
459
460 len = 0;
461 continue;
462 }
463 }
464
465 first = p;
466 }
467 }
468 }
469}
470
471
472/*
473 * 'SendBrowseList()' - Send new browsing information as necessary.
474 */
475
476void
477SendBrowseList(void)
478{
479 printer_t *p, /* Current printer */
480 *np; /* Next printer */
481 time_t ut, /* Minimum update time */
482 to; /* Timeout time */
483
484
485 if (!Browsing || !(BrowseProtocols & BROWSE_CUPS))
486 return;
487
488 /*
489 * Compute the update and timeout times...
490 */
491
492 ut = time(NULL) - BrowseInterval;
493 to = time(NULL) - BrowseTimeout;
494
495 /*
496 * Loop through all of the printers and send local updates as needed...
497 */
498
499 for (p = Printers; p != NULL; p = np)
500 {
501 np = p->next;
502
503 if (p->type & CUPS_PRINTER_REMOTE)
504 {
505 /*
506 * See if this printer needs to be timed out...
507 */
508
509 if (p->browse_time < to)
510 {
511 LogMessage(L_INFO, "Remote destination \"%s\" has timed out; deleting it...",
512 p->name);
513 DeletePrinter(p);
514 }
515 }
516 else if (p->browse_time < ut && BrowseInterval > 0 &&
517 !(p->type & CUPS_PRINTER_IMPLICIT))
518 {
519 /*
520 * Need to send an update...
521 */
522
523 p->browse_time = time(NULL);
524
525 if (BrowseProtocols & BROWSE_CUPS)
526 SendCUPSBrowse(p);
527
528#ifdef HAVE_LIBSLP
529 if (BrowseProtocols & BROWSE_SLP)
530 SendSLPBrowse(p);
531#endif /* HAVE_LIBSLP */
532 }
533 }
534}
535
536
537/*
538 * 'SendCUPSBrowse()' - Send new browsing information using the CUPS protocol.
539 */
540
541void
542SendCUPSBrowse(printer_t *p) /* I - Printer to send */
543{
544 int i; /* Looping var */
545 int bytes; /* Length of packet */
546 char packet[1453];
547 /* Browse data packet */
548
549
550 snprintf(packet, sizeof(packet), "%x %x %s \"%s\" \"%s\" \"%s\"\n",
551 p->type | CUPS_PRINTER_REMOTE, p->state, p->uri,
552 p->location, p->info, p->make_model);
553
554 bytes = strlen(packet);
555 LogMessage(L_DEBUG2, "SendBrowseList: (%d bytes) %s", bytes, packet);
556
557 /*
558 * Send a packet to each browse address...
559 */
560
561 for (i = 0; i < NumBrowsers; i ++)
562 if (sendto(BrowseSocket, packet, bytes, 0,
563 (struct sockaddr *)Browsers + i, sizeof(Browsers[0])) <= 0)
564 {
565 LogMessage(L_ERROR, "SendBrowseList: sendto failed for browser %d - %s.",
566 i + 1, strerror(errno));
567 LogMessage(L_ERROR, "Browsing turned off.");
568
569 StopBrowsing();
570 Browsing = 0;
571 return;
572 }
573}
574
575
d6de4648 576/*
577 * 'StartBrowsing()' - Start sending and receiving broadcast information.
578 */
579
fd8b1cf8 580void
581StartBrowsing(void)
582{
d6de4648 583 int val; /* Socket option value */
584 struct sockaddr_in addr; /* Broadcast address */
585
586
8828fd5f 587 if (!Browsing)
d6de4648 588 return;
589
753453e4 590 if (BrowseProtocols & BROWSE_CUPS)
591 {
592 /*
593 * Create the broadcast socket...
594 */
595
596 if ((BrowseSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
597 {
598 LogMessage(L_ERROR, "StartBrowsing: Unable to create broadcast socket - %s.",
599 strerror(errno));
600 Browsing = 0;
601 return;
602 }
603
604 /*
605 * Set the "broadcast" flag...
606 */
607
608 val = 1;
609 if (setsockopt(BrowseSocket, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val)))
610 {
611 LogMessage(L_ERROR, "StartBrowsing: Unable to set broadcast mode - %s.",
612 strerror(errno));
613
614 #if defined(WIN32) || defined(__EMX__)
615 closesocket(BrowseSocket);
616 #else
617 close(BrowseSocket);
618 #endif /* WIN32 || __EMX__ */
619
620 BrowseSocket = -1;
621 Browsing = 0;
622 return;
623 }
624
625 /*
626 * Bind the socket to browse port...
627 */
628
629 memset(&addr, 0, sizeof(addr));
630 addr.sin_addr.s_addr = htonl(INADDR_ANY);
631 addr.sin_family = AF_INET;
632 addr.sin_port = htons(BrowsePort);
633
634 if (bind(BrowseSocket, (struct sockaddr *)&addr, sizeof(addr)))
635 {
636 LogMessage(L_ERROR, "StartBrowsing: Unable to bind broadcast socket - %s.",
637 strerror(errno));
d6de4648 638
753453e4 639 #if defined(WIN32) || defined(__EMX__)
640 closesocket(BrowseSocket);
641 #else
642 close(BrowseSocket);
643 #endif /* WIN32 || __EMX__ */
644
645 BrowseSocket = -1;
646 Browsing = 0;
647 return;
648 }
649
650 /*
651 * Finally, add the socket to the input selection set...
652 */
653
654 LogMessage(L_DEBUG2, "StartBrowsing: Adding fd %d to InputSet...",
655 BrowseSocket);
656
657 FD_SET(BrowseSocket, &InputSet);
658 }
659
660#ifdef HAVE_LIBSLP
661 if (BrowseProtocols & BROWSE_SLP)
d6de4648 662 {
753453e4 663 /*
664 * Open SLP handle...
665 */
666
667 if (SLPOpen("en", SLP_FALSE, &BrowseSLPHandle) != SLP_OK)
668 {
669 LogMessage(L_ERROR, "Unable to open an SLP handle; disabling SLP browsing!");
670 BrowseProtocols &= ~BROWSE_SLP;
671 }
672
673 BrowseSLPRefresh = 0;
d6de4648 674 }
753453e4 675}
d6de4648 676
d6de4648 677
753453e4 678/*
679 * 'StartPolling()' - Start polling servers as needed.
680 */
681
682void
683StartPolling(void)
684{
685 int i; /* Looping var */
686 dirsvc_poll_t *poll; /* Current polling server */
687 int pid; /* New process ID */
688 char sport[10]; /* Server port */
689 char bport[10]; /* Browser port */
690 char interval[10]; /* Poll interval */
691
692
693 sprintf(bport, "%d", BrowsePort);
694
695 if (BrowseInterval)
696 sprintf(interval, "%d", BrowseInterval);
697 else
698 strcpy(interval, "30");
699
700 for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
fd3ece61 701 {
753453e4 702 sprintf(sport, "%d", poll->port);
fd3ece61 703
753453e4 704 if ((pid = fork()) == 0)
705 {
706 /*
707 * Child...
708 */
fd3ece61 709
753453e4 710 if (getuid() == 0)
711 {
712 /*
713 * Running as root, so change to non-priviledged user...
714 */
715
716 if (setgid(Group))
717 exit(errno);
718
719 if (setuid(User))
720 exit(errno);
721 }
722
723 /*
724 * Reset group membership to just the main one we belong to.
725 */
726
727 setgroups(0, NULL);
728
729 /*
730 * Execute the polling daemon...
731 */
732
733 execl(CUPS_SERVERBIN "/daemon/cups-polld", "cups-polld", poll->hostname,
734 sport, interval, bport, NULL);
735 exit(errno);
736 }
737 else if (pid < 0)
738 {
739 LogMessage(L_ERROR, "StartPolling: Unable to fork polling daemon - %s",
740 strerror(errno));
741 poll->pid = 0;
742 break;
743 }
744 else
745 {
746 poll->pid = pid;
747 LogMessage(L_DEBUG, "StartPolling: Started polling daemon for %s:%d, pid = %d",
748 poll->hostname, poll->port, pid);
749 }
fd3ece61 750 }
753453e4 751>>>>>>> 1.86
752}
d6de4648 753
d6de4648 754
753453e4 755/*
756 * 'StopBrowsing()' - Stop sending and receiving broadcast information.
757 */
758
759void
760StopBrowsing(void)
761{
762 if (!Browsing)
763 return;
d6de4648 764
753453e4 765 if (BrowseProtocols & BROWSE_CUPS)
d6de4648 766 {
753453e4 767 /*
768 * Close the socket and remove it from the input selection set.
769 */
d6de4648 770
753453e4 771 if (BrowseSocket >= 0)
772 {
d6de4648 773#if defined(WIN32) || defined(__EMX__)
753453e4 774 closesocket(BrowseSocket);
d6de4648 775#else
753453e4 776 close(BrowseSocket);
d6de4648 777#endif /* WIN32 || __EMX__ */
778
753453e4 779 LogMessage(L_DEBUG2, "StopBrowsing: Removing fd %d from InputSet...",
780 BrowseSocket);
781
782 FD_CLR(BrowseSocket, &InputSet);
783 BrowseSocket = 0;
784 }
d6de4648 785 }
786
753453e4 787#ifdef HAVE_LIBSLP
788 if (BrowseProtocols & BROWSE_SLP)
789 {
790 /*
791 * Close SLP handle...
792 */
d6de4648 793
753453e4 794 SLPClose(BrowseSLPHandle);
795 }
796#endif /* HAVE_LIBSLP */
fd8b1cf8 797}
798
799
d6de4648 800/*
753453e4 801 * 'StopPolling()' - Stop polling servers as needed.
d6de4648 802 */
803
fd8b1cf8 804void
753453e4 805StopPolling(void)
fd8b1cf8 806{
753453e4 807 int i; /* Looping var */
808 dirsvc_poll_t *poll; /* Current polling server */
d6de4648 809
d6de4648 810
753453e4 811 for (i = 0, poll = Polled; i < NumPolled; i ++, poll ++)
812 if (poll->pid)
813 kill(poll->pid, SIGTERM);
fd8b1cf8 814}
815
816
d6de4648 817/*
753453e4 818 * 'UpdateCUPSBrowse()' - Update the browse lists using the CUPS protocol.
d6de4648 819 */
820
fd8b1cf8 821void
753453e4 822UpdateCUPSBrowse(void)
fd8b1cf8 823{
8b43895a 824 int i; /* Looping var */
e5ebb675 825 int auth; /* Authorization status */
753453e4 826 int len; /* Length of name string */
d6de4648 827 int bytes; /* Number of bytes left */
20e0a4cb 828 char packet[1540], /* Broadcast packet */
829 *pptr; /* Pointer into packet */
99de6da0 830 http_addr_t srcaddr; /* Source address */
e5ebb675 831 char srcname[1024]; /* Source hostname */
99de6da0 832 unsigned address[4], /* Source address */
833 temp; /* Temporary address var (host order) */
d6de4648 834 cups_ptype_t type; /* Printer type */
835 ipp_pstate_t state; /* Printer state */
836 char uri[HTTP_MAX_URI], /* Printer URI */
837 method[HTTP_MAX_URI], /* Method portion of URI */
838 username[HTTP_MAX_URI], /* Username portion of URI */
839 host[HTTP_MAX_URI], /* Host portion of URI */
a2c6b8b1 840 resource[HTTP_MAX_URI], /* Resource portion of URI */
841 info[IPP_MAX_NAME], /* Information string */
842 location[IPP_MAX_NAME], /* Location string */
843 make_model[IPP_MAX_NAME];/* Make and model string */
d6de4648 844 int port; /* Port portion of URI */
d6de4648 845
846
847 /*
848 * Read a packet from the browse socket...
849 */
850
e5ebb675 851 len = sizeof(srcaddr);
16b0a852 852 if ((bytes = recvfrom(BrowseSocket, packet, sizeof(packet), 0,
e5ebb675 853 (struct sockaddr *)&srcaddr, &len)) <= 0)
18d7d592 854 {
89db771d 855 /*
856 * "Connection refused" is returned under Linux if the destination port
857 * or address is unreachable from a previous sendto(); check for the
858 * error here and ignore it for now...
859 */
860
861 if (errno != ECONNREFUSED)
862 {
863 LogMessage(L_ERROR, "Browse recv failed - %s.", strerror(errno));
864 LogMessage(L_ERROR, "Browsing turned off.");
865
866 StopBrowsing();
867 Browsing = 0;
868 }
1a5606a3 869
18d7d592 870 return;
871 }
872
873 packet[bytes] = '\0';
e5ebb675 874
875 /*
876 * Figure out where it came from...
877 */
878
99de6da0 879#ifdef AF_INET6
880 if (srcaddr.addr.sa_family == AF_INET6)
881 {
882 address[0] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[0]);
883 address[1] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[1]);
884 address[2] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[2]);
885 address[3] = ntohl(srcaddr.ipv6.sin6_addr.s6_addr32[3]);
886 }
e5ebb675 887 else
99de6da0 888#endif /* AF_INET6 */
f9bacabb 889 {
99de6da0 890 temp = ntohl(srcaddr.ipv4.sin_addr.s_addr);
891
892 address[3] = temp & 255;
893 temp >>= 8;
894 address[2] = temp & 255;
895 temp >>= 8;
896 address[1] = temp & 255;
897 temp >>= 8;
898 address[0] = temp & 255;
e5ebb675 899 }
1a5606a3 900
99de6da0 901 if (HostNameLookups)
902 httpAddrLookup(&srcaddr, srcname, sizeof(srcname));
903 else
904 httpAddrString(&srcaddr, srcname, sizeof(srcname));
905
e5ebb675 906 len = strlen(srcname);
907
908 /*
909 * Do ACL stuff...
910 */
911
753453e4 912 if (BrowseACL && (BrowseACL->num_allow || BrowseACL->num_deny))
e5ebb675 913 {
99de6da0 914 if (httpAddrLocalhost(&srcaddr) || strcasecmp(srcname, "localhost") == 0)
e5ebb675 915 {
916 /*
917 * Access from localhost (127.0.0.1) is always allowed...
918 */
919
920 auth = AUTH_ALLOW;
921 }
922 else
923 {
924 /*
925 * Do authorization checks on the domain/address...
926 */
927
d21a7597 928 switch (BrowseACL->order_type)
e5ebb675 929 {
d21a7597 930 default :
931 auth = AUTH_DENY; /* anti-compiler-warning-code */
932 break;
933
e5ebb675 934 case AUTH_ALLOW : /* Order Deny,Allow */
d21a7597 935 auth = AUTH_ALLOW;
936
e5ebb675 937 if (CheckAuth(address, srcname, len,
938 BrowseACL->num_deny, BrowseACL->deny))
939 auth = AUTH_DENY;
940
941 if (CheckAuth(address, srcname, len,
942 BrowseACL->num_allow, BrowseACL->allow))
943 auth = AUTH_ALLOW;
944 break;
945
946 case AUTH_DENY : /* Order Allow,Deny */
d21a7597 947 auth = AUTH_DENY;
948
e5ebb675 949 if (CheckAuth(address, srcname, len,
950 BrowseACL->num_allow, BrowseACL->allow))
951 auth = AUTH_ALLOW;
952
953 if (CheckAuth(address, srcname, len,
954 BrowseACL->num_deny, BrowseACL->deny))
955 auth = AUTH_DENY;
956 break;
957 }
958 }
959 }
960 else
961 auth = AUTH_ALLOW;
962
963 if (auth == AUTH_DENY)
964 {
965 LogMessage(L_DEBUG, "UpdateBrowseList: Refused %d bytes from %s", bytes,
966 srcname);
d6de4648 967 return;
f9bacabb 968 }
d6de4648 969
58e8cf34 970 LogMessage(L_DEBUG2, "UpdateBrowseList: (%d bytes from %s) %s", bytes, srcname,
e5ebb675 971 packet);
972
973 /*
974 * Parse packet...
975 */
d6de4648 976
20e0a4cb 977 if (sscanf(packet, "%x%x%1023s", (unsigned *)&type, (unsigned *)&state,
978 uri) < 3)
d6de4648 979 {
5ea8888e 980 LogMessage(L_WARN, "UpdateBrowseList: Garbled browse packet - %s",
d6de4648 981 packet);
982 return;
983 }
984
20e0a4cb 985 strcpy(location, "Location Unknown");
986 strcpy(info, "No Information Available");
987 make_model[0] = '\0';
988
989 if ((pptr = strchr(packet, '\"')) != NULL)
990 {
991 /*
992 * Have extended information; can't use sscanf for it because not all
993 * sscanf's allow empty strings with %[^\"]...
994 */
995
996 for (i = 0, pptr ++;
997 i < (sizeof(location) - 1) && *pptr && *pptr != '\"';
998 i ++, pptr ++)
999 location[i] = *pptr;
1000
1001 if (i)
1002 location[i] = '\0';
1003
1004 if (*pptr == '\"')
1005 pptr ++;
1006
1007 while (*pptr && isspace(*pptr))
1008 pptr ++;
1009
05156f4e 1010 if (*pptr == '\"')
1011 {
1012 for (i = 0, pptr ++;
1013 i < (sizeof(info) - 1) && *pptr && *pptr != '\"';
1014 i ++, pptr ++)
1015 info[i] = *pptr;
20e0a4cb 1016
05156f4e 1017 if (i)
1018 info[i] = '\0';
20e0a4cb 1019
05156f4e 1020 if (*pptr == '\"')
1021 pptr ++;
20e0a4cb 1022
05156f4e 1023 while (*pptr && isspace(*pptr))
1024 pptr ++;
20e0a4cb 1025
05156f4e 1026 if (*pptr == '\"')
1027 {
1028 for (i = 0, pptr ++;
1029 i < (sizeof(make_model) - 1) && *pptr && *pptr != '\"';
1030 i ++, pptr ++)
1031 make_model[i] = *pptr;
20e0a4cb 1032
05156f4e 1033 if (i)
1034 make_model[i] = '\0';
1035 }
1036 }
20e0a4cb 1037 }
1038
1039 DEBUG_puts(packet);
a2c6b8b1 1040 DEBUG_printf(("type=%x, state=%x, uri=\"%s\"\n"
1041 "location=\"%s\", info=\"%s\", make_model=\"%s\"\n",
1042 type, state, uri, location, info, make_model));
a8b216d5 1043
d6de4648 1044 /*
1045 * Pull the URI apart to see if this is a local or remote printer...
1046 */
1047
1048 httpSeparate(uri, method, username, host, &port, resource);
1049
a8b216d5 1050 DEBUG_printf(("host=\"%s\", ServerName=\"%s\"\n", host, ServerName));
1051
d6de4648 1052 if (strcasecmp(host, ServerName) == 0)
1053 return;
1054
e5ebb675 1055 /*
1056 * Do relaying...
1057 */
1058
1059 for (i = 0; i < NumRelays; i ++)
1060 if (CheckAuth(address, srcname, len, 1, &(Relays[i].from)))
1061 if (sendto(BrowseSocket, packet, bytes, 0,
1062 (struct sockaddr *)&(Relays[i].to),
99de6da0 1063 sizeof(http_addr_t)) <= 0)
e5ebb675 1064 {
1065 LogMessage(L_ERROR, "UpdateBrowseList: sendto failed for relay %d - %s.",
1066 i + 1, strerror(errno));
1067 return;
1068 }
1069
d6de4648 1070 /*
753453e4 1071 * Process the browse data...
d6de4648 1072 */
1073
753453e4 1074 ProcessBrowseData(uri, type, state, location, info, make_model);
1075}
d6f1ff9a 1076
d6f1ff9a 1077
753453e4 1078/***********************************************************************
1079 **** SLP Support Code *************************************************
1080 ***********************************************************************/
d6de4648 1081
753453e4 1082#ifdef HAVE_LIBSLP
1083/*
1084 * SLP service name for CUPS...
1085 */
c7fa9d06 1086
753453e4 1087# define SLP_CUPS_SRVTYPE "service:printer"
1088# define SLP_CUPS_SRVLEN 15
c7fa9d06 1089
753453e4 1090typedef struct _slpsrvurl
1091{
1092 struct _slpsrvurl *next;
1093 char url[HTTP_MAX_URI];
1094} slpsrvurl_t;
a2c6b8b1 1095
d6de4648 1096
753453e4 1097/*
1098 * 'RegReportCallback()' - Empty SLPRegReport.
1099 */
c7fa9d06 1100
753453e4 1101void
1102RegReportCallback(SLPHandle hslp,
1103 SLPError errcode,
1104 void *cookie)
1105{
1106 (void)hslp;
1107 (void)errcode;
1108 (void)cookie;
d6f1ff9a 1109
753453e4 1110 return;
1111}
d6f1ff9a 1112
d6f1ff9a 1113
753453e4 1114/*
1115 * 'SendSLPBrowse()' - Register the specified printer with SLP.
1116 */
c7fa9d06 1117
753453e4 1118void
1119SendSLPBrowse(printer_t *p) /* I - Printer to register */
1120{
1121 char srvurl[HTTP_MAX_URI], /* Printer service URI */
1122 attrs[8192], /* Printer attributes */
1123 finishings[1024], /* Finishings to support */
1124 make_model[IPP_MAX_NAME * 2],
1125 /* Make and model, quoted */
1126 location[IPP_MAX_NAME * 2],
1127 /* Location, quoted */
1128 info[IPP_MAX_NAME * 2],
1129 /* Info, quoted */
1130 *src, /* Pointer to original string */
1131 *dst; /* Pointer to destination string */
1132 ipp_attribute_t *authentication; /* uri-authentication-supported value */
1133 SLPError error; /* SLP error, if any */
1134
1135
1136 LogMessage(L_DEBUG, "SendSLPBrowse(%p = \"%s\")", p, p->name);
c7fa9d06 1137
753453e4 1138 /*
1139 * Make the SLP service URL that conforms to the IANA
1140 * 'printer:' template.
1141 */
c7fa9d06 1142
753453e4 1143 snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri);
a2c6b8b1 1144
753453e4 1145 LogMessage(L_DEBUG2, "Service URL = \"%s\"", srvurl);
d6de4648 1146
1147 /*
753453e4 1148 * Figure out the finishings string...
d6de4648 1149 */
1150
753453e4 1151 if (p->type & CUPS_PRINTER_STAPLE)
1152 strcpy(finishings, "staple");
1153 else
1154 finishings[0] = '\0';
8b43895a 1155
753453e4 1156 if (p->type & CUPS_PRINTER_BIND)
20e0a4cb 1157 {
753453e4 1158 if (finishings[0])
1159 strncat(finishings, ",bind", sizeof(finishings) - 1);
1160 else
1161 strcpy(finishings, "bind");
20e0a4cb 1162 }
1163
753453e4 1164 if (p->type & CUPS_PRINTER_PUNCH)
20e0a4cb 1165 {
753453e4 1166 if (finishings[0])
1167 strncat(finishings, ",punch", sizeof(finishings) - 1);
1168 else
1169 strcpy(finishings, "punch");
20e0a4cb 1170 }
1171
753453e4 1172 if (p->type & CUPS_PRINTER_COVER)
20e0a4cb 1173 {
753453e4 1174 if (finishings[0])
1175 strncat(finishings, ",cover", sizeof(finishings) - 1);
1176 else
1177 strcpy(finishings, "cover");
20e0a4cb 1178 }
1179
753453e4 1180 if (p->type & CUPS_PRINTER_SORT)
20e0a4cb 1181 {
753453e4 1182 if (finishings[0])
1183 strncat(finishings, ",sort", sizeof(finishings) - 1);
20e0a4cb 1184 else
753453e4 1185 strcpy(finishings, "sort");
20e0a4cb 1186 }
753453e4 1187
1188 if (!finishings[0])
1189 strcpy(finishings, "none");
1190
1191 finishings[sizeof(finishings) - 1] = '\0';
1192
1193 /*
1194 * Quote any commas in the make and model, location, and info strings
1195 * (local strings are twice the size of the ones in the printer_t
1196 * structure, so no buffer overflow is possible...)
1197 */
1198
1199 for (src = p->make_model, dst = make_model; *src;)
1200 {
1201 if (*src == ',' || *src == '\\' || *src == ')')
1202 *dst++ = '\\';
1203
1204 *dst++ = *src++;
1205 }
1206
1207 *dst = '\0';
1208
1209 if (!make_model[0])
1210 strcpy(make_model, "Unknown");
1211
1212 for (src = p->location, dst = location; *src;)
20e0a4cb 1213 {
753453e4 1214 if (*src == ',' || *src == '\\' || *src == ')')
1215 *dst++ = '\\';
1216
1217 *dst++ = *src++;
20e0a4cb 1218 }
1219
753453e4 1220 *dst = '\0';
1221
1222 if (!location[0])
1223 strcpy(location, "Unknown");
1224
1225 for (src = p->info, dst = info; *src;)
20e0a4cb 1226 {
753453e4 1227 if (*src == ',' || *src == '\\' || *src == ')')
1228 *dst++ = '\\';
1229
1230 *dst++ = *src++;
20e0a4cb 1231 }
1232
753453e4 1233 *dst = '\0';
1234
1235 if (!info[0])
1236 strcpy(info, "Unknown");
1237
1238 /*
1239 * Get the authentication value...
1240 */
1241
1242 authentication = ippFindAttribute(p->attrs, "uri-authentication-supported",
1243 IPP_TAG_KEYWORD);
a2c6b8b1 1244
fb00e262 1245 /*
753453e4 1246 * Make the SLP attribute string list that conforms to
1247 * the IANA 'printer:' template.
fb00e262 1248 */
1249
753453e4 1250 snprintf(attrs, sizeof(attrs),
1251 "(printer-uri-supported=%s),"
1252 "(uri-authentication-supported=%s>),"
1253#ifdef HAVE_LIBSSL
1254 "(uri-security-supported=tls>),"
1255#else
1256 "(uri-security-supported=none>),"
1257#endif /* HAVE_LIBSSL */
1258 "(printer-name=%s),"
1259 "(printer-location=%s),"
1260 "(printer-info=%s),"
1261 "(printer-more-info=%s),"
1262 "(printer-make-and-model=%s),"
1263 "(charset-supported=utf-8),"
1264 "(natural-language-configured=%s),"
1265 "(natural-language-supported=de,en,es,fr,it),"
1266 "(color-supported=%s),"
1267 "(finishings-supported=%s),"
1268 "(sides-supported=one-sided%s),"
1269 "(multiple-document-jobs-supported=true)"
1270 "(ipp-versions-supported=1.0,1.1)",
1271 p->uri, authentication->values[0].string.text, p->name, location,
1272 info, p->uri, make_model, DefaultLanguage,
1273 p->type & CUPS_PRINTER_COLOR ? "true" : "false",
1274 finishings,
1275 p->type & CUPS_PRINTER_DUPLEX ?
1276 ",two-sided-long-edge,two-sided-short-edge" : "");
1277
1278 LogMessage(L_DEBUG2, "Attributes = \"%s\"", attrs);
fb00e262 1279
8b43895a 1280 /*
753453e4 1281 * Register the printer with the SLP server...
8b43895a 1282 */
1283
753453e4 1284 error = SLPReg(BrowseSLPHandle, srvurl, BrowseTimeout,
1285 SLP_CUPS_SRVTYPE, attrs, SLP_TRUE, RegReportCallback, 0);
1286
1287 if (error != SLP_OK)
1288 LogMessage(L_ERROR, "SLPReg of \"%s\" failed with status %d!", p->name,
1289 error);
1290}
1291
1292
1293/*
1294 * 'SLPDeregPrinter()' - SLPDereg() the specified printer
1295 */
1296
1297void
1298SLPDeregPrinter(printer_t *p)
1299{
1300 char srvurl[HTTP_MAX_URI]; /* Printer service URI */
1301
1302
1303 if((p->type & CUPS_PRINTER_REMOTE) == 0)
8b43895a 1304 {
1305 /*
753453e4 1306 * Make the SLP service URL that conforms to the IANA
1307 * 'printer:' template.
8b43895a 1308 */
1309
753453e4 1310 snprintf(srvurl, sizeof(srvurl), SLP_CUPS_SRVTYPE ":%s", p->uri);
b5cb0608 1311
753453e4 1312 /*
1313 * Deregister the printer...
1314 */
b5cb0608 1315
753453e4 1316 SLPDereg(BrowseSLPHandle, srvurl, RegReportCallback, 0);
1317 }
1318}
8b43895a 1319
8b43895a 1320
753453e4 1321/*
1322 * 'GetSlpAttrVal()' - Get an attribute from an SLP registration.
1323 */
8b43895a 1324
753453e4 1325int /* O - 0 on success */
1326GetSlpAttrVal(const char *attrlist, /* I - Attribute list string */
1327 const char *tag, /* I - Name of attribute */
1328 char *valbuf, /* O - Value */
1329 int valbuflen) /* I - Max length of value */
1330{
1331 char *ptr1, /* Pointer into string */
1332 *ptr2; /* ... */
1333
1334
1335 valbuf[0] = '\0';
1336
1337 if ((ptr1 = strstr(attrlist, tag)) != NULL)
1338 {
1339 ptr1 += strlen(tag);
1340
1341 if ((ptr2 = strchr(ptr1,')')) != NULL)
1342 {
1343 if (valbuflen > (ptr2 - ptr1))
8b43895a 1344 {
1345 /*
753453e4 1346 * Copy the value...
8b43895a 1347 */
1348
753453e4 1349 strncpy(valbuf, ptr1, ptr2 - ptr1);
1350 valbuf[ptr2 - ptr1] = '\0';
4139b718 1351
753453e4 1352 /*
1353 * Dequote the value...
1354 */
4139b718 1355
753453e4 1356 for (ptr1 = valbuf; *ptr1; ptr1 ++)
1357 if (*ptr1 == '\\' && ptr1[1])
1358 strcpy(ptr1, ptr1 + 1);
20da3efb 1359
753453e4 1360 return (0);
1361 }
1362 }
1363 }
8b43895a 1364
753453e4 1365 return (-1);
1366}
8b43895a 1367
8b43895a 1368
753453e4 1369/*
1370 * 'AttrCallback()' - SLP attribute callback
1371 */
8b43895a 1372
753453e4 1373SLPBoolean
1374AttrCallback(SLPHandle hslp,
1375 const char *attrlist,
1376 SLPError errcode,
1377 void *cookie)
1378{
1379 char tmp[IPP_MAX_NAME];
1380 printer_t *p = (printer_t*)cookie;
8b43895a 1381
8b43895a 1382
753453e4 1383 /*
1384 * Let the compiler know we won't be using these...
1385 */
8b43895a 1386
753453e4 1387 (void)hslp;
782359ca 1388
753453e4 1389 /*
1390 * Bail if there was an error
1391 */
782359ca 1392
753453e4 1393 if (errcode != SLP_OK)
1394 return (SLP_TRUE);
782359ca 1395
753453e4 1396 /*
1397 * Parse the attrlist to obtain things needed to build CUPS browse packet
1398 */
1399
1400 memset(p, 0, sizeof(printer_t));
1401
1402 p->type = CUPS_PRINTER_REMOTE;
1403
1404 if (GetSlpAttrVal(attrlist, "(printer-location=", p->location,
1405 sizeof(p->location)))
1406 return (SLP_FALSE);
1407 if (GetSlpAttrVal(attrlist, "(printer-make-and-model=", p->make_model,
1408 sizeof(p->make_model)))
1409 return (SLP_FALSE);
1410
1411 if (GetSlpAttrVal(attrlist, "(color-supported=", tmp, sizeof(tmp)))
1412 return (SLP_FALSE);
1413 if (strcasecmp(tmp, "true") == 0)
1414 p->type |= CUPS_PRINTER_COLOR;
1415
1416 if (GetSlpAttrVal(attrlist, "(finishings-supported=", tmp, sizeof(tmp)))
1417 return (SLP_FALSE);
1418 if (strstr(tmp, "staple"))
1419 p->type |= CUPS_PRINTER_STAPLE;
1420 if (strstr(tmp, "bind"))
1421 p->type |= CUPS_PRINTER_BIND;
1422 if (strstr(tmp, "punch"))
1423 p->type |= CUPS_PRINTER_PUNCH;
1424
1425 if (GetSlpAttrVal(attrlist, "(sides-supported=", tmp, sizeof(tmp)))
1426 return (SLP_FALSE);
1427 if (strstr(tmp,"two-sided"))
1428 p->type |= CUPS_PRINTER_DUPLEX;
1429
1430 return (SLP_TRUE);
fd8b1cf8 1431}
1432
1433
d6de4648 1434/*
753453e4 1435 * 'SrvUrlCallback()' - SLP service url callback
d6de4648 1436 */
1437
753453e4 1438SLPBoolean /* O - TRUE = OK, FALSE = error */
1439SrvUrlCallback(SLPHandle hslp, /* I - SLP handle */
1440 const char *srvurl, /* I - URL of service */
1441 unsigned short lifetime, /* I - Life of service */
1442 SLPError errcode, /* I - Existing error code */
1443 void *cookie) /* I - Pointer to service list */
fd8b1cf8 1444{
753453e4 1445 slpsrvurl_t *s, /* New service entry */
1446 **head; /* Pointer to head of entry */
d6de4648 1447
1448
753453e4 1449 /*
1450 * Let the compiler know we won't be using these vars...
1451 */
1452
1453 (void)hslp;
1454 (void)lifetime;
f63a2256 1455
d6de4648 1456 /*
753453e4 1457 * Bail if there was an error
d6de4648 1458 */
1459
753453e4 1460 if (errcode != SLP_OK)
1461 return (SLP_TRUE);
d6de4648 1462
1463 /*
753453e4 1464 * Grab the head of the list...
d6de4648 1465 */
1466
753453e4 1467 head = (slpsrvurl_t**)cookie;
d6de4648 1468
753453e4 1469 /*
1470 * Allocate a *temporary* slpsrvurl_t to hold this entry.
1471 */
d6de4648 1472
753453e4 1473 if ((s = (slpsrvurl_t *)calloc(1, sizeof(slpsrvurl_t))) == NULL)
1474 return (SLP_FALSE);
d6de4648 1475
753453e4 1476 /*
1477 * Copy the SLP service URL...
1478 */
d6de4648 1479
753453e4 1480 strncpy(s->url, srvurl, sizeof(s->url));
a2c6b8b1 1481
753453e4 1482 /*
1483 * Link the SLP service URL into the head of the list
1484 */
d6de4648 1485
753453e4 1486 if (*head)
1487 s->next = *head;
d6de4648 1488
753453e4 1489 *head = s;
f63a2256 1490
753453e4 1491 return (SLP_TRUE);
fd8b1cf8 1492}
a129ddbd 1493
1494
1495/*
753453e4 1496 * 'UpdateSLPBrowse()' - Get browsing information via SLP.
03081fd2 1497 */
1498
1499void
753453e4 1500UpdateSLPBrowse(void)
03081fd2 1501{
753453e4 1502 slpsrvurl_t *s, /* Temporary list of service URLs */
1503 *next; /* Next service in list */
1504 printer_t p; /* Printer information */
1505 const char *uri; /* Pointer to printer URI */
1506 char method[HTTP_MAX_URI], /* Method portion of URI */
1507 username[HTTP_MAX_URI], /* Username portion of URI */
1508 host[HTTP_MAX_URI], /* Host portion of URI */
1509 resource[HTTP_MAX_URI]; /* Resource portion of URI */
1510 int port; /* Port portion of URI */
e5ebb675 1511
1512
753453e4 1513 LogMessage(L_DEBUG, "UpdateSLPBrowse() Start...");
b1ac1113 1514
753453e4 1515 /*
1516 * Reset the refresh time...
1517 */
e5ebb675 1518
753453e4 1519 BrowseSLPRefresh = time(NULL) + BrowseTimeout - BrowseInterval;
e5ebb675 1520
753453e4 1521 /*
1522 * Poll for remote printers using SLP...
1523 */
e5ebb675 1524
753453e4 1525 s = NULL;
5aeb433c 1526
753453e4 1527 SLPFindSrvs(BrowseSLPHandle, SLP_CUPS_SRVTYPE, "", "",
1528 SrvUrlCallback, &s);
5aeb433c 1529
753453e4 1530 /*
1531 * Loop through the list of available printers...
1532 */
1533
1534 for (; s; s = next)
1535 {
1536 /*
1537 * Load a printer_t structure with the SLP service attributes...
1538 */
1539
1540 SLPFindAttrs(BrowseSLPHandle, s->url, "", "", AttrCallback, &p);
1541
1542 /*
1543 * Process this printer entry...
1544 */
1545
1546 uri = s->url + SLP_CUPS_SRVLEN + 1;
5aeb433c 1547
753453e4 1548 if (strncmp(uri, "http://", 7) == 0 ||
1549 strncmp(uri, "ipp://", 6) == 0)
1550 {
5aeb433c 1551 /*
753453e4 1552 * Pull the URI apart to see if this is a local or remote printer...
5aeb433c 1553 */
1554
753453e4 1555 httpSeparate(uri, method, username, host, &port, resource);
1556
1557 if (strcasecmp(host, ServerName) == 0)
1558 continue;
5aeb433c 1559
1560 /*
753453e4 1561 * OK, at least an IPP printer, see if it is a CUPS printer or
1562 * class...
5aeb433c 1563 */
e5ebb675 1564
753453e4 1565 if (strstr(uri, "/printers/") != NULL)
1566 ProcessBrowseData(uri, p.type, IPP_PRINTER_IDLE, p.location,
1567 p.info, p.make_model);
1568 else if (strstr(uri, "/classes/") != NULL)
1569 ProcessBrowseData(uri, p.type | CUPS_PRINTER_CLASS, IPP_PRINTER_IDLE,
1570 p.location, p.info, p.make_model);
e5ebb675 1571 }
03081fd2 1572
753453e4 1573 /*
1574 * Save the "next" pointer and free this listing...
1575 */
e5ebb675 1576
753453e4 1577 next = s->next;
1578 free(s);
1579 }
e5ebb675 1580
753453e4 1581 LogMessage(L_DEBUG, "UpdateSLPBrowse() End...");
03081fd2 1582}
753453e4 1583#endif /* HAVE_LIBSLP */
03081fd2 1584
1585
1586/*
753453e4 1587 * End of "$Id: dirsvc.c,v 1.73.2.3 2001/12/26 16:52:52 mike Exp $".
a129ddbd 1588 */