Libinfo-330.tar.gz
[apple/libinfo.git] / lookup.subproj / file_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 <si_module.h>
25 #include <paths.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <time.h>
30 #include <dirent.h>
31 #include <errno.h>
32 #include <arpa/inet.h>
33 #include <sys/param.h>
34 #include <sys/mount.h>
35 #include <sys/stat.h>
36 #include <ils.h>
37
38 /* These really should be in netdb.h & etc. */
39 #define _PATH_RPCS "/etc/rpc"
40 #define _PATH_ALIASES "/etc/aliases"
41 #define _PATH_ETHERS "/etc/ethers"
42
43 static si_item_t *rootfs = NULL;
44
45 static char *
46 _fsi_copy_string(char *s)
47 {
48 int len;
49 char *t;
50
51 if (s == NULL) return NULL;
52
53 len = strlen(s) + 1;
54 t = malloc(len);
55 bcopy(s, t, len);
56 return t;
57 }
58
59 static char **
60 _fsi_append_string(char *s, char **l)
61 {
62 int i, len;
63
64 if (s == NULL) return l;
65 if (l == NULL)
66 {
67 l = (char **)malloc(2 * sizeof(char *));
68 l[0] = s;
69 l[1] = NULL;
70 return l;
71 }
72
73 for (i = 0; l[i] != NULL; i++);
74 len = i + 1; /* count the NULL on the end of the list too! */
75
76 l = (char **)reallocf(l, (len + 1) * sizeof(char *));
77
78 l[len - 1] = s;
79 l[len] = NULL;
80 return l;
81 }
82
83 __private_extern__ char **
84 _fsi_tokenize(char *data, const char *sep, int trailing_empty, int *ntokens)
85 {
86 char **tokens;
87 int p, i, start, end, more, len, end_on_sep;
88 int scanning;
89
90 tokens = NULL;
91 end_on_sep = 0;
92
93 if (data == NULL) return NULL;
94
95 if (ntokens != NULL) *ntokens = 0;
96 if (sep == NULL)
97 {
98 tokens = _fsi_append_string(data, tokens);
99 if (ntokens != NULL) *ntokens = *ntokens + 1;
100 return tokens;
101 }
102
103 len = strlen(sep);
104 p = 0;
105
106 while (data[p] != '\0')
107 {
108 end_on_sep = 1;
109 /* skip leading white space */
110 while ((data[p] == ' ') || (data[p] == '\t') || (data[p] == '\n')) p++;
111
112 /* check for end of line */
113 if (data[p] == '\0') break;
114
115 /* scan for separator */
116 start = p;
117 end = p;
118 scanning = 1;
119 end_on_sep = 0;
120
121 while (scanning == 1)
122 {
123 if (data[p] == '\0') break;
124
125 for (i = 0; i < len; i++)
126 {
127 if (data[p] == sep[i])
128 {
129 scanning = 0;
130 end_on_sep = 1;
131 break;
132 }
133 }
134
135 /* end is last non-whitespace character */
136 if ((scanning == 1) && (data[p] != ' ') && (data[p] != '\t') && (data[p] != '\n')) end = p;
137
138 p += scanning;
139 }
140
141 /* see if there's data left after p */
142 more = 0;
143 if (data[p] != '\0') more = 1;
144
145 /* set the character following the token to nul */
146 if (start == p) data[p] = '\0';
147 else data[end + 1] = '\0';
148
149 tokens = _fsi_append_string(data + start, tokens);
150 if (ntokens != NULL) *ntokens = *ntokens + 1;
151 p += more;
152 }
153
154 if ((end_on_sep == 1) && (trailing_empty != 0))
155 {
156 /* if the scan ended on an empty token, add a null string */
157 tokens = _fsi_append_string(data + p, tokens);
158 if (ntokens != NULL) *ntokens = *ntokens + 1;
159 }
160
161 return tokens;
162 }
163
164 __private_extern__ char *
165 _fsi_get_line(FILE *fp)
166 {
167 char s[4096];
168 char *out;
169
170 s[0] = '\0';
171
172 fgets(s, sizeof(s), fp);
173 if ((s == NULL) || (s[0] == '\0')) return NULL;
174
175 if (s[0] != '#') s[strlen(s) - 1] = '\0';
176
177 out = _fsi_copy_string(s);
178 return out;
179 }
180
181 /* USERS */
182
183 static si_item_t *
184 _fsi_parse_user(si_mod_t *si, const char *name, uid_t uid, int which, char *data, int format, uint64_t sec, uint64_t nsec)
185 {
186 char **tokens;
187 int ntokens, match;
188 time_t change, exsire;
189 si_item_t *item;
190 uid_t xuid;
191
192 if (data == NULL) return NULL;
193
194 ntokens = 0;
195 tokens = _fsi_tokenize(data, ":", 1, &ntokens);
196 if (((format == 0) && (ntokens != 10)) || ((format == 1) && (ntokens != 7)))
197 {
198 free(tokens);
199 return NULL;
200 }
201
202 xuid = atoi(tokens[2]);
203 match = 0;
204
205 /* XXX MATCH GECOS? XXX*/
206 if (which == SEL_ALL) match = 1;
207 else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1;
208 else if ((which == SEL_NUMBER) && (uid == xuid)) match = 1;
209
210 if (match == 0)
211 {
212 free(tokens);
213 return NULL;
214 }
215
216 if (format == 0)
217 {
218 /* master.passwd: name[0] passwd[1] uid[2] gid[3] class[4] change[5] exsire[6] gecos[7] dir[8] shell[9] */
219 /* struct pwd: name[0] passwd[1] uid[2] gid[3] change[5] class[4] gecos[7] dir[8] shell[9] exsire[6] */
220 change = atoi(tokens[5]);
221 exsire = atoi(tokens[6]);
222 item = (si_item_t *)LI_ils_create("L4488ss44LssssL", (unsigned long)si, CATEGORY_USER, 1, sec, nsec, tokens[0], tokens[1], xuid, atoi(tokens[3]), change, tokens[4], tokens[7], tokens[8], tokens[9], exsire);
223 }
224 else
225 {
226 /* passwd: name[0] passwd[1] uid[2] gid[3] gecos[4] dir[5] shell[6] */
227 /* struct pwd: name[0] passwd[1] uid[2] gid[3] change[-] class[-] gecos[4] dir[5] shell[6] exsire[-] */
228 item = (si_item_t *)LI_ils_create("L4488ss44LssssL", (unsigned long)si, CATEGORY_USER, 1, sec, nsec, tokens[0], tokens[1], xuid, atoi(tokens[3]), 0, "", tokens[4], tokens[5], tokens[6], 0);
229 }
230
231 free(tokens);
232 return item;
233 }
234
235 static void *
236 _fsi_get_user(si_mod_t *si, const char *name, uid_t uid, int which)
237 {
238 char *line;
239 si_item_t *item;
240 int fmt;
241 FILE *f;
242 si_list_t *all;
243 struct stat sb;
244 uint64_t sec, nsec;
245
246 if ((which == SEL_NAME) && (name == NULL)) return NULL;
247
248 all = NULL;
249 f = NULL;
250 fmt = 0;
251 sec = 0;
252 nsec = 0;
253
254 if (geteuid() == 0)
255 {
256 f = fopen(_PATH_MASTERPASSWD, "r");
257 }
258 else
259 {
260 f = fopen(_PATH_PASSWD, "r");
261 fmt = 1;
262 }
263
264 if (f == NULL) return NULL;
265
266 memset(&sb, 0, sizeof(struct stat));
267 if (fstat(fileno(f), &sb) == 0)
268 {
269 sec = sb.st_mtimespec.tv_sec;
270 nsec = sb.st_mtimespec.tv_nsec;
271 }
272
273 forever
274 {
275 line = _fsi_get_line(f);
276 if (line == NULL) break;
277
278 if (line[0] == '#')
279 {
280 free(line);
281 line = NULL;
282 continue;
283 }
284
285 item = _fsi_parse_user(si, name, uid, which, line, fmt, sec, nsec);
286 free(line);
287 line = NULL;
288
289 if (item == NULL) continue;
290
291 if (which == SEL_ALL)
292 {
293 all = si_list_add(all, item);
294 si_item_release(item);
295 continue;
296 }
297
298 fclose(f);
299 return item;
300 }
301 fclose(f);
302 return all;
303 }
304
305 /* GROUPS */
306
307 static si_item_t *
308 _fsi_parse_group(si_mod_t *si, const char *name, gid_t gid, int which, char *data, uint64_t sec, uint64_t nsec)
309 {
310 char **tokens, **members;
311 int ntokens, match;
312 si_item_t *item;
313 gid_t xgid;
314
315 if (data == NULL) return NULL;
316
317 ntokens = 0;
318 tokens = _fsi_tokenize(data, ":", 1, &ntokens);
319 if (ntokens != 4)
320 {
321 free(tokens);
322 return NULL;
323 }
324
325 xgid = atoi(tokens[2]);
326 match = 0;
327
328 if (which == SEL_ALL) match = 1;
329 else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1;
330 else if ((which == SEL_NUMBER) && (gid == xgid)) match = 1;
331
332 if (match == 0)
333 {
334 free(tokens);
335 return NULL;
336 }
337
338 ntokens = 0;
339 members = _fsi_tokenize(tokens[3], ",", 1, &ntokens);
340
341 item = (si_item_t *)LI_ils_create("L4488ss4*", (unsigned long)si, CATEGORY_GROUP, 1, sec, nsec, tokens[0], tokens[1], xgid, members);
342
343 free(tokens);
344 free(members);
345
346 return item;
347 }
348
349 static void *
350 _fsi_get_group(si_mod_t *si, const char *name, gid_t gid, int which)
351 {
352 char *line;
353 si_item_t *item;
354 FILE *f;
355 si_list_t *all;
356 struct stat sb;
357 uint64_t sec, nsec;
358
359 if ((which == SEL_NAME) && (name == NULL)) return NULL;
360
361 all = NULL;
362 f = NULL;
363 sec = 0;
364 nsec = 0;
365
366 f = fopen(_PATH_GROUP, "r");
367 if (f == NULL) return NULL;
368
369 memset(&sb, 0, sizeof(struct stat));
370 if (fstat(fileno(f), &sb) == 0)
371 {
372 sec = sb.st_mtimespec.tv_sec;
373 nsec = sb.st_mtimespec.tv_nsec;
374 }
375
376 forever
377 {
378 line = _fsi_get_line(f);
379 if (line == NULL) break;
380
381 if (line[0] == '#')
382 {
383 free(line);
384 line = NULL;
385 continue;
386 }
387
388 item = _fsi_parse_group(si, name, gid, which, line, sec, nsec);
389 free(line);
390 line = NULL;
391
392 if (item == NULL) continue;
393
394 if (which == SEL_ALL)
395 {
396 all = si_list_add(all, item);
397 si_item_release(item);
398 continue;
399 }
400
401 fclose(f);
402 return item;
403 }
404
405 fclose(f);
406 return all;
407 }
408
409 static void *
410 _fsi_get_grouplist(si_mod_t *si, const char *user)
411 {
412 char **tokens, **members;
413 int ntokens, i, match, gidcount;
414 char *line;
415 si_item_t *item;
416 FILE *f;
417 struct stat sb;
418 uint64_t sec, nsec;
419 int32_t gid, basegid, *gidp;
420 char **gidlist;
421 struct passwd *pw;
422
423 if (user == NULL) return NULL;
424
425 gidlist = NULL;
426 gidcount = 0;
427 f = NULL;
428 sec = 0;
429 nsec = 0;
430 basegid = -1;
431
432 item = si->sim_user_byname(si, user);
433 if (item != NULL)
434 {
435 pw = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
436 basegid = pw->pw_gid;
437 free(item);
438 }
439
440 f = fopen(_PATH_GROUP, "r");
441 if (f == NULL) return NULL;
442
443 memset(&sb, 0, sizeof(struct stat));
444 if (fstat(fileno(f), &sb) == 0)
445 {
446 sec = sb.st_mtimespec.tv_sec;
447 nsec = sb.st_mtimespec.tv_nsec;
448 }
449
450 forever
451 {
452 line = _fsi_get_line(f);
453 if (line == NULL) break;
454
455 if (line[0] == '#')
456 {
457 free(line);
458 line = NULL;
459 continue;
460 }
461
462 ntokens = 0;
463 tokens = _fsi_tokenize(line, ":", 1, &ntokens);
464 if (ntokens != 4)
465 {
466 free(tokens);
467 continue;
468 }
469
470 ntokens = 0;
471 members = _fsi_tokenize(tokens[3], ",", 1, &ntokens);
472
473 match = 0;
474 gid = -2;
475
476 for (i = 0; (i < ntokens) && (match == 0); i++)
477 {
478 if (string_equal(user, members[i]))
479 {
480 gid = atoi(tokens[2]);
481 match = 1;
482 }
483 }
484
485 free(tokens);
486 free(members);
487 free(line);
488 line = NULL;
489
490 if (match == 1)
491 {
492 if (gidcount == 0) gidlist = (char **)calloc(1, sizeof(char *));
493 else gidlist = (char **)reallocf(gidlist, (gidcount + 1) * sizeof(char *));
494 gidp = (int32_t *)calloc(1, sizeof(int32_t));
495
496 if (gidlist == NULL)
497 {
498 gidcount = 0;
499 break;
500 }
501
502 if (gidp == NULL)
503 {
504 for (i = 0; i < gidcount; i++) free(gidlist[i]);
505 free(gidlist);
506 gidcount = 0;
507 break;
508 }
509
510 *gidp = gid;
511 gidlist[gidcount++] = (char *)gidp;
512 }
513 }
514
515 fclose(f);
516
517 if (gidcount == 0) return NULL;
518
519 gidlist = (char **)reallocf(gidlist, (gidcount + 1) * sizeof(int32_t *));
520 if (gidlist == NULL) return NULL;
521 gidlist[gidcount] = NULL;
522
523 item = (si_item_t *)LI_ils_create("L4488s44a", (unsigned long)si, CATEGORY_GROUPLIST, 1, sec, nsec, user, basegid, gidcount, gidlist);
524
525 for (i = 0; i <= gidcount; i++) free(gidlist[i]);
526 free(gidlist);
527
528 return item;
529 }
530
531 /* ALIASES */
532
533 static si_item_t *
534 _fsi_parse_alias(si_mod_t *si, const char *name, int which, char *data, uint64_t sec, uint64_t nsec)
535 {
536 char **tokens, **members;
537 int ntokens, match;
538 si_item_t *item;
539
540 if (data == NULL) return NULL;
541
542 ntokens = 0;
543 tokens = _fsi_tokenize(data, ":", 1, &ntokens);
544 if (ntokens < 2)
545 {
546 free(tokens);
547 return NULL;
548 }
549
550 match = 0;
551
552 if (which == SEL_ALL) match = 1;
553 else if (string_equal(name, tokens[0])) match = 1;
554
555 if (match == 0)
556 {
557 free(tokens);
558 return NULL;
559 }
560
561 ntokens = 0;
562 members = _fsi_tokenize(tokens[3], ",", 1, &ntokens);
563
564 item = (si_item_t *)LI_ils_create("L4488s4*4", (unsigned long)si, CATEGORY_ALIAS, 1, sec, nsec, tokens[0], ntokens, members, 1);
565
566 free(tokens);
567 free(members);
568
569 return item;
570 }
571
572 static void *
573 _fsi_get_alias(si_mod_t *si, const char *name, int which)
574 {
575 char *line;
576 si_item_t *item;
577 FILE *f;
578 si_list_t *all;
579 struct stat sb;
580 uint64_t sec, nsec;
581
582 if ((which == SEL_NAME) && (name == NULL)) return NULL;
583
584 all = NULL;
585 f = NULL;
586 sec = 0;
587 nsec = 0;
588
589 f = fopen(_PATH_ALIASES, "r");
590 if (f == NULL) return NULL;
591
592 memset(&sb, 0, sizeof(struct stat));
593 if (fstat(fileno(f), &sb) == 0)
594 {
595 sec = sb.st_mtimespec.tv_sec;
596 nsec = sb.st_mtimespec.tv_nsec;
597 }
598
599 forever
600 {
601 line = _fsi_get_line(f);
602 if (line == NULL) break;
603
604 if (line[0] == '#')
605 {
606 free(line);
607 line = NULL;
608 continue;
609 }
610
611 item = _fsi_parse_alias(si, name, which, line, sec, nsec);
612 free(line);
613 line = NULL;
614
615 if (item == NULL) continue;
616
617 if (which == SEL_ALL)
618 {
619 all = si_list_add(all, item);
620 si_item_release(item);
621 continue;
622 }
623
624 fclose(f);
625 return item;
626 }
627
628 fclose(f);
629 return all;
630 }
631
632 /* ETHERS */
633
634 static si_item_t *
635 _fsi_parse_ether(si_mod_t *si, const char *name, int which, char *data, uint64_t sec, uint64_t nsec)
636 {
637 char **tokens;
638 char *cmac;
639 int ntokens, match;
640 si_item_t *item;
641
642 if (data == NULL) return NULL;
643
644 ntokens = 0;
645 tokens = _fsi_tokenize(data, " \t", 1, &ntokens);
646 if (ntokens != 2)
647 {
648 free(tokens);
649 return NULL;
650 }
651
652 cmac = si_canonical_mac_address(tokens[1]);
653 if (cmac == NULL)
654 {
655 free(tokens);
656 return NULL;
657 }
658
659 match = 0;
660 if (which == SEL_ALL) match = 1;
661 else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1;
662 else if ((which == SEL_NUMBER) && (string_equal(name, cmac))) match = 1;
663
664 if (match == 0)
665 {
666 free(tokens);
667 free(cmac);
668 return NULL;
669 }
670
671 item = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, sec, nsec, tokens[0], cmac);
672
673 free(tokens);
674 free(cmac);
675
676 return item;
677 }
678
679 static void *
680 _fsi_get_ether(si_mod_t *si, const char *name, int which)
681 {
682 char *line, *cmac;
683 si_item_t *item;
684 FILE *f;
685 si_list_t *all;
686 struct stat sb;
687 uint64_t sec, nsec;
688
689 if ((which != SEL_ALL) && (name == NULL)) return NULL;
690
691 cmac = NULL;
692 if (which == SEL_NUMBER)
693 {
694 cmac = si_canonical_mac_address(name);
695 if (cmac == NULL) return NULL;
696 }
697
698 all = NULL;
699 f = NULL;
700 sec = 0;
701 nsec = 0;
702
703 f = fopen(_PATH_ETHERS, "r");
704 if (f == NULL) return NULL;
705
706 memset(&sb, 0, sizeof(struct stat));
707 if (fstat(fileno(f), &sb) == 0)
708 {
709 sec = sb.st_mtimespec.tv_sec;
710 nsec = sb.st_mtimespec.tv_nsec;
711 }
712
713 forever
714 {
715 line = _fsi_get_line(f);
716 if (line == NULL) break;
717
718 if (line[0] == '#')
719 {
720 free(line);
721 line = NULL;
722 continue;
723 }
724
725 item = NULL;
726 if (which == SEL_NUMBER) item = _fsi_parse_ether(si, cmac, which, line, sec, nsec);
727 else item = _fsi_parse_ether(si, name, which, line, sec, nsec);
728
729 free(line);
730 line = NULL;
731
732 if (item == NULL) continue;
733
734 if (which == SEL_ALL)
735 {
736 all = si_list_add(all, item);
737 si_item_release(item);
738 continue;
739 }
740
741 fclose(f);
742 return item;
743 }
744
745 fclose(f);
746 return all;
747 }
748
749 /* HOSTS */
750
751 static si_item_t *
752 _fsi_parse_host(si_mod_t *si, const char *name, const void *addr, int af, int which, char *data, uint64_t sec, uint64_t nsec)
753 {
754 char **tokens, **h_aliases, *null_alias;
755 int i, ntokens, match, xaf, h_length;
756 struct in_addr a4;
757 struct in6_addr a6;
758 si_item_t *item;
759 char *h_addr_list[2];
760 char h_addr_4[4], h_addr_6[16];
761
762 if (data == NULL) return NULL;
763
764 null_alias = NULL;
765
766 ntokens = 0;
767 tokens = _fsi_tokenize(data, " ", 0, &ntokens);
768 if (ntokens < 2)
769 {
770 free(tokens);
771 return NULL;
772 }
773
774 h_addr_list[1] = NULL;
775
776 xaf = AF_UNSPEC;
777 if (inet_pton(AF_INET, tokens[0], &a4) == 1)
778 {
779 xaf = AF_INET;
780 h_length = sizeof(struct in_addr);
781 memcpy(h_addr_4, &a4, 4);
782 h_addr_list[0] = h_addr_4;
783 }
784 else if (inet_pton(AF_INET6, tokens[0], &a6) == 1)
785 {
786 xaf = AF_INET6;
787 h_length = sizeof(struct in6_addr);
788 memcpy(h_addr_6, &a6, 16);
789 h_addr_list[0] = h_addr_6;
790 }
791
792 if (xaf == AF_UNSPEC)
793 {
794 free(tokens);
795 return NULL;
796 }
797
798 h_aliases = NULL;
799 if (ntokens > 2) h_aliases = &(tokens[2]);
800
801 match = 0;
802
803 if (which == SEL_ALL) match = 1;
804 else
805 {
806 if (af == xaf)
807 {
808 if (which == SEL_NAME)
809 {
810 if (string_equal(name, tokens[1])) match = 1;
811 else if (h_aliases != NULL)
812 {
813 for (i = 0; (h_aliases[i] != NULL) && (match == 0); i++)
814 if (string_equal(name, h_aliases[i])) match = 1;
815 }
816 }
817 else if (which == SEL_NUMBER)
818 {
819 if (memcmp(addr, h_addr_list[0], h_length) == 0) match = 1;
820 }
821 }
822 }
823
824 if (match == 0)
825 {
826 free(tokens);
827 return NULL;
828 }
829
830 item = NULL;
831
832 if (h_aliases == NULL) h_aliases = &null_alias;
833
834 if (af == AF_INET)
835 {
836 item = (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, sec, nsec, tokens[1], h_aliases, af, h_length, h_addr_list);
837 }
838 else
839 {
840 item = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, sec, nsec, tokens[1], h_aliases, af, h_length, h_addr_list);
841 }
842
843 free(tokens);
844
845 return item;
846 }
847
848 static void *
849 _fsi_get_host(si_mod_t *si, const char *name, const void *addr, int af, int which, uint32_t *err)
850 {
851 char *line;
852 si_item_t *item;
853 FILE *f;
854 si_list_t *all;
855 struct stat sb;
856 uint64_t sec, nsec;
857
858 sec = 0;
859 nsec = 0;
860
861 if ((which == SEL_NAME) && (name == NULL))
862 {
863 if (err != NULL) *err = NO_RECOVERY;
864 return NULL;
865 }
866
867 if ((which == SEL_NUMBER) && (addr == NULL))
868 {
869 if (err != NULL) *err = NO_RECOVERY;
870 return NULL;
871 }
872
873 f = fopen(_PATH_HOSTS, "r");
874 if (f == NULL)
875 {
876 if (err != NULL) *err = NO_RECOVERY;
877 return NULL;
878 }
879
880 memset(&sb, 0, sizeof(struct stat));
881 if (fstat(fileno(f), &sb) == 0)
882 {
883 sec = sb.st_mtimespec.tv_sec;
884 nsec = sb.st_mtimespec.tv_nsec;
885 }
886
887 all = NULL;
888
889 forever
890 {
891 line = _fsi_get_line(f);
892 if (line == NULL) break;
893
894 if (line[0] == '#')
895 {
896 free(line);
897 line = NULL;
898 continue;
899 }
900
901 item = _fsi_parse_host(si, name, addr, af, which, line, sec, nsec);
902 free(line);
903 line = NULL;
904
905 if (item == NULL) continue;
906
907 if (which == SEL_ALL)
908 {
909 all = si_list_add(all, item);
910 si_item_release(item);
911 continue;
912 }
913
914 fclose(f);
915 return item;
916 }
917
918 fclose(f);
919 return all;
920 }
921
922 /* SERVICE */
923
924 static si_item_t *
925 _fsi_parse_service(si_mod_t *si, const char *name, const char *proto, int port, int which, char *data, uint64_t sec, uint64_t nsec)
926 {
927 char **tokens, **s_aliases, *xproto;
928 int i, ntokens, match;
929 si_item_t *item;
930 int xport;
931
932 if (data == NULL) return NULL;
933
934 port = ntohs(port);
935
936 ntokens = 0;
937 tokens = _fsi_tokenize(data, " ", 0, &ntokens);
938 if (ntokens < 2)
939 {
940 free(tokens);
941 return NULL;
942 }
943
944 s_aliases = NULL;
945 if (ntokens > 2) s_aliases = &(tokens[2]);
946
947 xport = atoi(tokens[1]);
948
949 xproto = strchr(tokens[1], '/');
950
951 if (xproto == NULL)
952 {
953 free(tokens);
954 return NULL;
955 }
956
957 *xproto++ = '\0';
958 if ((proto != NULL) && (string_not_equal(proto, xproto)))
959 {
960 free(tokens);
961 return NULL;
962 }
963
964 match = 0;
965 if (which == SEL_ALL) match = 1;
966 else if (which == SEL_NAME)
967 {
968 if (string_equal(name, tokens[0])) match = 1;
969 else if (s_aliases != NULL)
970 {
971 for (i = 0; (s_aliases[i] != NULL) && (match == 0); i++)
972 if (string_equal(name, s_aliases[i])) match = 1;
973 }
974 }
975 else if ((which == SEL_NUMBER) && (port == xport)) match = 1;
976
977 if (match == 0)
978 {
979 free(tokens);
980 return NULL;
981 }
982
983 /* strange but correct */
984 xport = htons(xport);
985
986 item = (si_item_t *)LI_ils_create("L4488s*4s", (unsigned long)si, CATEGORY_SERVICE, 1, sec, nsec, tokens[0], s_aliases, xport, xproto);
987
988 free(tokens);
989
990 return item;
991 }
992
993 static void *
994 _fsi_get_service(si_mod_t *si, const char *name, const char *proto, int port, int which)
995 {
996 char *p, *line;
997 si_item_t *item;
998 FILE *f;
999 si_list_t *all;
1000 struct stat sb;
1001 uint64_t sec, nsec;
1002
1003 sec = 0;
1004 nsec = 0;
1005
1006 if ((which == SEL_NAME) && (name == NULL)) return NULL;
1007 if ((which == SEL_NUMBER) && (port == 0)) return NULL;
1008
1009 f = fopen(_PATH_SERVICES, "r");
1010 if (f == NULL) return NULL;
1011
1012 memset(&sb, 0, sizeof(struct stat));
1013 if (fstat(fileno(f), &sb) == 0)
1014 {
1015 sec = sb.st_mtimespec.tv_sec;
1016 nsec = sb.st_mtimespec.tv_nsec;
1017 }
1018
1019 all = NULL;
1020
1021 forever
1022 {
1023 line = _fsi_get_line(f);
1024 if (line == NULL) break;
1025
1026 if (line[0] == '#')
1027 {
1028 free(line);
1029 line = NULL;
1030 continue;
1031 }
1032
1033 p = strchr(line, '#');
1034 if (p != NULL) *p = '\0';
1035
1036 item = _fsi_parse_service(si, name, proto, port, which, line, sec, nsec);
1037 free(line);
1038 line = NULL;
1039
1040 if (item == NULL) continue;
1041
1042 if (which == SEL_ALL)
1043 {
1044 all = si_list_add(all, item);
1045 si_item_release(item);
1046 continue;
1047 }
1048
1049 fclose(f);
1050 return item;
1051 }
1052
1053 fclose(f);
1054 return all;
1055 }
1056
1057 /*
1058 * Generic name/number/aliases lookup
1059 * Works for protocols, networks, and rpcs
1060 */
1061
1062 static si_item_t *
1063 _fsi_parse_name_num_aliases(si_mod_t *si, const char *name, int num, int which, char *data, uint64_t sec, uint64_t nsec, int cat)
1064 {
1065 char **tokens, **aliases;
1066 int i, ntokens, match, xnum;
1067 si_item_t *item;
1068
1069 if (data == NULL) return NULL;
1070
1071 ntokens = 0;
1072 tokens = _fsi_tokenize(data, " ", 0, &ntokens);
1073 if (ntokens < 2)
1074 {
1075 free(tokens);
1076 return NULL;
1077 }
1078
1079 xnum = atoi(tokens[1]);
1080
1081 aliases = NULL;
1082 if (ntokens > 2) aliases = &(tokens[2]);
1083
1084 match = 0;
1085
1086 if (which == SEL_ALL) match = 1;
1087 else if (which == SEL_NAME)
1088 {
1089 if (string_equal(name, tokens[0])) match = 1;
1090 else if (aliases != NULL)
1091 {
1092 for (i = 0; (aliases[i] != NULL) && (match == 0); i++)
1093 if (string_equal(name, aliases[i])) match = 1;
1094 }
1095 }
1096 else if ((which == SEL_NUMBER) && (num == xnum)) match = 1;
1097
1098 if (match == 0)
1099 {
1100 free(tokens);
1101 return NULL;
1102 }
1103
1104 item = (si_item_t *)LI_ils_create("L4488s*4", (unsigned long)si, cat, 1, sec, nsec, tokens[0], aliases, xnum);
1105
1106 free(tokens);
1107
1108 return item;
1109 }
1110
1111 static void *
1112 _fsi_get_name_number_aliases(si_mod_t *si, const char *name, int num, int which, int cat, const char *path)
1113 {
1114 char *p, *line;
1115 si_item_t *item;
1116 FILE *f;
1117 si_list_t *all;
1118 struct stat sb;
1119 uint64_t sec, nsec;
1120
1121 sec = 0;
1122 nsec = 0;
1123
1124 f = fopen(path, "r");
1125 if (f == NULL) return NULL;
1126
1127 memset(&sb, 0, sizeof(struct stat));
1128 if (fstat(fileno(f), &sb) == 0)
1129 {
1130 sec = sb.st_mtimespec.tv_sec;
1131 nsec = sb.st_mtimespec.tv_nsec;
1132 }
1133
1134 all = NULL;
1135
1136 forever
1137 {
1138 line = _fsi_get_line(f);
1139 if (line == NULL) break;
1140
1141 if (line[0] == '#')
1142 {
1143 free(line);
1144 line = NULL;
1145 continue;
1146 }
1147
1148 p = strchr(line, '#');
1149 if (p != NULL) *p = '\0';
1150
1151 item = _fsi_parse_name_num_aliases(si, name, num, which, line, sec, nsec, cat);
1152 free(line);
1153 line = NULL;
1154
1155 if (item == NULL) continue;
1156
1157 if (which == SEL_ALL)
1158 {
1159 all = si_list_add(all, item);
1160 si_item_release(item);
1161 continue;
1162 }
1163
1164 fclose(f);
1165 return item;
1166 }
1167
1168 fclose(f);
1169 return all;
1170 }
1171
1172 /* MOUNT */
1173
1174 static si_item_t *
1175 _fsi_parse_fs(si_mod_t *si, const char *name, int which, char *data, uint64_t sec, uint64_t nsec)
1176 {
1177 char **tokens, *tmp, **opts, *fstype;
1178 int ntokens, match, i, freq, passno;
1179 si_item_t *item;
1180
1181 if (data == NULL) return NULL;
1182
1183 freq = 0;
1184 passno = 0;
1185 fstype = NULL;
1186
1187 ntokens = 0;
1188 tokens = _fsi_tokenize(data, " ", 0, &ntokens);
1189 if ((ntokens < 4) || (ntokens > 6))
1190 {
1191 free(tokens);
1192 return NULL;
1193 }
1194
1195 if (ntokens >= 5) freq = atoi(tokens[4]);
1196 if (ntokens == 6) passno = atoi(tokens[5]);
1197
1198 tmp = strdup(tokens[3]);
1199 if (tmp == NULL)
1200 {
1201 free(tokens);
1202 return NULL;
1203 }
1204
1205 ntokens = 0;
1206 opts = _fsi_tokenize(tmp, ",", 0, &ntokens);
1207
1208 if (opts == NULL)
1209 {
1210 free(tokens);
1211 free(tmp);
1212 return NULL;
1213 }
1214
1215 for (i = 0; i < ntokens; i++)
1216 {
1217 if ((string_equal(opts[i], "rw")) || (string_equal(opts[i], "ro")) || (string_equal(opts[i], "sw")) || (string_equal(opts[i], "xx")))
1218 {
1219 fstype = opts[i];
1220 break;
1221 }
1222 }
1223
1224 match = 0;
1225
1226 if (which == SEL_ALL) match = 1;
1227 else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1;
1228 else if ((which == SEL_NUMBER) && (string_equal(name, tokens[1]))) match = 1;
1229
1230 if (match == 0)
1231 {
1232 free(tokens);
1233 return NULL;
1234 }
1235
1236 item = (si_item_t *)LI_ils_create("L4488sssss44", (unsigned long)si, CATEGORY_FS, 1, sec, nsec, tokens[0], tokens[1], tokens[2], tokens[3], (fstype == NULL) ? "rw" : fstype, freq, passno);
1237
1238 free(tokens);
1239 free(opts);
1240 free(tmp);
1241
1242 return item;
1243 }
1244
1245 static char *
1246 _fsi_get_device_path(dev_t target_dev)
1247 {
1248 char *result;
1249 char dev[PATH_MAX];
1250 char *name;
1251 char namebuf[PATH_MAX];
1252
1253 result = NULL;
1254
1255 strlcpy(dev, _PATH_DEV, sizeof(dev));
1256
1257 /* The root device in fstab should always be a block special device */
1258 name = devname_r(target_dev, S_IFBLK, namebuf, sizeof(namebuf));
1259 if (name == NULL)
1260 {
1261 DIR *dirp;
1262 struct stat devst;
1263 struct dirent *ent, entbuf;
1264
1265 /* No _PATH_DEVDB. We have to search for it the slow way */
1266 dirp = opendir(_PATH_DEV);
1267 if (dirp == NULL) return NULL;
1268
1269 while (readdir_r(dirp, &entbuf, &ent) == 0 && ent != NULL)
1270 {
1271 /* Look for a block special device */
1272 if (ent->d_type == DT_BLK)
1273 {
1274 strlcat(dev, ent->d_name, sizeof(dev));
1275 if (stat(dev, &devst) == 0)
1276 {
1277 if (devst.st_rdev == target_dev) {
1278 result = strdup(dev);
1279 break;
1280 }
1281 }
1282 }
1283
1284 /* reset dev to _PATH_DEV and try again */
1285 dev[sizeof(_PATH_DEV) - 1] = '\0';
1286 }
1287
1288 if (dirp) closedir(dirp);
1289 }
1290 else
1291 {
1292 /* We found the _PATH_DEVDB entry */
1293 strlcat(dev, name, sizeof(dev));
1294 result = strdup(dev);
1295 }
1296
1297 return result;
1298 }
1299
1300 static si_item_t *
1301 _fsi_fs_root(si_mod_t *si)
1302 {
1303 struct stat rootstat;
1304 struct statfs rootfsinfo;
1305 char *root_spec;
1306 const char *root_path;
1307
1308 if (rootfs != NULL) return si_item_retain(rootfs);
1309
1310 root_path = "/";
1311
1312 if (stat(root_path, &rootstat) < 0) return NULL;
1313 if (statfs(root_path, &rootfsinfo) < 0) return NULL;
1314
1315 /* Check to make sure we're not looking at a synthetic root: */
1316 if (string_equal(rootfsinfo.f_fstypename, "synthfs"))
1317 {
1318 root_path = "/root";
1319 if (stat(root_path, &rootstat) < 0) return NULL;
1320 if (statfs(root_path, &rootfsinfo) < 0) return NULL;
1321 }
1322
1323 root_spec = _fsi_get_device_path(rootstat.st_dev);
1324
1325 rootfs = (si_item_t *)LI_ils_create("L4488sssss44", (unsigned long)si, CATEGORY_FS, 1, 0LL, 0LL, root_spec, root_path, rootfsinfo.f_fstypename, FSTAB_RW, FSTAB_RW, 0, 1);
1326 return rootfs;
1327 }
1328
1329
1330 static void *
1331 _fsi_get_fs(si_mod_t *si, const char *name, int which)
1332 {
1333 char *line;
1334 si_item_t *item;
1335 FILE *f;
1336 si_list_t *all;
1337 struct stat sb;
1338 uint64_t sec, nsec;
1339 int synthesize_root;
1340 struct fstab *rfs;
1341
1342 if ((which != SEL_ALL) && (name == NULL)) return NULL;
1343
1344 all = NULL;
1345 f = NULL;
1346 sec = 0;
1347 nsec = 0;
1348 #ifdef SYNTH_ROOTFS
1349 synthesize_root = 1;
1350 #else
1351 synthesize_root = 0;
1352 #endif
1353
1354 f = fopen(_PATH_FSTAB, "r");
1355 if ((f == NULL) || (synthesize_root == 1))
1356 {
1357 item = _fsi_fs_root(si);
1358
1359 rfs = NULL;
1360 if (item != NULL) rfs = (struct fstab *)((uintptr_t)item + sizeof(si_item_t));
1361
1362 switch (which)
1363 {
1364 case SEL_NAME:
1365 {
1366 if ((rfs != NULL) && (string_equal(name, rfs->fs_spec)))
1367 {
1368 if (f != NULL) fclose(f);
1369 return item;
1370 }
1371
1372 break;
1373 }
1374
1375 case SEL_NUMBER:
1376 {
1377 if ((rfs != NULL) && (string_equal(name, rfs->fs_file)))
1378 {
1379 if (f != NULL) fclose(f);
1380 return item;
1381 }
1382
1383 break;
1384 }
1385
1386 case SEL_ALL:
1387 {
1388 all = si_list_add(all, item);
1389 si_item_release(item);
1390 break;
1391 }
1392 }
1393 }
1394
1395 if (f == NULL) return all;
1396
1397 memset(&sb, 0, sizeof(struct stat));
1398 if (fstat(fileno(f), &sb) == 0)
1399 {
1400 sec = sb.st_mtimespec.tv_sec;
1401 nsec = sb.st_mtimespec.tv_nsec;
1402 }
1403
1404 forever
1405 {
1406 line = _fsi_get_line(f);
1407 if (line == NULL) break;
1408
1409 if (line[0] == '#')
1410 {
1411 free(line);
1412 line = NULL;
1413 continue;
1414 }
1415
1416 item = _fsi_parse_fs(si, name, which, line, sec, nsec);
1417 free(line);
1418 line = NULL;
1419
1420 if (item == NULL) continue;
1421
1422 if (which == SEL_ALL)
1423 {
1424 all = si_list_add(all, item);
1425 si_item_release(item);
1426 continue;
1427 }
1428
1429 fclose(f);
1430 return item;
1431 }
1432
1433 fclose(f);
1434 return all;
1435 }
1436
1437 __private_extern__ int
1438 file_is_valid(si_mod_t *si, si_item_t *item)
1439 {
1440 struct stat sb;
1441 uint64_t sec, nsec;
1442 const char *path;
1443 si_mod_t *src;
1444
1445 if (si == NULL) return 0;
1446 if (item == NULL) return 0;
1447 if (si->name == NULL) return 0;
1448 if (item->src == NULL) return 0;
1449
1450 src = (si_mod_t *)item->src;
1451
1452 if (src->name == NULL) return 0;
1453 if (string_not_equal(si->name, src->name)) return 0;
1454
1455 if (item == rootfs) return 1;
1456
1457 path = NULL;
1458 memset(&sb, 0, sizeof(struct stat));
1459 sec = item->validation_a;
1460 nsec = item->validation_b;
1461
1462 if (item->type == CATEGORY_USER)
1463 {
1464 if (geteuid() == 0) path = _PATH_MASTERPASSWD;
1465 else path = _PATH_PASSWD;
1466 }
1467 else if (item->type == CATEGORY_GROUP) path = _PATH_GROUP;
1468 else if (item->type == CATEGORY_HOST_IPV4) path = _PATH_HOSTS;
1469 else if (item->type == CATEGORY_HOST_IPV6) path = _PATH_HOSTS;
1470 else if (item->type == CATEGORY_NETWORK) path = _PATH_NETWORKS;
1471 else if (item->type == CATEGORY_SERVICE) path = _PATH_SERVICES;
1472 else if (item->type == CATEGORY_PROTOCOL) path = _PATH_PROTOCOLS;
1473 else if (item->type == CATEGORY_RPC) path = _PATH_RPCS;
1474 else if (item->type == CATEGORY_FS) path = _PATH_FSTAB;
1475
1476 if (path == NULL) return 0;
1477 if (stat(path, &sb) != 0) return 0;
1478 if (sec != sb.st_mtimespec.tv_sec) return 0;
1479 if (nsec != sb.st_mtimespec.tv_nsec) return 0;
1480
1481 return 1;
1482 }
1483
1484 __private_extern__ si_item_t *
1485 file_user_byname(si_mod_t *si, const char *name)
1486 {
1487 return _fsi_get_user(si, name, 0, SEL_NAME);
1488 }
1489
1490 __private_extern__ si_item_t *
1491 file_user_byuid(si_mod_t *si, uid_t uid)
1492 {
1493 return _fsi_get_user(si, NULL, uid, SEL_NUMBER);
1494 }
1495
1496 __private_extern__ si_list_t *
1497 file_user_all(si_mod_t *si)
1498 {
1499 return _fsi_get_user(si, NULL, 0, SEL_ALL);
1500 }
1501
1502 __private_extern__ si_item_t *
1503 file_group_byname(si_mod_t *si, const char *name)
1504 {
1505 return _fsi_get_group(si, name, 0, SEL_NAME);
1506 }
1507
1508 __private_extern__ si_item_t *
1509 file_group_bygid(si_mod_t *si, gid_t gid)
1510 {
1511 return _fsi_get_group(si, NULL, gid, SEL_NUMBER);
1512 }
1513
1514 __private_extern__ si_list_t *
1515 file_group_all(si_mod_t *si)
1516 {
1517 return _fsi_get_group(si, NULL, 0, SEL_ALL);
1518 }
1519
1520 __private_extern__ si_item_t *
1521 file_grouplist(si_mod_t *si, const char *name)
1522 {
1523 return _fsi_get_grouplist(si, name);
1524 }
1525
1526 __private_extern__ si_item_t *
1527 file_host_byname(si_mod_t *si, const char *name, int af, const char *ignored, uint32_t *err)
1528 {
1529 si_item_t *item;
1530
1531 if (err != NULL) *err = SI_STATUS_NO_ERROR;
1532
1533 item = _fsi_get_host(si, name, NULL, af, SEL_NAME, err);
1534 if ((item == NULL) && (err != NULL) && (*err == 0)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
1535
1536 return item;
1537 }
1538
1539 __private_extern__ si_item_t *
1540 file_host_byaddr(si_mod_t *si, const void *addr, int af, const char *ignored, uint32_t *err)
1541 {
1542 si_item_t *item;
1543
1544 if (err != NULL) *err = SI_STATUS_NO_ERROR;
1545
1546 item = _fsi_get_host(si, NULL, addr, af, SEL_NUMBER, err);
1547 if ((item == NULL) && (err != NULL) && (*err == 0)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
1548
1549 return item;
1550 }
1551
1552 __private_extern__ si_list_t *
1553 file_host_all(si_mod_t *si)
1554 {
1555 return _fsi_get_host(si, NULL, NULL, 0, SEL_ALL, NULL);
1556 }
1557
1558 __private_extern__ si_item_t *
1559 file_network_byname(si_mod_t *si, const char *name)
1560 {
1561 if (name == NULL) return NULL;
1562 return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_NETWORK, _PATH_NETWORKS);
1563 }
1564
1565 __private_extern__ si_item_t *
1566 file_network_byaddr(si_mod_t *si, uint32_t addr)
1567 {
1568 return _fsi_get_name_number_aliases(si, NULL, (int)addr, SEL_NUMBER, CATEGORY_NETWORK, _PATH_NETWORKS);
1569 }
1570
1571 __private_extern__ si_list_t *
1572 file_network_all(si_mod_t *si)
1573 {
1574 return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_NETWORK, _PATH_NETWORKS);
1575 }
1576
1577 __private_extern__ si_item_t *
1578 file_service_byname(si_mod_t *si, const char *name, const char *proto)
1579 {
1580 return _fsi_get_service(si, name, proto, 0, SEL_NAME);
1581 }
1582
1583 __private_extern__ si_item_t *
1584 file_service_byport(si_mod_t *si, int port, const char *proto)
1585 {
1586 return _fsi_get_service(si, NULL, proto, port, SEL_NUMBER);
1587 }
1588
1589 __private_extern__ si_list_t *
1590 file_service_all(si_mod_t *si)
1591 {
1592 return _fsi_get_service(si, NULL, NULL, 0, SEL_ALL);
1593 }
1594
1595 __private_extern__ si_item_t *
1596 file_protocol_byname(si_mod_t *si, const char *name)
1597 {
1598 if (name == NULL) return NULL;
1599 return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_PROTOCOL, _PATH_PROTOCOLS);
1600 }
1601
1602 __private_extern__ si_item_t *
1603 file_protocol_bynumber(si_mod_t *si, int number)
1604 {
1605 return _fsi_get_name_number_aliases(si, NULL, number, SEL_NUMBER, CATEGORY_PROTOCOL, _PATH_PROTOCOLS);
1606 }
1607
1608 __private_extern__ si_list_t *
1609 file_protocol_all(si_mod_t *si)
1610 {
1611 return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_PROTOCOL, _PATH_PROTOCOLS);
1612 }
1613
1614 __private_extern__ si_item_t *
1615 file_rpc_byname(si_mod_t *si, const char *name)
1616 {
1617 if (name == NULL) return NULL;
1618 return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_RPC, _PATH_RPCS);
1619 }
1620
1621 __private_extern__ si_item_t *
1622 file_rpc_bynumber(si_mod_t *si, int number)
1623 {
1624 return _fsi_get_name_number_aliases(si, NULL, number, SEL_NUMBER, CATEGORY_RPC, _PATH_RPCS);
1625 }
1626
1627 __private_extern__ si_list_t *
1628 file_rpc_all(si_mod_t *si)
1629 {
1630 return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_RPC, _PATH_RPCS);
1631 }
1632
1633 __private_extern__ si_item_t *
1634 file_fs_byspec(si_mod_t *si, const char *spec)
1635 {
1636 return _fsi_get_fs(si, spec, SEL_NAME);
1637 }
1638
1639 __private_extern__ si_item_t *
1640 file_fs_byfile(si_mod_t *si, const char *file)
1641 {
1642 return _fsi_get_fs(si, file, SEL_NUMBER);
1643 }
1644
1645 __private_extern__ si_list_t *
1646 file_fs_all(si_mod_t *si)
1647 {
1648 return _fsi_get_fs(si, NULL, SEL_ALL);
1649 }
1650
1651 __private_extern__ si_item_t *
1652 file_alias_byname(si_mod_t *si, const char *name)
1653 {
1654 return _fsi_get_alias(si, name, SEL_NAME);
1655 }
1656
1657 __private_extern__ si_list_t *
1658 file_alias_all(si_mod_t *si)
1659 {
1660 return _fsi_get_alias(si, NULL, SEL_ALL);
1661 }
1662
1663 __private_extern__ si_item_t *
1664 file_mac_byname(si_mod_t *si, const char *name)
1665 {
1666 return _fsi_get_ether(si, name, SEL_NAME);
1667 }
1668
1669 __private_extern__ si_item_t *
1670 file_mac_bymac(si_mod_t *si, const char *mac)
1671 {
1672 return _fsi_get_ether(si, mac, SEL_NUMBER);
1673 }
1674
1675 __private_extern__ si_list_t *
1676 file_mac_all(si_mod_t *si)
1677 {
1678 return _fsi_get_ether(si, NULL, SEL_ALL);
1679 }
1680
1681 __private_extern__ si_mod_t *
1682 si_module_static_file()
1683 {
1684 si_mod_t *out;
1685 char *outname;
1686
1687 out = (si_mod_t *)calloc(1, sizeof(si_mod_t));
1688 outname = strdup("file");
1689
1690 if ((out == NULL) || (outname == NULL))
1691 {
1692 if (out != NULL) free(out);
1693 if (outname != NULL) free(outname);
1694
1695 errno = ENOMEM;
1696 return NULL;
1697 }
1698
1699 out->name = outname;
1700 out->vers = 1;
1701 out->refcount = 1;
1702
1703 out->sim_is_valid = file_is_valid;
1704
1705 out->sim_user_byname = file_user_byname;
1706 out->sim_user_byuid = file_user_byuid;
1707 out->sim_user_all = file_user_all;
1708
1709 out->sim_group_byname = file_group_byname;
1710 out->sim_group_bygid = file_group_bygid;
1711 out->sim_group_all = file_group_all;
1712
1713 out->sim_grouplist = file_grouplist;
1714
1715 /* NETGROUP SUPPORT NOT IMPLEMENTED */
1716 out->sim_netgroup_byname = NULL;
1717 out->sim_in_netgroup = NULL;
1718
1719 out->sim_alias_byname = file_alias_byname;
1720 out->sim_alias_all = file_alias_all;
1721
1722 out->sim_host_byname = file_host_byname;
1723 out->sim_host_byaddr = file_host_byaddr;
1724 out->sim_host_all = file_host_all;
1725
1726 out->sim_network_byname = file_network_byname;
1727 out->sim_network_byaddr = file_network_byaddr;
1728 out->sim_network_all = file_network_all;
1729
1730 out->sim_service_byname = file_service_byname;
1731 out->sim_service_byport = file_service_byport;
1732 out->sim_service_all = file_service_all;
1733
1734 out->sim_protocol_byname = file_protocol_byname;
1735 out->sim_protocol_bynumber = file_protocol_bynumber;
1736 out->sim_protocol_all = file_protocol_all;
1737
1738 out->sim_rpc_byname = file_rpc_byname;
1739 out->sim_rpc_bynumber = file_rpc_bynumber;
1740 out->sim_rpc_all = file_rpc_all;
1741
1742 out->sim_fs_byspec = file_fs_byspec;
1743 out->sim_fs_byfile = file_fs_byfile;
1744 out->sim_fs_all = file_fs_all;
1745
1746 out->sim_mac_byname = file_mac_byname;
1747 out->sim_mac_bymac = file_mac_bymac;
1748 out->sim_mac_all = file_mac_all;
1749
1750 /* no addrinfo support */
1751 out->sim_wants_addrinfo = NULL;
1752 out->sim_addrinfo = NULL;
1753
1754 /* no nameinfo support */
1755 out->sim_nameinfo = NULL;
1756
1757 return out;
1758 }