Libinfo-517.200.9.tar.gz
[apple/libinfo.git] / lookup.subproj / search_module.c
1 /*
2 * Copyright (c) 2008-2011 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 <dispatch/dispatch.h>
37 #include "si_module.h"
38
39 #define _PATH_SI_CONF "/etc/sysinfo.conf"
40
41 #define SEARCH_FLAG_CACHE_ENABLED 0x00000001
42 #define SEARCH_MODULE_FLAG_DISABLED 0x00000001
43
44 typedef struct
45 {
46 si_mod_t **module;
47 uint32_t *module_flags;
48 uint32_t count;
49 uint32_t flags;
50 } search_list_t;
51
52 typedef struct
53 {
54 search_list_t search_list[CATEGORY_COUNT];
55 si_mod_t *cache;
56 } search_si_private_t;
57
58 extern void si_cache_add_item(si_mod_t *si, si_mod_t *src, si_item_t *item);
59 extern void si_cache_add_list(si_mod_t *si, si_mod_t *src, si_list_t *list);
60
61 extern char **_fsi_tokenize(char *data, const char *sep, int trailing_empty, int *ntokens);
62 extern char *_fsi_get_line(FILE *fp);
63
64 static void si_module_config_parse_line(search_si_private_t *pp, char *line);
65 static int si_module_config_modules_for_category(search_si_private_t *pp, int cat, int ntokens, const char * const *tokens);
66
67 static si_mod_t *
68 search_get_module(search_si_private_t *pp, int cat, int *n)
69 {
70 int x;
71
72 if ((pp == NULL) || (n == NULL)) return NULL;
73
74 x = *n;
75 *n = x + 1;
76
77 /* Use custom search list if available */
78 if (pp->search_list[cat].count > 0 && x < pp->search_list[cat].count)
79 {
80 return pp->search_list[cat].module[x];
81 }
82
83 /* Otherwise use the default search list */
84 while (x < pp->search_list[CATEGORY_DEFAULT].count)
85 {
86 if (pp->search_list[CATEGORY_DEFAULT].module_flags[x] & SEARCH_MODULE_FLAG_DISABLED)
87 {
88 x++;
89 *n = x + 1;
90 }
91 else
92 {
93 return pp->search_list[CATEGORY_DEFAULT].module[x];
94 }
95 }
96
97 return NULL;
98 }
99
100 __private_extern__ void
101 search_set_flags(si_mod_t *si, const char *name, uint32_t flag)
102 {
103 search_si_private_t *pp;
104 uint32_t i;
105
106 if (si == NULL) return;
107 if (si->private == NULL) return;
108
109 pp = (search_si_private_t *)si->private;
110
111 for (i = 0; i < pp->search_list[CATEGORY_DEFAULT].count; i++)
112 {
113 si_mod_t *mod = pp->search_list[CATEGORY_DEFAULT].module[i];
114 if ((mod == NULL) || (mod->name == NULL)) continue;
115
116 if (string_equal(name, mod->name))
117 {
118 pp->search_list[CATEGORY_DEFAULT].module_flags[i] = flag;
119 break;
120 }
121 }
122 }
123
124 static si_mod_t *
125 search_cat_cache(search_si_private_t *pp, int cat)
126 {
127 if (pp == NULL) return NULL;
128 if (cat < 0 || cat > CATEGORY_COUNT) return NULL;
129
130 if (pp->search_list[cat].count == 0)
131 {
132 cat = CATEGORY_DEFAULT;
133 }
134
135 if ((pp->search_list[cat].flags & SEARCH_FLAG_CACHE_ENABLED) != 0)
136 {
137 return pp->cache;
138 }
139
140 return NULL;
141 }
142
143 static void
144 search_close(si_mod_t *si)
145 {
146 int i;
147 search_si_private_t *pp;
148
149 if (si == NULL) return;
150 if (si->private == NULL) return;
151
152 pp = (search_si_private_t *)si->private;
153
154 for (i = 0; i < CATEGORY_COUNT; i++)
155 {
156 if (pp->search_list[i].module != NULL)
157 {
158 free(pp->search_list[i].module);
159 pp->search_list[i].module = NULL;
160 pp->search_list[i].count = 0;
161 pp->search_list[i].flags = 0;
162 }
163 }
164
165 free(pp);
166 }
167
168 static si_item_t *
169 search_item_byname(si_mod_t *si, const char *name, int cat, si_item_t *(*call)(si_mod_t *, const char *))
170 {
171 int i;
172 search_si_private_t *pp;
173 si_item_t *item;
174 si_mod_t *src;
175
176 if (si == NULL) return NULL;
177 if (call == NULL) return NULL;
178
179 pp = (search_si_private_t *)si->private;
180 if (pp == NULL) return NULL;
181
182 i = 0;
183
184 while (NULL != (src = search_get_module(pp, cat, &i)))
185 {
186 item = call(src, name);
187 if (item != NULL)
188 {
189 si_cache_add_item(search_cat_cache(pp, cat), src, item);
190 return item;
191 }
192 }
193
194 return NULL;
195 }
196
197 static si_item_t *
198 search_item_bynumber(si_mod_t *si, uint32_t number, int cat, si_item_t *(*call)(si_mod_t *, uint32_t))
199 {
200 int i;
201 search_si_private_t *pp;
202 si_item_t *item;
203 si_mod_t *src;
204
205 if (si == NULL) return NULL;
206 if (call == NULL) return NULL;
207
208 pp = (search_si_private_t *)si->private;
209 if (pp == NULL) return NULL;
210
211 i = 0;
212
213 while (NULL != (src = search_get_module(pp, cat, &i)))
214 {
215 item = call(src, number);
216 if (item != NULL)
217 {
218 si_cache_add_item(search_cat_cache(pp, cat), src, item);
219 return item;
220 }
221 }
222
223 return NULL;
224 }
225
226 static si_item_t *
227 search_item_byuuid(si_mod_t *si, uuid_t uuid, int cat, si_item_t *(*call)(si_mod_t *, uuid_t))
228 {
229 int i;
230 search_si_private_t *pp;
231 si_item_t *item;
232 si_mod_t *src;
233
234 if (si == NULL) return NULL;
235 if (call == NULL) return NULL;
236
237 pp = (search_si_private_t *)si->private;
238 if (pp == NULL) return NULL;
239
240 i = 0;
241
242 while (NULL != (src = search_get_module(pp, cat, &i)))
243 {
244 item = call(src, uuid);
245 if (item != NULL)
246 {
247 /*
248 * N.B. item not added to cache, since the data does not
249 * contain the uuid that was used to find it.
250 */
251 return item;
252 }
253 }
254
255 return NULL;
256 }
257 static si_list_t *
258 search_list(si_mod_t *si, int cat, si_list_t *(*call)(si_mod_t *))
259 {
260 int i, null_res;
261 search_si_private_t *pp;
262 si_list_t *list, *all;
263 si_mod_t *cache, *src;
264
265 if (si == NULL) return NULL;
266 if (call == NULL) return NULL;
267
268 pp = (search_si_private_t *)si->private;
269 if (pp == NULL) return NULL;
270
271 cache = search_cat_cache(pp, cat);
272 if (cache != NULL)
273 {
274 list = call(cache);
275 if (list != NULL) return list;
276 }
277
278 i = 0;
279
280 all = NULL;
281 null_res = 0;
282
283 while (NULL != (src = search_get_module(pp, cat, &i)))
284 {
285 if (src == pp->cache) continue;
286
287 list = call(src);
288 if (list == NULL)
289 {
290 null_res = 1;
291 continue;
292 }
293
294 all = si_list_concat(all, list);
295 si_list_release(list);
296 }
297
298 if ((all != NULL) && (null_res == 0)) si_cache_add_list(cache, si, all);
299 return all;
300 }
301
302 static si_item_t *
303 search_user_byname(si_mod_t *si, const char *name)
304 {
305 return search_item_byname(si, name, CATEGORY_USER, si_user_byname);
306 }
307
308 static si_item_t *
309 search_user_byuid(si_mod_t *si, uid_t uid)
310 {
311 return search_item_bynumber(si, (uint32_t)uid, CATEGORY_USER, si_user_byuid);
312 }
313
314 static si_item_t *
315 search_user_byuuid(si_mod_t *si, uuid_t uuid)
316 {
317 return search_item_byuuid(si, uuid, CATEGORY_USER, si_user_byuuid);
318 }
319
320 static si_list_t *
321 search_user_all(si_mod_t *si)
322 {
323 return search_list(si, CATEGORY_USER, si_user_all);
324 }
325
326 static si_item_t *
327 search_group_byname(si_mod_t *si, const char *name)
328 {
329 return search_item_byname(si, name, CATEGORY_GROUP, si_group_byname);
330 }
331
332 static si_item_t *
333 search_group_bygid(si_mod_t *si, gid_t gid)
334 {
335 return search_item_bynumber(si, (uint32_t)gid, CATEGORY_GROUP, si_group_bygid);
336 }
337
338 static si_item_t *
339 search_group_byuuid(si_mod_t *si, uuid_t uuid)
340 {
341 return search_item_byuuid(si, uuid, CATEGORY_GROUP, si_group_byuuid);
342 }
343
344 static si_list_t *
345 search_group_all(si_mod_t *si)
346 {
347 return search_list(si, CATEGORY_GROUP, si_group_all);
348 }
349
350 static si_item_t *
351 search_groupist(si_mod_t *si, const char *name, uint32_t count)
352 {
353 int i;
354 search_si_private_t *pp;
355 si_item_t *item = NULL;
356 si_mod_t *src;
357
358 if (si == NULL) return NULL;
359
360 pp = (search_si_private_t *)si->private;
361 if (pp == NULL) return NULL;
362
363 i = 0;
364
365 while (NULL != (src = search_get_module(pp, CATEGORY_GROUPLIST, &i))) {
366 if (src == pp->cache) continue;
367
368 if (src->vtable->sim_grouplist != NULL) {
369 item = src->vtable->sim_grouplist(si, name, count);
370 if (item != NULL) break;
371 }
372 }
373
374 return item;
375 }
376
377 static si_list_t *
378 search_netgroup_byname(si_mod_t *si, const char *name)
379 {
380 int i, cat, null_res;
381 search_si_private_t *pp;
382 si_list_t *list, *all;
383 si_mod_t *cache, *src;
384
385 if (si == NULL) return NULL;
386
387 pp = (search_si_private_t *)si->private;
388 if (pp == NULL) return NULL;
389
390 cat = CATEGORY_NETGROUP;
391
392 cache = search_cat_cache(pp, cat);
393 if (cache != NULL)
394 {
395 list = si_netgroup_byname(cache, name);
396 if (list != NULL) return list;
397 }
398
399 i = 0;
400 null_res = 0;
401
402 all = NULL;
403 while (NULL != (src = search_get_module(pp, cat, &i)))
404 {
405 if (src == pp->cache) continue;
406
407 list = si_netgroup_byname(src, name);
408 if (list == NULL)
409 {
410 null_res = 1;
411 continue;
412 }
413
414 all = si_list_concat(all, list);
415 si_list_release(list);
416 }
417
418 if ((all != NULL) && (null_res == 0)) si_cache_add_list(cache, si, all);
419 return all;
420 }
421
422 static int
423 search_in_netgroup(si_mod_t *si, const char *group, const char *host, const char *user, const char *domain)
424 {
425 int i, cat, innetgr;
426 search_si_private_t *pp;
427 si_mod_t *src;
428
429 if (si == NULL) return 0;
430
431 pp = (search_si_private_t *)si->private;
432 if (pp == NULL) return 0;
433
434 cat = CATEGORY_NETGROUP;
435 i = 0;
436
437 while (NULL != (src = search_get_module(pp, cat, &i)))
438 {
439 innetgr = si_in_netgroup(src, group, host, user, domain);
440 if (innetgr != 0) return 1;
441 }
442
443 return 0;
444 }
445
446 static si_item_t *
447 search_alias_byname(si_mod_t *si, const char *name)
448 {
449 return search_item_byname(si, name, CATEGORY_ALIAS, si_alias_byname);
450 }
451
452 static si_list_t *
453 search_alias_all(si_mod_t *si)
454 {
455 return search_list(si, CATEGORY_ALIAS, si_alias_all);
456 }
457
458 static si_item_t *
459 search_host_byname(si_mod_t *si, const char *name, int af, const char *interface, uint32_t *err)
460 {
461 int i, cat;
462 search_si_private_t *pp;
463 si_item_t *item;
464 si_mod_t *src;
465
466 if (err != NULL) *err = SI_STATUS_NO_ERROR;
467
468 if ((si == NULL) || (name == NULL))
469 {
470 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
471 return NULL;
472 }
473
474 pp = (search_si_private_t *)si->private;
475 if (pp == NULL)
476 {
477 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
478 return NULL;
479 }
480
481 cat = CATEGORY_HOST_IPV4;
482 if (af == AF_INET6) cat = CATEGORY_HOST_IPV6;
483
484 i = 0;
485
486 while (NULL != (src = search_get_module(pp, cat, &i)))
487 {
488 item = si_host_byname(src, name, af, interface, err);
489 if (item != NULL)
490 {
491 si_cache_add_item(search_cat_cache(pp, cat), src, item);
492 return item;
493 }
494 }
495
496 if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
497 return NULL;
498 }
499
500 static si_item_t *
501 search_host_byaddr(si_mod_t *si, const void *addr, int af, const char *interface, uint32_t *err)
502 {
503 int i, cat;
504 search_si_private_t *pp;
505 si_item_t *item;
506 si_mod_t *src;
507
508 if (err != NULL) *err = SI_STATUS_NO_ERROR;
509
510 if ((si == NULL) || (addr == NULL))
511 {
512 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
513 return NULL;
514 }
515
516 pp = (search_si_private_t *)si->private;
517 if (pp == NULL)
518 {
519 if (err != NULL) *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
520 return NULL;
521 }
522
523 cat = CATEGORY_HOST_IPV4;
524 if (af == AF_INET6) cat = CATEGORY_HOST_IPV6;
525
526 i = 0;
527
528 while (NULL != (src = search_get_module(pp, cat, &i)))
529 {
530 item = si_host_byaddr(src, addr, af, interface, err);
531 if (item != NULL)
532 {
533 si_cache_add_item(search_cat_cache(pp, cat), src, item);
534 return item;
535 }
536 }
537
538 if (err != NULL) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
539 return NULL;
540 }
541
542 static si_list_t *
543 search_host_all(si_mod_t *si)
544 {
545 return search_list(si, CATEGORY_HOST, si_host_all);
546 }
547
548 static si_item_t *
549 search_network_byname(si_mod_t *si, const char *name)
550 {
551 return search_item_byname(si, name, CATEGORY_NETWORK, si_network_byname);
552 }
553
554 static si_item_t *
555 search_network_byaddr(si_mod_t *si, uint32_t addr)
556 {
557 return search_item_bynumber(si, addr, CATEGORY_NETWORK, si_network_byaddr);
558 }
559
560 static si_list_t *
561 search_network_all(si_mod_t *si)
562 {
563 return search_list(si, CATEGORY_NETWORK, si_network_all);
564 }
565
566 static si_item_t *
567 search_service_byname(si_mod_t *si, const char *name, const char *proto)
568 {
569 int i, cat;
570 si_item_t *item;
571 search_si_private_t *pp;
572 si_mod_t *src;
573
574 if (si == NULL) return NULL;
575 if (name == NULL) return NULL;
576
577 pp = (search_si_private_t *)si->private;
578 if (pp == NULL) return NULL;
579
580 cat = CATEGORY_SERVICE;
581 i = 0;
582
583 while (NULL != (src = search_get_module(pp, cat, &i)))
584 {
585 item = si_service_byname(src, name, proto);
586 if (item != NULL)
587 {
588 si_cache_add_item(search_cat_cache(pp, cat), src, item);
589 return item;
590 }
591 }
592
593 return NULL;
594 }
595
596 static si_item_t *
597 search_service_byport(si_mod_t *si, int port, const char *proto)
598 {
599 int i, cat;
600 search_si_private_t *pp;
601 si_item_t *item;
602 si_mod_t *src;
603
604 if (si == NULL) return NULL;
605
606 pp = (search_si_private_t *)si->private;
607 if (pp == NULL) return NULL;
608
609 cat = CATEGORY_SERVICE;
610 i = 0;
611
612 while (NULL != (src = search_get_module(pp, cat, &i)))
613 {
614 item = si_service_byport(src, port, proto);
615 if (item != NULL)
616 {
617 si_cache_add_item(search_cat_cache(pp, cat), src, item);
618 return item;
619 }
620 }
621
622 return NULL;
623 }
624
625 static si_list_t *
626 search_service_all(si_mod_t *si)
627 {
628 return search_list(si, CATEGORY_SERVICE, si_service_all);
629 }
630
631 static si_item_t *
632 search_protocol_byname(si_mod_t *si, const char *name)
633 {
634 return search_item_byname(si, name, CATEGORY_PROTOCOL, si_protocol_byname);
635 }
636
637 static si_item_t *
638 search_protocol_bynumber(si_mod_t *si, int number)
639 {
640 return search_item_bynumber(si, (uint32_t)number, CATEGORY_PROTOCOL, si_protocol_bynumber);
641 }
642
643 static si_list_t *
644 search_protocol_all(si_mod_t *si)
645 {
646 return search_list(si, CATEGORY_PROTOCOL, si_protocol_all);
647 }
648
649 static si_item_t *
650 search_rpc_byname(si_mod_t *si, const char *name)
651 {
652 return search_item_byname(si, name, CATEGORY_RPC, si_rpc_byname);
653 }
654
655 static si_item_t *
656 search_rpc_bynumber(si_mod_t *si, int number)
657 {
658 int i, cat;
659 search_si_private_t *pp;
660 si_item_t *item;
661 si_mod_t *src;
662
663 if (si == NULL) return NULL;
664
665 pp = (search_si_private_t *)si->private;
666 if (pp == NULL) return NULL;
667
668 cat = CATEGORY_RPC;
669 i = 0;
670
671 while (NULL != (src = search_get_module(pp, cat, &i)))
672 {
673 item = si_rpc_bynumber(src, number);
674 if (item != NULL)
675 {
676 si_cache_add_item(search_cat_cache(pp, cat), src, item);
677 return item;
678 }
679 }
680
681 return NULL;
682 }
683
684 static si_list_t *
685 search_rpc_all(si_mod_t *si)
686 {
687 return search_list(si, CATEGORY_RPC, si_rpc_all);
688 }
689
690 static si_item_t *
691 search_fs_byspec(si_mod_t *si, const char *name)
692 {
693 return search_item_byname(si, name, CATEGORY_FS, si_fs_byspec);
694 }
695
696 static si_item_t *
697 search_fs_byfile(si_mod_t *si, const char *name)
698 {
699 return search_item_byname(si, name, CATEGORY_FS, si_fs_byfile);
700 }
701
702 static si_list_t *
703 search_fs_all(si_mod_t *si)
704 {
705 return search_list(si, CATEGORY_FS, si_fs_all);
706 }
707
708 static si_item_t *
709 search_mac_byname(si_mod_t *si, const char *name)
710 {
711 return search_item_byname(si, name, CATEGORY_MAC, si_mac_byname);
712 }
713
714 static si_item_t *
715 search_mac_bymac(si_mod_t *si, const char *mac)
716 {
717 return search_item_byname(si, mac, CATEGORY_MAC, si_mac_bymac);
718 }
719
720 static si_list_t *
721 search_mac_all(si_mod_t *si)
722 {
723 return search_list(si, CATEGORY_MAC, si_mac_all);
724 }
725
726 static si_list_t *
727 search_srv_byname(si_mod_t *si, const char* qname, const char *interface, uint32_t *err)
728 {
729 int i, cat;
730 si_list_t *list = NULL;
731 si_mod_t *src;
732 search_si_private_t *pp;
733
734 if (si == NULL) return NULL;
735
736 pp = (search_si_private_t *)si->private;
737 if (pp == NULL) return NULL;
738
739 cat = CATEGORY_SRV;
740 i = 0;
741
742 while (NULL != (src = search_get_module(pp, cat, &i)))
743 {
744 if (src == pp->cache) continue;
745
746 if (src->vtable->sim_srv_byname != NULL)
747 {
748 list = src->vtable->sim_srv_byname(src, qname, interface, err);
749 if (list != NULL) return list;
750 }
751 }
752
753 if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME;
754 return NULL;
755 }
756
757 static int
758 search_wants_addrinfo(si_mod_t *si)
759 {
760 int i, cat;
761 si_mod_t *src;
762 search_si_private_t *pp;
763
764 if (si == NULL) return 0;
765
766 pp = (search_si_private_t *)si->private;
767 if (pp == NULL) return 0;
768
769 cat = CATEGORY_ADDRINFO;
770 i = 0;
771
772 while (NULL != (src = search_get_module(pp, cat, &i)))
773 {
774 if (src == pp->cache) continue;
775 if (src->vtable->sim_addrinfo != NULL) return 1;
776 }
777
778 return 0;
779 }
780
781 static si_list_t *
782 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)
783 {
784 int i, cat;
785 search_si_private_t *pp;
786 si_list_t *list = NULL;
787 si_mod_t *src;
788
789 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
790
791 if (si == NULL) return NULL;
792
793 pp = (search_si_private_t *)si->private;
794 if (pp == NULL) return NULL;
795
796 cat = CATEGORY_ADDRINFO;
797 i = 0;
798
799 while (NULL != (src = search_get_module(pp, cat, &i)))
800 {
801 if (src == pp->cache) continue;
802
803 if (src->vtable->sim_addrinfo != NULL)
804 {
805 list = src->vtable->sim_addrinfo(src, node, serv, family, socktype, protocol, flags, interface, err);
806 if (list != NULL) return list;
807 }
808 }
809
810 if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME;
811 return NULL;
812 }
813
814 static si_item_t *
815 search_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, const char *interface, uint32_t *err)
816 {
817 int i, cat;
818 search_si_private_t *pp;
819 si_item_t *item;
820 si_mod_t *src;
821
822 if (err != NULL) *err = SI_STATUS_EAI_FAIL;
823
824 if (si == NULL) return NULL;
825
826 pp = (search_si_private_t *)si->private;
827 if (pp == NULL) return NULL;
828
829 cat = CATEGORY_NAMEINFO;
830 i = 0;
831
832 while (NULL != (src = search_get_module(pp, cat, &i)))
833 {
834 item = si_nameinfo(src, sa, flags, interface, err);
835 if (item != NULL)
836 {
837 si_cache_add_item(search_cat_cache(pp, cat), src, item);
838 if (err != NULL) *err = SI_STATUS_NO_ERROR;
839 return item;
840 }
841 }
842
843 if ((i > 0) && (err != NULL)) *err = SI_STATUS_EAI_NONAME;
844 return NULL;
845 }
846
847 static int
848 search_is_valid(si_mod_t *si, si_item_t *item)
849 {
850 si_mod_t *src;
851
852 if (si == NULL) return 0;
853 if (item == NULL) return 0;
854 if (si->name == NULL) return 0;
855 if (item->src == NULL) return 0;
856
857 src = (si_mod_t *)item->src;
858
859 if (src->name == NULL) return 0;
860 if (string_not_equal(si->name, src->name)) return 0;
861 return 0;
862 }
863
864 si_mod_t *
865 si_module_static_search(void)
866 {
867 static bool result = false;
868
869 static const struct si_mod_vtable_s search_vtable =
870 {
871 .sim_close = &search_close,
872
873 .sim_is_valid = &search_is_valid,
874
875 .sim_user_byname = &search_user_byname,
876 .sim_user_byuid = &search_user_byuid,
877 .sim_user_byuuid = &search_user_byuuid,
878 .sim_user_all = &search_user_all,
879
880 .sim_group_byname = &search_group_byname,
881 .sim_group_bygid = &search_group_bygid,
882 .sim_group_byuuid = &search_group_byuuid,
883 .sim_group_all = &search_group_all,
884
885 .sim_grouplist = &search_groupist,
886
887 .sim_netgroup_byname = &search_netgroup_byname,
888 .sim_in_netgroup = &search_in_netgroup,
889
890 .sim_alias_byname = &search_alias_byname,
891 .sim_alias_all = &search_alias_all,
892
893 .sim_host_byname = &search_host_byname,
894 .sim_host_byaddr = &search_host_byaddr,
895 .sim_host_all = &search_host_all,
896
897 .sim_network_byname = &search_network_byname,
898 .sim_network_byaddr = &search_network_byaddr,
899 .sim_network_all = &search_network_all,
900
901 .sim_service_byname = &search_service_byname,
902 .sim_service_byport = &search_service_byport,
903 .sim_service_all = &search_service_all,
904
905 .sim_protocol_byname = &search_protocol_byname,
906 .sim_protocol_bynumber = &search_protocol_bynumber,
907 .sim_protocol_all = &search_protocol_all,
908
909 .sim_rpc_byname = &search_rpc_byname,
910 .sim_rpc_bynumber = &search_rpc_bynumber,
911 .sim_rpc_all = &search_rpc_all,
912
913 .sim_fs_byspec = &search_fs_byspec,
914 .sim_fs_byfile = &search_fs_byfile,
915 .sim_fs_all = &search_fs_all,
916
917 .sim_mac_byname = &search_mac_byname,
918 .sim_mac_bymac = &search_mac_bymac,
919 .sim_mac_all = &search_mac_all,
920
921 .sim_addrinfo = &search_addrinfo,
922 .sim_wants_addrinfo = &search_wants_addrinfo,
923 .sim_nameinfo = &search_nameinfo,
924
925 .sim_srv_byname = &search_srv_byname,
926 };
927
928 static si_mod_t si =
929 {
930 .vers = 1,
931 .refcount = 1,
932 .flags = SI_MOD_FLAG_STATIC,
933
934 .private = NULL,
935 .vtable = &search_vtable,
936 };
937
938 static dispatch_once_t once;
939
940 dispatch_once(&once, ^{
941 si.name = strdup("search");
942 search_si_private_t *pp = calloc(1, sizeof(search_si_private_t));
943 si.private = pp;
944
945 /*
946 * Default search order:
947 * 1) cache
948 * 2) DirectoryService/OpenDirectory (where available)
949 * 3) flat file
950 * 4) mDNSResponder
951 */
952
953 const char * const modules[] =
954 {
955 "default", // CATEGORY_DEFAULT
956 "cache",
957 #ifdef MUSER_AVAILABLE
958 "muser",
959 #endif
960 #ifdef DS_AVAILABLE
961 "ds",
962 #endif
963 "mdns",
964 "file",
965 };
966
967 int count = sizeof(modules) / sizeof(char *);
968 if (si_module_config_modules_for_category(pp, CATEGORY_DEFAULT, count, modules) != 0)
969 {
970 free(si.name);
971 si.name = NULL;
972 free(pp);
973 si.private = NULL;
974 result = true;
975 return;
976 }
977
978 pp->cache = pp->search_list[CATEGORY_DEFAULT].module[0];
979
980 char *check = getenv("SYSINFO_CONF_ENABLE");
981 if ((check != NULL) && (!strcmp(check, "1")))
982 {
983 FILE *conf = fopen(_PATH_SI_CONF, "r");
984 errno = 0;
985 if (conf != NULL)
986 {
987 forever
988 {
989 char *line = _fsi_get_line(conf);
990 if (line == NULL) break;
991
992 si_module_config_parse_line(pp, line);
993 free(line);
994 }
995
996 fclose(conf);
997 }
998 }
999 });
1000
1001 return (!result) ? &si : NULL;
1002 }
1003
1004 static void
1005 si_module_config_parse_line(search_si_private_t *pp, char *line)
1006 {
1007 if (line == NULL || line[0] == '#') {
1008 return;
1009 }
1010
1011 int ntokens = 0;
1012 char **tokens = _fsi_tokenize(line, " : ", 0, &ntokens);
1013
1014 int cat = CATEGORY_INVALID;
1015
1016 if (string_equal(tokens[0], "default")) cat = CATEGORY_DEFAULT;
1017 else if (string_equal(tokens[0], "user")) cat = CATEGORY_USER;
1018 else if (string_equal(tokens[0], "group")) cat = CATEGORY_GROUP;
1019 else if (string_equal(tokens[0], "grouplist")) cat = CATEGORY_GROUPLIST;
1020 else if (string_equal(tokens[0], "netgroup")) cat = CATEGORY_NETGROUP;
1021 else if (string_equal(tokens[0], "alias")) cat = CATEGORY_ALIAS;
1022 else if (string_equal(tokens[0], "host")) cat = CATEGORY_HOST_IPV4;
1023 else if (string_equal(tokens[0], "network")) cat = CATEGORY_NETWORK;
1024 else if (string_equal(tokens[0], "service")) cat = CATEGORY_SERVICE;
1025 else if (string_equal(tokens[0], "protocol")) cat = CATEGORY_PROTOCOL;
1026 else if (string_equal(tokens[0], "rpc")) cat = CATEGORY_RPC;
1027 else if (string_equal(tokens[0], "fs")) cat = CATEGORY_FS;
1028 else if (string_equal(tokens[0], "mac")) cat = CATEGORY_MAC;
1029 else if (string_equal(tokens[0], "addrinfo")) cat = CATEGORY_ADDRINFO;
1030 else if (string_equal(tokens[0], "nameinfo")) cat = CATEGORY_NAMEINFO;
1031
1032 if (cat != CATEGORY_INVALID)
1033 {
1034 si_module_config_modules_for_category(pp, cat, ntokens, (const char * const *)tokens);
1035 }
1036
1037 free(tokens);
1038 }
1039
1040 static int
1041 si_module_config_modules_for_category(search_si_private_t *pp, int cat, int ntokens, const char * const *tokens)
1042 {
1043 int count = ntokens - 1;
1044 pp->search_list[cat].count = count;
1045 if (count == 0)
1046 {
1047 return -1;
1048 }
1049
1050 pp->search_list[cat].module = (si_mod_t **)calloc(pp->search_list[cat].count, sizeof(si_mod_t *));
1051 pp->search_list[cat].module_flags = (uint32_t *)calloc(pp->search_list[cat].count, sizeof(uint32_t));
1052 if ((pp->search_list[cat].module == NULL) || (pp->search_list[cat].module_flags == NULL))
1053 {
1054 free(pp->search_list[cat].module);
1055 free(pp->search_list[cat].module_flags);
1056 return -1;
1057 }
1058
1059 int i, j;
1060 for (i = 1, j = 0; i < ntokens; i++)
1061 {
1062 si_mod_t *mod = si_module_with_name(tokens[i]);
1063 if (mod != NULL)
1064 {
1065 pp->search_list[cat].module[j] = mod;
1066 j++;
1067
1068 if (string_equal(tokens[i], "cache"))
1069 {
1070 pp->search_list[cat].flags |= SEARCH_FLAG_CACHE_ENABLED;
1071 }
1072 }
1073 }
1074 return 0;
1075 }