Libinfo-330.10.tar.gz
[apple/libinfo.git] / lookup.subproj / search_module.c
1 /*
2 * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <stdlib.h>
25 #include <paths.h>
26 #include <stdarg.h>
27 #include <unistd.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <netdb.h>
32 #include <pthread.h>
33 #include <sys/param.h>
34 #include <sys/stat.h>
35 #include <arpa/inet.h>
36 #include "si_module.h"
37
38 #define _PATH_SI_CONF "/etc/sysinfo.conf"
39
40 #define SEARCH_FLAG_MAC 0x00000001
41 #define SEARCH_FLAG_APPLETV 0x00000002
42 #define SEARCH_FLAG_IPHONE 0x00000004
43 #define SEARCH_FLAG_CACHE_ENABLED 0x00010000
44
45 typedef struct
46 {
47 si_mod_t **module;
48 uint32_t count;
49 uint32_t flags;
50 } search_list_t;
51
52 typedef struct
53 {
54 uint32_t flags;
55 search_list_t search_list[CATEGORY_COUNT];
56 si_mod_t *cache;
57 si_mod_t *dns;
58 si_mod_t *mdns;
59 si_mod_t *file;
60 si_mod_t *ds;
61 } search_si_private_t;
62
63 __private_extern__ void si_cache_add_item(si_mod_t *si, si_mod_t *src, si_item_t *item);
64 __private_extern__ void si_cache_add_list(si_mod_t *si, si_mod_t *src, si_list_t *list);
65
66 __private_extern__ char **_fsi_tokenize(char *data, const char *sep, int trailing_empty, int *ntokens);
67 __private_extern__ char *_fsi_get_line(FILE *fp);
68
69 #ifdef DS_AVAILABLE
70 extern int _ds_running();
71 #else
72 static inline int _ds_running(void) { return 0; }
73 #endif
74
75 static __attribute__((noinline)) si_mod_t *
76 search_get_module(search_si_private_t *pp, int cat, int *n)
77 {
78 int x;
79
80 if ((pp == NULL) || (n == NULL)) return NULL;
81
82 x = *n;
83 *n = x + 1;
84
85 /* Use custom search list if available */
86 if (x < pp->search_list[cat].count)
87 {
88 return pp->search_list[cat].module[x];
89 }
90
91 /*
92 * Search order:
93 * 1) cache
94 * 2) DS if available, otherwise flat files
95 * 3) mdns (for host lookups only)
96 */
97 switch (x)
98 {
99 case 0: return pp->cache;
100 case 1: if (_ds_running()) return pp->ds;
101 else return pp->file;
102 case 2: return pp->mdns;
103 default: return NULL;
104 }
105 }
106
107 static si_mod_t *
108 search_cat_cache(search_si_private_t *pp, int cat)
109 {
110 if (pp == NULL) return NULL;
111 if ((cat < 0) || (cat > CATEGORY_COUNT)) return NULL;
112
113 if (pp->search_list[cat].count > 0)
114 {
115 if (pp->search_list[cat].flags & SEARCH_FLAG_CACHE_ENABLED) return pp->cache;
116 return NULL;
117 }
118
119 if ((pp->flags & SEARCH_FLAG_MAC) || (pp->flags & SEARCH_FLAG_APPLETV) || (pp->flags & SEARCH_FLAG_IPHONE)) return pp->cache;
120 return NULL;
121 }
122
123 static void
124 search_close(si_mod_t *si)
125 {
126 int i;
127 search_si_private_t *pp;
128
129 if (si == NULL) return;
130 if (si->private == NULL) return;
131
132 pp = (search_si_private_t *)si->private;
133
134 si_module_release(pp->cache);
135 si_module_release(pp->file);
136 si_module_release(pp->dns);
137 si_module_release(pp->mdns);
138 si_module_release(pp->ds);
139
140 for (i = 0; i < CATEGORY_COUNT; i++)
141 {
142 if (pp->search_list[i].module != NULL)
143 {
144 free(pp->search_list[i].module);
145 pp->search_list[i].module = NULL;
146 pp->search_list[i].count = 0;
147 pp->search_list[i].flags = 0;
148 }
149 }
150
151 free(pp);
152 }
153
154 static si_item_t *
155 search_item_byname(si_mod_t *si, const char *name, int cat, si_item_t *(*call)(si_mod_t *, const char *))
156 {
157 int i;
158 search_si_private_t *pp;
159 si_item_t *item;
160 si_mod_t *src;
161
162 if (si == NULL) return NULL;
163 if (call == NULL) return NULL;
164
165 pp = (search_si_private_t *)si->private;
166 if (pp == NULL) return NULL;
167
168 i = 0;
169
170 while (NULL != (src = search_get_module(pp, cat, &i)))
171 {
172 item = call(src, name);
173 if (item != NULL)
174 {
175 si_cache_add_item(search_cat_cache(pp, cat), src, item);
176 return item;
177 }
178 }
179
180 return NULL;
181 }
182
183 static si_item_t *
184 search_item_bynumber(si_mod_t *si, uint32_t number, int cat, si_item_t *(*call)(si_mod_t *, uint32_t))
185 {
186 int i;
187 search_si_private_t *pp;
188 si_item_t *item;
189 si_mod_t *src;
190
191 if (si == NULL) return NULL;
192 if (call == NULL) return NULL;
193
194 pp = (search_si_private_t *)si->private;
195 if (pp == NULL) return NULL;
196
197 i = 0;
198
199 while (NULL != (src = search_get_module(pp, cat, &i)))
200 {
201 item = call(src, number);
202 if (item != NULL)
203 {
204 si_cache_add_item(search_cat_cache(pp, cat), src, item);
205 return item;
206 }
207 }
208
209 return NULL;
210 }
211
212 static si_list_t *
213 search_list(si_mod_t *si, int cat, si_list_t *(*call)(si_mod_t *))
214 {
215 int i;
216 search_si_private_t *pp;
217 si_list_t *list, *all;
218 si_mod_t *cache, *src;
219
220 if (si == NULL) return NULL;
221 if (call == NULL) return NULL;
222
223 pp = (search_si_private_t *)si->private;
224 if (pp == NULL) return NULL;
225
226 cache = search_cat_cache(pp, cat);
227 if (cache != NULL)
228 {
229 list = call(cache);
230 if (list != NULL) return list;
231 }
232
233 i = 0;
234
235 all = NULL;
236
237 while (NULL != (src = search_get_module(pp, cat, &i)))
238 {
239 if (src == pp->cache) continue;
240
241 list = call(src);
242 if (list == NULL) continue;
243
244 all = si_list_concat(all, list);
245 si_list_release(list);
246 }
247
248 si_cache_add_list(cache, si, all);
249 return all;
250 }
251
252 __private_extern__ si_item_t *
253 search_user_byname(si_mod_t *si, const char *name)
254 {
255 return search_item_byname(si, name, CATEGORY_USER, si_user_byname);
256 }
257
258 __private_extern__ si_item_t *
259 search_user_byuid(si_mod_t *si, uid_t uid)
260 {
261 return search_item_bynumber(si, (uint32_t)uid, CATEGORY_USER, si_user_byuid);
262 }
263
264 __private_extern__ si_list_t *
265 search_user_all(si_mod_t *si)
266 {
267 return search_list(si, CATEGORY_USER, si_user_all);
268 }
269
270 __private_extern__ si_item_t *
271 search_group_byname(si_mod_t *si, const char *name)
272 {
273 return search_item_byname(si, name, CATEGORY_GROUP, si_group_byname);
274 }
275
276 __private_extern__ si_item_t *
277 search_group_bygid(si_mod_t *si, gid_t gid)
278 {
279 return search_item_bynumber(si, (uint32_t)gid, CATEGORY_USER, si_group_bygid);
280 }
281
282 __private_extern__ si_list_t *
283 search_group_all(si_mod_t *si)
284 {
285 return search_list(si, CATEGORY_GROUP, si_group_all);
286 }
287
288 __private_extern__ si_item_t *
289 search_groupist(si_mod_t *si, const char *name)
290 {
291 return search_item_byname(si, name, CATEGORY_GROUPLIST, si_grouplist);
292 }
293
294 __private_extern__ si_list_t *
295 search_netgroup_byname(si_mod_t *si, const char *name)
296 {
297 int i, cat;
298 search_si_private_t *pp;
299 si_list_t *list, *all;
300 si_mod_t *cache, *src;
301
302 if (si == NULL) return NULL;
303
304 pp = (search_si_private_t *)si->private;
305 if (pp == NULL) return NULL;
306
307 cat = CATEGORY_NETGROUP;
308
309 cache = search_cat_cache(pp, cat);
310 if (cache != NULL)
311 {
312 list = si_netgroup_byname(cache, name);
313 if (list != NULL) return list;
314 }
315
316 i = 0;
317
318 all = NULL;
319 while (NULL != (src = search_get_module(pp, cat, &i)))
320 {
321 if (src == pp->cache) continue;
322
323 list = si_netgroup_byname(src, name);
324 if (list == NULL) continue;
325
326 all = si_list_concat(all, list);
327 si_list_release(list);
328 }
329
330 si_cache_add_list(cache, si, all);
331 return all;
332 }
333
334 __private_extern__ int
335 search_in_netgroup(si_mod_t *si, const char *group, const char *host, const char *user, const char *domain)
336 {
337 int i, cat, innetgr;
338 search_si_private_t *pp;
339 si_mod_t *src;
340
341 if (si == NULL) return 0;
342
343 pp = (search_si_private_t *)si->private;
344 if (pp == NULL) return 0;
345
346 cat = CATEGORY_NETGROUP;
347 i = 0;
348 innetgr = 0;
349
350 while (NULL != (src = search_get_module(pp, cat, &i)))
351 {
352 innetgr = si_in_netgroup(src, group, host, user, domain);
353 if (innetgr != 0) return 1;
354 }
355
356 return 0;
357 }
358
359 __private_extern__ si_item_t *
360 search_alias_byname(si_mod_t *si, const char *name)
361 {
362 return search_item_byname(si, name, CATEGORY_ALIAS, si_alias_byname);
363 }
364
365 __private_extern__ si_list_t *
366 search_alias_all(si_mod_t *si)
367 {
368 return search_list(si, CATEGORY_ALIAS, si_alias_all);
369 }
370
371 __private_extern__ si_item_t *
372 search_host_byname(si_mod_t *si, const char *name, int af, const char *interface, uint32_t *err)
373 {
374 int i, cat;
375 search_si_private_t *pp;
376 si_item_t *item;
377 si_mod_t *src;
378
379 if (err != NULL) *err = SI_STATUS_NO_ERROR;
380
381 if ((si == NULL) || (name == NULL))
382 {
383 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
384 return NULL;
385 }
386
387 pp = (search_si_private_t *)si->private;
388 if (pp == NULL)
389 {
390 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
391 return NULL;
392 }
393
394 cat = CATEGORY_HOST_IPV4;
395 if (af == AF_INET6) cat = CATEGORY_HOST_IPV6;
396
397 i = 0;
398
399 while (NULL != (src = search_get_module(pp, cat, &i)))
400 {
401 item = si_host_byname(src, name, af, interface, err);
402 if (item != NULL)
403 {
404 si_cache_add_item(search_cat_cache(pp, cat), src, item);
405 return item;
406 }
407 }
408
409 if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
410 return NULL;
411 }
412
413 __private_extern__ si_item_t *
414 search_host_byaddr(si_mod_t *si, const void *addr, int af, const char *interface, uint32_t *err)
415 {
416 int i, cat;
417 search_si_private_t *pp;
418 si_item_t *item;
419 si_mod_t *src;
420
421 if (err != NULL) *err = SI_STATUS_NO_ERROR;
422
423 if ((si == NULL) || (addr == NULL))
424 {
425 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
426 return NULL;
427 }
428
429 pp = (search_si_private_t *)si->private;
430 if (pp == NULL)
431 {
432 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
433 return NULL;
434 }
435
436 cat = CATEGORY_HOST_IPV4;
437 if (af == AF_INET6) cat = CATEGORY_HOST_IPV6;
438
439 i = 0;
440
441 while (NULL != (src = search_get_module(pp, cat, &i)))
442 {
443 item = si_host_byaddr(src, addr, af, interface, err);
444 if (item != NULL)
445 {
446 si_cache_add_item(search_cat_cache(pp, cat), src, item);
447 return item;
448 }
449 }
450
451 if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
452 return NULL;
453 }
454
455 __private_extern__ si_list_t *
456 search_host_all(si_mod_t *si)
457 {
458 return search_list(si, CATEGORY_HOST, si_host_all);
459 }
460
461 __private_extern__ si_item_t *
462 search_network_byname(si_mod_t *si, const char *name)
463 {
464 return search_item_byname(si, name, CATEGORY_NETWORK, si_network_byname);
465 }
466
467 __private_extern__ si_item_t *
468 search_network_byaddr(si_mod_t *si, uint32_t addr)
469 {
470 return search_item_bynumber(si, addr, CATEGORY_NETWORK, si_network_byaddr);
471 }
472
473 __private_extern__ si_list_t *
474 search_network_all(si_mod_t *si)
475 {
476 return search_list(si, CATEGORY_NETWORK, si_network_all);
477 }
478
479 __private_extern__ si_item_t *
480 search_service_byname(si_mod_t *si, const char *name, const char *proto)
481 {
482 int i, cat;
483 si_item_t *item;
484 search_si_private_t *pp;
485 si_mod_t *src;
486
487 if (si == NULL) return NULL;
488 if (name == NULL) return NULL;
489
490 pp = (search_si_private_t *)si->private;
491 if (pp == NULL) return NULL;
492
493 cat = CATEGORY_SERVICE;
494 i = 0;
495
496 while (NULL != (src = search_get_module(pp, cat, &i)))
497 {
498 item = si_service_byname(src, name, proto);
499 if (item != NULL)
500 {
501 si_cache_add_item(search_cat_cache(pp, cat), src, item);
502 return item;
503 }
504 }
505
506 return NULL;
507 }
508
509 __private_extern__ si_item_t *
510 search_service_byport(si_mod_t *si, int port, const char *proto)
511 {
512 int i, cat;
513 search_si_private_t *pp;
514 si_item_t *item;
515 si_mod_t *src;
516
517 if (si == NULL) return NULL;
518
519 pp = (search_si_private_t *)si->private;
520 if (pp == NULL) return NULL;
521
522 cat = CATEGORY_SERVICE;
523 i = 0;
524
525 while (NULL != (src = search_get_module(pp, cat, &i)))
526 {
527 item = si_service_byport(src, port, proto);
528 if (item != NULL)
529 {
530 si_cache_add_item(search_cat_cache(pp, cat), src, item);
531 return item;
532 }
533 }
534
535 return NULL;
536 }
537
538 __private_extern__ si_list_t *
539 search_service_all(si_mod_t *si)
540 {
541 return search_list(si, CATEGORY_SERVICE, si_service_all);
542 }
543
544 __private_extern__ si_item_t *
545 search_protocol_byname(si_mod_t *si, const char *name)
546 {
547 return search_item_byname(si, name, CATEGORY_PROTOCOL, si_protocol_byname);
548 }
549
550 __private_extern__ si_item_t *
551 search_protocol_bynumber(si_mod_t *si, int number)
552 {
553 return search_item_bynumber(si, (uint32_t)number, CATEGORY_PROTOCOL, si_protocol_bynumber);
554 }
555
556 __private_extern__ si_list_t *
557 search_protocol_all(si_mod_t *si)
558 {
559 return search_list(si, CATEGORY_PROTOCOL, si_protocol_all);
560 }
561
562 __private_extern__ si_item_t *
563 search_rpc_byname(si_mod_t *si, const char *name)
564 {
565 return search_item_byname(si, name, CATEGORY_RPC, si_rpc_byname);
566 }
567
568 __private_extern__ si_item_t *
569 search_rpc_bynumber(si_mod_t *si, int number)
570 {
571 int i, cat;
572 search_si_private_t *pp;
573 si_item_t *item;
574 si_mod_t *src;
575
576 if (si == NULL) return NULL;
577
578 pp = (search_si_private_t *)si->private;
579 if (pp == NULL) return NULL;
580
581 cat = CATEGORY_RPC;
582 i = 0;
583
584 while (NULL != (src = search_get_module(pp, cat, &i)))
585 {
586 item = si_rpc_bynumber(src, number);
587 if (item != NULL)
588 {
589 si_cache_add_item(search_cat_cache(pp, cat), src, item);
590 return item;
591 }
592 }
593
594 return NULL;
595 }
596
597 __private_extern__ si_list_t *
598 search_rpc_all(si_mod_t *si)
599 {
600 return search_list(si, CATEGORY_RPC, si_rpc_all);
601 }
602
603 __private_extern__ si_item_t *
604 search_fs_byspec(si_mod_t *si, const char *name)
605 {
606 return search_item_byname(si, name, CATEGORY_FS, si_fs_byspec);
607 }
608
609 __private_extern__ si_item_t *
610 search_fs_byfile(si_mod_t *si, const char *name)
611 {
612 return search_item_byname(si, name, CATEGORY_FS, si_fs_byfile);
613 }
614
615 __private_extern__ si_list_t *
616 search_fs_all(si_mod_t *si)
617 {
618 return search_list(si, CATEGORY_FS, si_fs_all);
619 }
620
621 __private_extern__ si_item_t *
622 search_mac_byname(si_mod_t *si, const char *name)
623 {
624 return search_item_byname(si, name, CATEGORY_MAC, si_mac_byname);
625 }
626
627 __private_extern__ si_item_t *
628 search_mac_bymac(si_mod_t *si, const char *mac)
629 {
630 return search_item_byname(si, mac, CATEGORY_MAC, si_mac_bymac);
631 }
632
633 __private_extern__ si_list_t *
634 search_mac_all(si_mod_t *si)
635 {
636 return search_list(si, CATEGORY_MAC, si_mac_all);
637 }
638
639 __private_extern__ si_list_t *
640 search_srv_byname(si_mod_t *si, const char* qname, const char *interface, uint32_t *err)
641 {
642 int i, cat;
643 si_list_t *list = NULL;
644 si_mod_t *src;
645 search_si_private_t *pp;
646
647 if (si == NULL) return NULL;
648
649 pp = (search_si_private_t *)si->private;
650 if (pp == NULL) return NULL;
651
652 cat = CATEGORY_SRV;
653 i = 0;
654
655 while (NULL != (src = search_get_module(pp, cat, &i)))
656 {
657 if (src == pp->cache) continue;
658
659 if (src->sim_srv_byname != NULL)
660 {
661 list = src->sim_srv_byname(src, qname, interface, err);
662 if (list != NULL) return list;
663 }
664 }
665
666 if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME;
667 return NULL;
668 }
669
670 __private_extern__ int
671 search_wants_addrinfo(si_mod_t *si)
672 {
673 int i, cat;
674 si_mod_t *src;
675 search_si_private_t *pp;
676
677 if (si == NULL) return 0;
678
679 pp = (search_si_private_t *)si->private;
680 if (pp == NULL) return 0;
681
682 cat = CATEGORY_ADDRINFO;
683 i = 0;
684
685 while (NULL != (src = search_get_module(pp, cat, &i)))
686 {
687 if (src == pp->cache) continue;
688 if (src->sim_addrinfo != NULL) return 1;
689 }
690
691 return 0;
692 }
693
694 __private_extern__ si_list_t *
695 search_addrinfo(si_mod_t *si, const void *node, const void *serv, uint32_t family, uint32_t socktype, uint32_t protocol, uint32_t flags, const char *interface, uint32_t *err)
696 {
697 int i, cat;
698 search_si_private_t *pp;
699 si_list_t *list = NULL;
700 si_mod_t *src;
701
702 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
703
704 if (si == NULL) return NULL;
705
706 pp = (search_si_private_t *)si->private;
707 if (pp == NULL) return NULL;
708
709 cat = CATEGORY_ADDRINFO;
710 i = 0;
711
712 while (NULL != (src = search_get_module(pp, cat, &i)))
713 {
714 if (src == pp->cache) continue;
715
716 if (src->sim_addrinfo != NULL)
717 {
718 list = src->sim_addrinfo(src, node, serv, family, socktype, protocol, flags, interface, err);
719 if (list != NULL) return list;
720 }
721 }
722
723 if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME;
724 return NULL;
725 }
726
727 __private_extern__ si_item_t *
728 search_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, const char *interface, uint32_t *err)
729 {
730 int i, cat;
731 search_si_private_t *pp;
732 si_item_t *item;
733 si_mod_t *src;
734
735 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
736
737 if (si == NULL) return NULL;
738
739 pp = (search_si_private_t *)si->private;
740 if (pp == NULL) return NULL;
741
742 cat = CATEGORY_NAMEINFO;
743 i = 0;
744
745 while (NULL != (src = search_get_module(pp, cat, &i)))
746 {
747 item = si_nameinfo(src, sa, flags, interface, err);
748 if (item != NULL)
749 {
750 si_cache_add_item(search_cat_cache(pp, cat), src, item);
751 if (err != NULL) *err = SI_STATUS_NO_ERROR;
752 return item;
753 }
754 }
755
756 if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME;
757 return NULL;
758 }
759
760 __private_extern__ int
761 search_is_valid(si_mod_t *si, si_item_t *item)
762 {
763 si_mod_t *src;
764
765 if (si == NULL) return 0;
766 if (item == NULL) return 0;
767 if (si->name == NULL) return 0;
768 if (item->src == NULL) return 0;
769
770 src = (si_mod_t *)item->src;
771
772 if (src->name == NULL) return 0;
773 if (string_not_equal(si->name, src->name)) return 0;
774 return 0;
775 }
776
777 static si_mod_t *
778 search_alloc()
779 {
780 si_mod_t *out;
781 char *outname;
782 search_si_private_t *pp;
783
784 out = (si_mod_t *)calloc(1, sizeof(si_mod_t));
785 outname = strdup("search");
786 pp = (search_si_private_t *)calloc(1, sizeof(search_si_private_t));
787
788 if ((out == NULL) || (outname == NULL) || (pp == NULL))
789 {
790 if (out != NULL) free(out);
791 if (outname != NULL) free(outname);
792 if (pp != NULL) free(pp);
793
794 errno = ENOMEM;
795 return NULL;
796 }
797
798 out->name = outname;
799 out->vers = 1;
800 out->refcount = 1;
801 out->private = pp;
802
803 out->sim_close = search_close;
804
805 out->sim_is_valid = search_is_valid;
806
807 out->sim_user_byname = search_user_byname;
808 out->sim_user_byuid = search_user_byuid;
809 out->sim_user_all = search_user_all;
810
811 out->sim_group_byname = search_group_byname;
812 out->sim_group_bygid = search_group_bygid;
813 out->sim_group_all = search_group_all;
814
815 out->sim_grouplist = search_groupist;
816
817 out->sim_netgroup_byname = search_netgroup_byname;
818 out->sim_in_netgroup = search_in_netgroup;
819
820 out->sim_alias_byname = search_alias_byname;
821 out->sim_alias_all = search_alias_all;
822
823 out->sim_host_byname = search_host_byname;
824 out->sim_host_byaddr = search_host_byaddr;
825 out->sim_host_all = search_host_all;
826
827 out->sim_network_byname = search_network_byname;
828 out->sim_network_byaddr = search_network_byaddr;
829 out->sim_network_all = search_network_all;
830
831 out->sim_service_byname = search_service_byname;
832 out->sim_service_byport = search_service_byport;
833 out->sim_service_all = search_service_all;
834
835 out->sim_protocol_byname = search_protocol_byname;
836 out->sim_protocol_bynumber = search_protocol_bynumber;
837 out->sim_protocol_all = search_protocol_all;
838
839 out->sim_rpc_byname = search_rpc_byname;
840 out->sim_rpc_bynumber = search_rpc_bynumber;
841 out->sim_rpc_all = search_rpc_all;
842
843 out->sim_fs_byspec = search_fs_byspec;
844 out->sim_fs_byfile = search_fs_byfile;
845 out->sim_fs_all = search_fs_all;
846
847 out->sim_mac_byname = search_mac_byname;
848 out->sim_mac_bymac = search_mac_bymac;
849 out->sim_mac_all = search_mac_all;
850
851 out->sim_addrinfo = search_addrinfo;
852 out->sim_wants_addrinfo = search_wants_addrinfo;
853 out->sim_nameinfo = search_nameinfo;
854
855 out->sim_srv_byname = search_srv_byname;
856
857 return out;
858 }
859
860 static void
861 init_optional_modules(search_si_private_t *pp)
862 {
863 if (pp->mdns == NULL)
864 {
865 pp->mdns = si_module_with_name("mdns");
866 /* allow this to fail */
867 }
868
869 #ifdef DS_AVAILABLE
870 if (pp->flags & SEARCH_FLAG_MAC)
871 {
872 if (pp->ds == NULL)
873 {
874 pp->ds = si_module_with_name("ds");
875 /* allow this to fail */
876 }
877 }
878 #endif
879
880 if (pp->flags & (SEARCH_FLAG_APPLETV | SEARCH_FLAG_IPHONE))
881 {
882 if (pp->dns == NULL)
883 {
884 pp->dns = si_module_with_name("dns");
885 /* allow this to fail */
886 }
887 }
888 }
889
890 __private_extern__ si_mod_t *
891 si_module_static_search()
892 {
893 si_mod_t *out;
894 search_si_private_t *pp;
895 FILE *conf;
896 char *line, **tokens;
897 int cat, i, j, ntokens;
898
899 out = search_alloc();
900 if (out == NULL) return NULL;
901
902 pp = (search_si_private_t *)out->private;
903 if (pp == NULL)
904 {
905 free(out);
906 return NULL;
907 }
908
909 #ifdef CONFIG_MAC
910 pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_MAC;
911 #endif
912 #ifdef CONFIG_APPLETV
913 pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_APPLETV;
914 #endif
915
916 #ifdef CONFIG_IPHONE
917 pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_IPHONE;
918 #endif
919
920 pp->cache = si_module_with_name("cache");
921 if (pp->cache == NULL)
922 {
923 search_close(out);
924 return NULL;
925 }
926
927 pp->file = si_module_with_name("file");
928 if (pp->file == NULL)
929 {
930 search_close(out);
931 return NULL;
932 }
933
934 init_optional_modules(pp);
935
936 conf = fopen(_PATH_SI_CONF, "r");
937 if (conf == NULL) return out;
938
939 forever
940 {
941 line = _fsi_get_line(conf);
942 if (line == NULL) break;
943
944 if (line[0] == '#')
945 {
946 free(line);
947 line = NULL;
948 continue;
949 }
950
951 ntokens = 0;
952 tokens = _fsi_tokenize(line, " : ", 0, &ntokens);
953
954 if (ntokens < 2)
955 {
956 free(tokens);
957 tokens = NULL;
958 free(line);
959 line = NULL;
960 continue;
961 }
962
963 if (string_equal(tokens[0], "config"))
964 {
965 if (string_equal(tokens[1], "mac")) pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_MAC;
966 else if (string_equal(tokens[1], "appletv")) pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_APPLETV;
967 else if (string_equal(tokens[1], "iphone")) pp->flags = SEARCH_FLAG_CACHE_ENABLED | SEARCH_FLAG_IPHONE;
968
969 init_optional_modules(pp);
970
971 free(tokens);
972 tokens = NULL;
973 free(line);
974 line = NULL;
975 continue;
976 }
977
978 if (string_equal(tokens[0], "user")) cat = CATEGORY_USER;
979 else if (string_equal(tokens[0], "group")) cat = CATEGORY_GROUP;
980 else if (string_equal(tokens[0], "grouplist")) cat = CATEGORY_GROUPLIST;
981 else if (string_equal(tokens[0], "netgroup")) cat = CATEGORY_NETGROUP;
982 else if (string_equal(tokens[0], "alias")) cat = CATEGORY_ALIAS;
983 else if (string_equal(tokens[0], "host")) cat = CATEGORY_HOST_IPV4;
984 else if (string_equal(tokens[0], "network")) cat = CATEGORY_NETWORK;
985 else if (string_equal(tokens[0], "service")) cat = CATEGORY_SERVICE;
986 else if (string_equal(tokens[0], "protocol")) cat = CATEGORY_PROTOCOL;
987 else if (string_equal(tokens[0], "rpc")) cat = CATEGORY_RPC;
988 else if (string_equal(tokens[0], "fs")) cat = CATEGORY_FS;
989 else if (string_equal(tokens[0], "mac")) cat = CATEGORY_MAC;
990 else if (string_equal(tokens[0], "addrinfo")) cat = CATEGORY_ADDRINFO;
991 else if (string_equal(tokens[0], "nameinfo")) cat = CATEGORY_NAMEINFO;
992 else
993 {
994 free(tokens);
995 tokens = NULL;
996 free(line);
997 line = NULL;
998 continue;
999 }
1000
1001 do_ipv6:
1002
1003 if (pp->search_list[cat].module != NULL)
1004 {
1005 free(tokens);
1006 tokens = NULL;
1007 free(line);
1008 line = NULL;
1009 continue;
1010 }
1011
1012 pp->search_list[cat].count = ntokens - 1;
1013 pp->search_list[cat].module = (si_mod_t **)calloc(pp->search_list[cat].count, sizeof(si_mod_t *));
1014 if (pp->search_list[cat].module == NULL)
1015 {
1016 search_close(out);
1017 free(tokens);
1018 tokens = NULL;
1019 free(line);
1020 line = NULL;
1021 return NULL;
1022 }
1023
1024 for (i = 1, j = 0; i < ntokens; i++, j++)
1025 {
1026 if (string_equal(tokens[i], "cache"))
1027 {
1028 pp->search_list[cat].module[j] = pp->cache;
1029 pp->search_list[cat].flags = SEARCH_FLAG_CACHE_ENABLED;
1030 }
1031 else if (string_equal(tokens[i], "file"))
1032 {
1033 if (pp->file == NULL) pp->file = si_module_with_name("file");
1034 pp->search_list[cat].module[j] = pp->file;
1035 }
1036 else if (string_equal(tokens[i], "dns"))
1037 {
1038 if (pp->dns == NULL) pp->dns = si_module_with_name("dns");
1039 pp->search_list[cat].module[j] = pp->dns;
1040 }
1041 else if (string_equal(tokens[i], "mdns"))
1042 {
1043 if (pp->mdns == NULL) pp->mdns = si_module_with_name("mdns");
1044 pp->search_list[cat].module[j] = pp->mdns;
1045 }
1046 else if (string_equal(tokens[i], "ds"))
1047 {
1048 if (pp->ds == NULL) pp->ds = si_module_with_name("ds");
1049 pp->search_list[cat].module[j] = pp->ds;
1050 }
1051 }
1052
1053 if (cat == CATEGORY_HOST_IPV4)
1054 {
1055 cat = CATEGORY_HOST_IPV6;
1056 goto do_ipv6;
1057 }
1058
1059 free(tokens);
1060 tokens = NULL;
1061 free(line);
1062 line = NULL;
1063 }
1064
1065 return out;
1066 }
1067
1068 __private_extern__ si_mod_t *
1069 search_custom(int n, ...)
1070 {
1071 va_list ap;
1072 si_mod_t *out, *m;
1073 search_si_private_t *pp;
1074 int cat, i;
1075 char *name;
1076
1077 if (n == 0) return si_module_static_search();
1078
1079 out = search_alloc();
1080 if (out == NULL) return NULL;
1081
1082 pp = (search_si_private_t *)out->private;
1083 if (pp == NULL)
1084 {
1085 free(out);
1086 return NULL;
1087 }
1088
1089 for (cat = 0; cat < CATEGORY_COUNT; cat++)
1090 {
1091 pp->search_list[cat].count = n;
1092 pp->search_list[cat].module = (si_mod_t **)calloc(pp->search_list[cat].count, sizeof(si_mod_t *));
1093 if (pp->search_list[cat].module == NULL)
1094 {
1095 search_close(out);
1096 return NULL;
1097 }
1098
1099 }
1100
1101 va_start(ap, n);
1102
1103 for (i = 0; i < n; i++)
1104 {
1105 name = va_arg(ap, char *);
1106 if (name == NULL) break;
1107
1108 m = NULL;
1109 if (string_equal(name, "cache"))
1110 {
1111 if (pp->cache == NULL)
1112 {
1113 pp->cache = si_module_with_name("cache");
1114 m = pp->cache;
1115 if (pp->cache == NULL)
1116 {
1117 search_close(out);
1118 return NULL;
1119 }
1120 }
1121 }
1122 else if (string_equal(name, "file"))
1123 {
1124 if (pp->file == NULL)
1125 {
1126 pp->file = si_module_with_name("file");
1127 m = pp->file;
1128 if (pp->file == NULL)
1129 {
1130 search_close(out);
1131 return NULL;
1132 }
1133 }
1134 }
1135 else if (string_equal(name, "dns"))
1136 {
1137 if (pp->dns == NULL)
1138 {
1139 pp->dns = si_module_with_name("dns");
1140 m = pp->dns;
1141 if (pp->dns == NULL)
1142 {
1143 search_close(out);
1144 return NULL;
1145 }
1146 }
1147 }
1148 else if (string_equal(name, "mdns"))
1149 {
1150 if (pp->mdns == NULL)
1151 {
1152 pp->mdns = si_module_with_name("mdns");
1153 m = pp->mdns;
1154 if (pp->mdns == NULL)
1155 {
1156 search_close(out);
1157 return NULL;
1158 }
1159 }
1160 }
1161 else if (string_equal(name, "ds"))
1162 {
1163 if (pp->ds == NULL)
1164 {
1165 pp->ds = si_module_with_name("ds");
1166 m = pp->ds;
1167 if (pp->ds == NULL)
1168 {
1169 search_close(out);
1170 return NULL;
1171 }
1172 }
1173 }
1174
1175 for (cat = 0; cat < CATEGORY_COUNT; cat++)
1176 {
1177 if (string_equal(name, "cache")) pp->search_list[cat].flags = SEARCH_FLAG_CACHE_ENABLED;
1178 pp->search_list[cat].module[i] = m;
1179 }
1180 }
1181
1182 va_end(ap);
1183
1184 return out;
1185 }