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 44typedef 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 52typedef struct 53{ 54 search_list_t search_list[CATEGORY_COUNT]; 55 si_mod_t *cache; 56} search_si_private_t; 57 58extern void si_cache_add_item(si_mod_t *si, si_mod_t *src, si_item_t *item); 59extern void si_cache_add_list(si_mod_t *si, si_mod_t *src, si_list_t *list); 60 61extern char **_fsi_tokenize(char *data, const char *sep, int trailing_empty, int *ntokens); 62extern char *_fsi_get_line(FILE *fp); 63 64static void si_module_config_parse_line(search_si_private_t *pp, char *line); 65static void si_module_config_modules_for_category(search_si_private_t *pp, int cat, int ntokens, const char * const *tokens); 66 67static si_mod_t * 68search_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 101search_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 124static si_mod_t * 125search_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 143static void 144search_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 168static si_item_t * 169search_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 197static si_item_t * 198search_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 226static si_item_t * 227search_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} 257static si_list_t * 258search_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 302static si_item_t * 303search_user_byname(si_mod_t *si, const char *name) 304{ 305 return search_item_byname(si, name, CATEGORY_USER, si_user_byname); 306} 307 308static si_item_t * 309search_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 314static si_item_t * 315search_user_byuuid(si_mod_t *si, uuid_t uuid) 316{ 317 return search_item_byuuid(si, uuid, CATEGORY_USER, si_user_byuuid); 318} 319 320static si_list_t * 321search_user_all(si_mod_t *si) 322{ 323 return search_list(si, CATEGORY_USER, si_user_all); 324} 325 326static si_item_t * 327search_group_byname(si_mod_t *si, const char *name) 328{ 329 return search_item_byname(si, name, CATEGORY_GROUP, si_group_byname); 330} 331 332static si_item_t * 333search_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 338static si_item_t * 339search_group_byuuid(si_mod_t *si, uuid_t uuid) 340{ 341 return search_item_byuuid(si, uuid, CATEGORY_GROUP, si_group_byuuid); 342} 343 344static si_list_t * 345search_group_all(si_mod_t *si) 346{ 347 return search_list(si, CATEGORY_GROUP, si_group_all); 348} 349 350static si_item_t * 351search_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 377static si_list_t * 378search_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 422static int 423search_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 446static si_item_t * 447search_alias_byname(si_mod_t *si, const char *name) 448{ 449 return search_item_byname(si, name, CATEGORY_ALIAS, si_alias_byname); 450} 451 452static si_list_t * 453search_alias_all(si_mod_t *si) 454{ 455 return search_list(si, CATEGORY_ALIAS, si_alias_all); 456} 457 458static si_item_t * 459search_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 500static si_item_t * 501search_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 542static si_list_t * 543search_host_all(si_mod_t *si) 544{ 545 return search_list(si, CATEGORY_HOST, si_host_all); 546} 547 548static si_item_t * 549search_network_byname(si_mod_t *si, const char *name) 550{ 551 return search_item_byname(si, name, CATEGORY_NETWORK, si_network_byname); 552} 553 554static si_item_t * 555search_network_byaddr(si_mod_t *si, uint32_t addr) 556{ 557 return search_item_bynumber(si, addr, CATEGORY_NETWORK, si_network_byaddr); 558} 559 560static si_list_t * 561search_network_all(si_mod_t *si) 562{ 563 return search_list(si, CATEGORY_NETWORK, si_network_all); 564} 565 566static si_item_t * 567search_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 596static si_item_t * 597search_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 625static si_list_t * 626search_service_all(si_mod_t *si) 627{ 628 return search_list(si, CATEGORY_SERVICE, si_service_all); 629} 630 631static si_item_t * 632search_protocol_byname(si_mod_t *si, const char *name) 633{ 634 return search_item_byname(si, name, CATEGORY_PROTOCOL, si_protocol_byname); 635} 636 637static si_item_t * 638search_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 643static si_list_t * 644search_protocol_all(si_mod_t *si) 645{ 646 return search_list(si, CATEGORY_PROTOCOL, si_protocol_all); 647} 648 649static si_item_t * 650search_rpc_byname(si_mod_t *si, const char *name) 651{ 652 return search_item_byname(si, name, CATEGORY_RPC, si_rpc_byname); 653} 654 655static si_item_t * 656search_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 684static si_list_t * 685search_rpc_all(si_mod_t *si) 686{ 687 return search_list(si, CATEGORY_RPC, si_rpc_all); 688} 689 690static si_item_t * 691search_fs_byspec(si_mod_t *si, const char *name) 692{ 693 return search_item_byname(si, name, CATEGORY_FS, si_fs_byspec); 694} 695 696static si_item_t * 697search_fs_byfile(si_mod_t *si, const char *name) 698{ 699 return search_item_byname(si, name, CATEGORY_FS, si_fs_byfile); 700} 701 702static si_list_t * 703search_fs_all(si_mod_t *si) 704{ 705 return search_list(si, CATEGORY_FS, si_fs_all); 706} 707 708static si_item_t * 709search_mac_byname(si_mod_t *si, const char *name) 710{ 711 return search_item_byname(si, name, CATEGORY_MAC, si_mac_byname); 712} 713 714static si_item_t * 715search_mac_bymac(si_mod_t *si, const char *mac) 716{ 717 return search_item_byname(si, mac, CATEGORY_MAC, si_mac_bymac); 718} 719 720static si_list_t * 721search_mac_all(si_mod_t *si) 722{ 723 return search_list(si, CATEGORY_MAC, si_mac_all); 724} 725 726static si_list_t * 727search_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 757static int 758search_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 781static si_list_t * 782search_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 814static si_item_t * 815search_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 847static int 848search_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 864si_mod_t * 865si_module_static_search(void) 866{ 867 static const struct si_mod_vtable_s search_vtable = 868 { 869 .sim_close = &search_close, 870 871 .sim_is_valid = &search_is_valid, 872 873 .sim_user_byname = &search_user_byname, 874 .sim_user_byuid = &search_user_byuid, 875 .sim_user_byuuid = &search_user_byuuid, 876 .sim_user_all = &search_user_all, 877 878 .sim_group_byname = &search_group_byname, 879 .sim_group_bygid = &search_group_bygid, 880 .sim_group_byuuid = &search_group_byuuid, 881 .sim_group_all = &search_group_all, 882 883 .sim_grouplist = &search_groupist, 884 885 .sim_netgroup_byname = &search_netgroup_byname, 886 .sim_in_netgroup = &search_in_netgroup, 887 888 .sim_alias_byname = &search_alias_byname, 889 .sim_alias_all = &search_alias_all, 890 891 .sim_host_byname = &search_host_byname, 892 .sim_host_byaddr = &search_host_byaddr, 893 .sim_host_all = &search_host_all, 894 895 .sim_network_byname = &search_network_byname, 896 .sim_network_byaddr = &search_network_byaddr, 897 .sim_network_all = &search_network_all, 898 899 .sim_service_byname = &search_service_byname, 900 .sim_service_byport = &search_service_byport, 901 .sim_service_all = &search_service_all, 902 903 .sim_protocol_byname = &search_protocol_byname, 904 .sim_protocol_bynumber = &search_protocol_bynumber, 905 .sim_protocol_all = &search_protocol_all, 906 907 .sim_rpc_byname = &search_rpc_byname, 908 .sim_rpc_bynumber = &search_rpc_bynumber, 909 .sim_rpc_all = &search_rpc_all, 910 911 .sim_fs_byspec = &search_fs_byspec, 912 .sim_fs_byfile = &search_fs_byfile, 913 .sim_fs_all = &search_fs_all, 914 915 .sim_mac_byname = &search_mac_byname, 916 .sim_mac_bymac = &search_mac_bymac, 917 .sim_mac_all = &search_mac_all, 918 919 .sim_addrinfo = &search_addrinfo, 920 .sim_wants_addrinfo = &search_wants_addrinfo, 921 .sim_nameinfo = &search_nameinfo, 922 923 .sim_srv_byname = &search_srv_byname, 924 }; 925 926 static si_mod_t si = 927 { 928 .vers = 1, 929 .refcount = 1, 930 .flags = SI_MOD_FLAG_STATIC, 931 932 .private = NULL, 933 .vtable = &search_vtable, 934 }; 935 936 static dispatch_once_t once; 937 938 dispatch_once(&once, ^{ 939 si.name = strdup("search"); 940 search_si_private_t *pp = calloc(1, sizeof(search_si_private_t)); 941 si.private = pp; 942 943 /* 944 * Default search order: 945 * 1) cache 946 * 2) DirectoryService/OpenDirectory (where available) 947 * 3) flat file 948 * 4) mDNSResponder 949 */ 950 951 const char * const modules[] = 952 { 953 "default", // CATEGORY_DEFAULT 954 "cache", 955#ifdef DS_AVAILABLE 956 "ds", 957#endif 958 "mdns", 959 "file", 960 }; 961 962 int count = sizeof(modules) / sizeof(char *); 963 si_module_config_modules_for_category(pp, CATEGORY_DEFAULT, count, modules); 964 pp->cache = pp->search_list[CATEGORY_DEFAULT].module[0]; 965 966 char *check = getenv("SYSINFO_CONF_ENABLE"); 967 if ((check != NULL) && (!strcmp(check, "1"))) 968 { 969 FILE *conf = fopen(_PATH_SI_CONF, "r"); 970 errno = 0; 971 if (conf != NULL) 972 { 973 forever 974 { 975 char *line = _fsi_get_line(conf); 976 if (line == NULL) break; 977 978 si_module_config_parse_line(pp, line); 979 free(line); 980 } 981 982 fclose(conf); 983 } 984 } 985 }); 986 987 return &si; 988} 989 990static void 991si_module_config_parse_line(search_si_private_t *pp, char *line) 992{ 993 if (line == NULL || line[0] == '#') { 994 return; 995 } 996 997 int ntokens = 0; 998 char **tokens = _fsi_tokenize(line, " : ", 0, &ntokens); 999 1000 int cat = CATEGORY_INVALID; 1001 1002 if (string_equal(tokens[0], "default")) cat = CATEGORY_DEFAULT; 1003 else if (string_equal(tokens[0], "user")) cat = CATEGORY_USER; 1004 else if (string_equal(tokens[0], "group")) cat = CATEGORY_GROUP; 1005 else if (string_equal(tokens[0], "grouplist")) cat = CATEGORY_GROUPLIST; 1006 else if (string_equal(tokens[0], "netgroup")) cat = CATEGORY_NETGROUP; 1007 else if (string_equal(tokens[0], "alias")) cat = CATEGORY_ALIAS; 1008 else if (string_equal(tokens[0], "host")) cat = CATEGORY_HOST_IPV4; 1009 else if (string_equal(tokens[0], "network")) cat = CATEGORY_NETWORK; 1010 else if (string_equal(tokens[0], "service")) cat = CATEGORY_SERVICE; 1011 else if (string_equal(tokens[0], "protocol")) cat = CATEGORY_PROTOCOL; 1012 else if (string_equal(tokens[0], "rpc")) cat = CATEGORY_RPC; 1013 else if (string_equal(tokens[0], "fs")) cat = CATEGORY_FS; 1014 else if (string_equal(tokens[0], "mac")) cat = CATEGORY_MAC; 1015 else if (string_equal(tokens[0], "addrinfo")) cat = CATEGORY_ADDRINFO; 1016 else if (string_equal(tokens[0], "nameinfo")) cat = CATEGORY_NAMEINFO; 1017 1018 if (cat != CATEGORY_INVALID) 1019 { 1020 si_module_config_modules_for_category(pp, cat, ntokens, (const char * const *)tokens); 1021 } 1022 1023 free(tokens); 1024} 1025 1026static void 1027si_module_config_modules_for_category(search_si_private_t *pp, int cat, int ntokens, const char * const *tokens) 1028{ 1029 int count = ntokens - 1; 1030 pp->search_list[cat].count = count; 1031 if (count == 0) 1032 { 1033 return; 1034 } 1035 1036 pp->search_list[cat].module = (si_mod_t **)calloc(pp->search_list[cat].count, sizeof(si_mod_t *)); 1037 pp->search_list[cat].module_flags = (uint32_t *)calloc(pp->search_list[cat].count, sizeof(uint32_t)); 1038 if ((pp->search_list[cat].module == NULL) || (pp->search_list[cat].module_flags == NULL)) 1039 { 1040 free(pp->search_list[cat].module); 1041 free(pp->search_list[cat].module_flags); 1042 return; 1043 } 1044 1045 int i, j; 1046 for (i = 1, j = 0; i < ntokens; i++) 1047 { 1048 si_mod_t *mod = si_module_with_name(tokens[i]); 1049 if (mod != NULL) 1050 { 1051 pp->search_list[cat].module[j] = mod; 1052 j++; 1053 1054 if (string_equal(tokens[i], "cache")) 1055 { 1056 pp->search_list[cat].flags |= SEARCH_FLAG_CACHE_ENABLED; 1057 } 1058 } 1059 } 1060} 1061