]>
Commit | Line | Data |
---|---|---|
d49d4c81 | 1 | /* |
9d0fc09c | 2 | * Copyright (c) 2008-2015 Apple Inc. All rights reserved. |
d49d4c81 A |
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> | |
e44d8d47 | 32 | #include <notify.h> |
d31dd049 | 33 | #include <pthread.h> |
d49d4c81 A |
34 | #include <arpa/inet.h> |
35 | #include <sys/param.h> | |
36 | #include <sys/mount.h> | |
37 | #include <sys/stat.h> | |
38 | #include <ils.h> | |
e44d8d47 | 39 | #include <dispatch/dispatch.h> |
993b5481 | 40 | #include <TargetConditionals.h> |
8df84744 A |
41 | #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) |
42 | #include <sys/sysctl.h> | |
43 | #include <apfs/apfs_sysctl.h> | |
44 | #endif | |
e44d8d47 A |
45 | |
46 | /* notify SPI */ | |
47 | uint32_t notify_peek(int token, uint32_t *val); | |
48 | ||
49 | extern uint32_t gL1CacheEnabled; | |
d49d4c81 A |
50 | |
51 | /* These really should be in netdb.h & etc. */ | |
52 | #define _PATH_RPCS "/etc/rpc" | |
53 | #define _PATH_ALIASES "/etc/aliases" | |
54 | #define _PATH_ETHERS "/etc/ethers" | |
e44d8d47 | 55 | #define _PATH_NETGROUP "/etc/netgroup" |
d49d4c81 | 56 | |
e44d8d47 | 57 | static dispatch_once_t rootfs_once; |
d49d4c81 A |
58 | static si_item_t *rootfs = NULL; |
59 | ||
e44d8d47 A |
60 | #define CHUNK 256 |
61 | #define FNG_MEM 0x00000010 | |
62 | #define FNG_GRP 0x00000020 | |
63 | ||
64 | #define forever for(;;) | |
65 | ||
66 | #define VALIDATION_PASSWD 0 | |
67 | #define VALIDATION_MASTER_PASSWD 1 | |
68 | #define VALIDATION_GROUP 2 | |
69 | #define VALIDATION_NETGROUP 3 | |
70 | #define VALIDATION_ALIASES 4 | |
71 | #define VALIDATION_HOSTS 5 | |
72 | #define VALIDATION_NETWORKS 6 | |
73 | #define VALIDATION_SERVICES 7 | |
74 | #define VALIDATION_PROTOCOLS 8 | |
75 | #define VALIDATION_RPC 9 | |
76 | #define VALIDATION_FSTAB 10 | |
77 | #define VALIDATION_ETHERS 11 | |
78 | #define VALIDATION_COUNT 12 | |
79 | ||
80 | #define VALIDATION_MASK_PASSWD 0x00000001 | |
81 | #define VALIDATION_MASK_MASTER_PASSWD 0x00000002 | |
82 | #define VALIDATION_MASK_MASK_GROUP 0x00000004 | |
83 | #define VALIDATION_MASK_NETGROUP 0x00000008 | |
84 | #define VALIDATION_MASK_ALIASES 0x00000010 | |
85 | #define VALIDATION_MASK_HOSTS 0x00000020 | |
86 | #define VALIDATION_MASK_NETWORKS 0x00000040 | |
87 | #define VALIDATION_MASK_SERVICES 0x00000080 | |
88 | #define VALIDATION_MASK_PROTOCOLS 0x00000100 | |
89 | #define VALIDATION_MASK_RPC 0x00000200 | |
90 | #define VALIDATION_MASK_FSTAB 0x00000400 | |
91 | #define VALIDATION_MASK_ETHERS 0x00000800 | |
92 | ||
93 | typedef struct file_netgroup_member_s | |
94 | { | |
95 | uint32_t flags; | |
96 | char *host; | |
97 | char *user; | |
98 | char *domain; | |
99 | struct file_netgroup_member_s *next; | |
100 | } file_netgroup_member_t; | |
101 | ||
102 | typedef struct file_netgroup_s | |
103 | { | |
104 | char *name; | |
105 | uint32_t flags; | |
106 | file_netgroup_member_t *members; | |
107 | struct file_netgroup_s *next; | |
108 | } file_netgroup_t; | |
109 | ||
110 | typedef struct | |
111 | { | |
112 | uint32_t validation_notify_mask; | |
113 | int notify_token[VALIDATION_COUNT]; | |
114 | file_netgroup_t *file_netgroup_cache; | |
115 | uint64_t netgroup_validation_a; | |
116 | uint64_t netgroup_validation_b; | |
117 | } file_si_private_t; | |
118 | ||
119 | static pthread_mutex_t file_mutex = PTHREAD_MUTEX_INITIALIZER; | |
120 | ||
d49d4c81 A |
121 | static char * |
122 | _fsi_copy_string(char *s) | |
123 | { | |
124 | int len; | |
125 | char *t; | |
126 | ||
127 | if (s == NULL) return NULL; | |
128 | ||
129 | len = strlen(s) + 1; | |
130 | t = malloc(len); | |
0eb52ff2 A |
131 | if (t == NULL) return NULL; |
132 | ||
d49d4c81 A |
133 | bcopy(s, t, len); |
134 | return t; | |
135 | } | |
136 | ||
137 | static char ** | |
138 | _fsi_append_string(char *s, char **l) | |
139 | { | |
140 | int i, len; | |
141 | ||
142 | if (s == NULL) return l; | |
d31dd049 A |
143 | if (l != NULL) { |
144 | for (i = 0; l[i] != NULL; i++); | |
145 | len = i; | |
146 | } else { | |
147 | len = 0; | |
d49d4c81 A |
148 | } |
149 | ||
d31dd049 A |
150 | l = (char **) reallocf(l, (len + 2) * sizeof(char *)); |
151 | if (l == NULL) return NULL; | |
d49d4c81 | 152 | |
d31dd049 A |
153 | l[len] = s; |
154 | l[len + 1] = NULL; | |
d49d4c81 A |
155 | return l; |
156 | } | |
157 | ||
e44d8d47 | 158 | char ** |
d49d4c81 A |
159 | _fsi_tokenize(char *data, const char *sep, int trailing_empty, int *ntokens) |
160 | { | |
161 | char **tokens; | |
162 | int p, i, start, end, more, len, end_on_sep; | |
163 | int scanning; | |
164 | ||
165 | tokens = NULL; | |
166 | end_on_sep = 0; | |
167 | ||
168 | if (data == NULL) return NULL; | |
169 | ||
170 | if (ntokens != NULL) *ntokens = 0; | |
171 | if (sep == NULL) | |
172 | { | |
173 | tokens = _fsi_append_string(data, tokens); | |
174 | if (ntokens != NULL) *ntokens = *ntokens + 1; | |
175 | return tokens; | |
176 | } | |
177 | ||
178 | len = strlen(sep); | |
179 | p = 0; | |
180 | ||
181 | while (data[p] != '\0') | |
182 | { | |
183 | end_on_sep = 1; | |
184 | /* skip leading white space */ | |
185 | while ((data[p] == ' ') || (data[p] == '\t') || (data[p] == '\n')) p++; | |
186 | ||
187 | /* check for end of line */ | |
188 | if (data[p] == '\0') break; | |
189 | ||
190 | /* scan for separator */ | |
191 | start = p; | |
192 | end = p; | |
193 | scanning = 1; | |
194 | end_on_sep = 0; | |
195 | ||
196 | while (scanning == 1) | |
197 | { | |
198 | if (data[p] == '\0') break; | |
199 | ||
200 | for (i = 0; i < len; i++) | |
201 | { | |
202 | if (data[p] == sep[i]) | |
203 | { | |
204 | scanning = 0; | |
205 | end_on_sep = 1; | |
206 | break; | |
207 | } | |
208 | } | |
209 | ||
210 | /* end is last non-whitespace character */ | |
211 | if ((scanning == 1) && (data[p] != ' ') && (data[p] != '\t') && (data[p] != '\n')) end = p; | |
212 | ||
213 | p += scanning; | |
214 | } | |
215 | ||
216 | /* see if there's data left after p */ | |
217 | more = 0; | |
218 | if (data[p] != '\0') more = 1; | |
219 | ||
220 | /* set the character following the token to nul */ | |
221 | if (start == p) data[p] = '\0'; | |
222 | else data[end + 1] = '\0'; | |
223 | ||
224 | tokens = _fsi_append_string(data + start, tokens); | |
225 | if (ntokens != NULL) *ntokens = *ntokens + 1; | |
226 | p += more; | |
227 | } | |
228 | ||
229 | if ((end_on_sep == 1) && (trailing_empty != 0)) | |
230 | { | |
231 | /* if the scan ended on an empty token, add a null string */ | |
232 | tokens = _fsi_append_string(data + p, tokens); | |
233 | if (ntokens != NULL) *ntokens = *ntokens + 1; | |
234 | } | |
235 | ||
236 | return tokens; | |
237 | } | |
238 | ||
e44d8d47 | 239 | char * |
d49d4c81 A |
240 | _fsi_get_line(FILE *fp) |
241 | { | |
242 | char s[4096]; | |
9d0fc09c | 243 | char *x, *out; |
d49d4c81 A |
244 | |
245 | s[0] = '\0'; | |
246 | ||
9d0fc09c A |
247 | x = fgets(s, sizeof(s), fp); |
248 | if ((x == NULL) || (s[0] == '\0')) return NULL; | |
d49d4c81 A |
249 | |
250 | if (s[0] != '#') s[strlen(s) - 1] = '\0'; | |
251 | ||
252 | out = _fsi_copy_string(s); | |
253 | return out; | |
254 | } | |
255 | ||
e44d8d47 A |
256 | static const char * |
257 | _fsi_validation_path(int vtype) | |
258 | { | |
259 | if (vtype == VALIDATION_PASSWD) return _PATH_PASSWD; | |
260 | else if (vtype == VALIDATION_MASTER_PASSWD) return _PATH_MASTERPASSWD; | |
261 | else if (vtype == VALIDATION_GROUP) return _PATH_GROUP; | |
262 | else if (vtype == VALIDATION_NETGROUP) return _PATH_NETGROUP; | |
263 | else if (vtype == VALIDATION_ALIASES) return _PATH_ALIASES; | |
264 | else if (vtype == VALIDATION_HOSTS) return _PATH_HOSTS; | |
265 | else if (vtype == VALIDATION_NETWORKS) return _PATH_NETWORKS; | |
266 | else if (vtype == VALIDATION_SERVICES) return _PATH_SERVICES; | |
267 | else if (vtype == VALIDATION_PROTOCOLS) return _PATH_PROTOCOLS; | |
268 | else if (vtype == VALIDATION_RPC) return _PATH_RPCS; | |
269 | else if (vtype == VALIDATION_FSTAB) return _PATH_FSTAB; | |
270 | else if (vtype == VALIDATION_ETHERS) return _PATH_ETHERS; | |
271 | ||
272 | return NULL; | |
273 | } | |
274 | ||
275 | static void | |
276 | _fsi_get_validation(si_mod_t *si, int vtype, const char *path, FILE *f, uint64_t *a, uint64_t *b) | |
277 | { | |
278 | struct stat sb; | |
279 | file_si_private_t *pp; | |
280 | uint32_t peek, bit; | |
281 | int status; | |
282 | ||
283 | if (a != NULL) *a = 0; | |
d31dd049 | 284 | if (b != NULL) *b = 0; |
e44d8d47 A |
285 | |
286 | if (si == NULL) return; | |
287 | if (path == NULL) return; | |
288 | if (gL1CacheEnabled == 0) return; | |
289 | ||
290 | pp = (file_si_private_t *)si->private; | |
291 | if (pp == NULL) return; | |
292 | ||
293 | if (vtype >= VALIDATION_COUNT) return; | |
294 | ||
295 | bit = 1 << vtype; | |
296 | if (bit & pp->validation_notify_mask) | |
297 | { | |
298 | /* use notify validation for this type */ | |
299 | if (pp->notify_token[vtype] < 0) | |
300 | { | |
301 | char *str = NULL; | |
302 | asprintf(&str, "com.apple.system.info:%s", path); | |
303 | if (str == NULL) return; | |
304 | ||
305 | status = notify_register_check(str, &(pp->notify_token[vtype])); | |
306 | free(str); | |
307 | } | |
308 | ||
309 | if (a != NULL) | |
310 | { | |
311 | status = notify_peek(pp->notify_token[vtype], &peek); | |
312 | if (status == NOTIFY_STATUS_OK) *a = ntohl(peek); | |
313 | } | |
314 | ||
315 | if (b != NULL) *b = vtype; | |
316 | } | |
317 | else | |
318 | { | |
319 | /* use stat() and last mod time for this type */ | |
320 | memset(&sb, 0, sizeof(struct stat)); | |
321 | if (f != NULL) | |
322 | { | |
323 | if (fstat(fileno(f), &sb) == 0) | |
324 | { | |
325 | if (a != NULL) *a = sb.st_mtimespec.tv_sec; | |
326 | if (b != NULL) *b = sb.st_mtimespec.tv_nsec; | |
327 | } | |
328 | } | |
329 | else | |
330 | { | |
331 | path = _fsi_validation_path(vtype); | |
332 | if (path != NULL) | |
333 | { | |
334 | memset(&sb, 0, sizeof(struct stat)); | |
335 | if (stat(path, &sb) == 0) | |
336 | { | |
337 | if (a != NULL) *a = sb.st_mtimespec.tv_sec; | |
338 | if (b != NULL) *b = sb.st_mtimespec.tv_nsec; | |
339 | } | |
340 | } | |
341 | } | |
342 | } | |
343 | } | |
344 | ||
345 | static int | |
346 | _fsi_validate(si_mod_t *si, int cat, uint64_t va, uint64_t vb) | |
347 | { | |
ff4fe4c3 | 348 | #if !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) |
e44d8d47 A |
349 | struct stat sb; |
350 | const char *path; | |
351 | uint32_t item_val, curr_val, vtype; | |
352 | file_si_private_t *pp; | |
353 | int status; | |
53dd3e4a | 354 | #endif |
e44d8d47 A |
355 | |
356 | if (si == NULL) return 0; | |
357 | ||
ff4fe4c3 | 358 | #if !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) |
993b5481 | 359 | /* /etc is on a read-only filesystem, so no validation is required */ |
993b5481 | 360 | |
e44d8d47 A |
361 | pp = (file_si_private_t *)si->private; |
362 | if (pp == NULL) return 0; | |
363 | ||
364 | vtype = UINT32_MAX; | |
365 | switch (cat) | |
366 | { | |
367 | case CATEGORY_USER: | |
368 | { | |
369 | if (geteuid() == 0) vtype = VALIDATION_MASTER_PASSWD; | |
370 | else vtype = VALIDATION_PASSWD; | |
371 | break; | |
372 | } | |
373 | case CATEGORY_GROUP: | |
374 | { | |
375 | vtype = VALIDATION_GROUP; | |
376 | break; | |
377 | } | |
378 | case CATEGORY_GROUPLIST: | |
379 | { | |
380 | vtype = VALIDATION_GROUP; | |
381 | break; | |
382 | } | |
383 | case CATEGORY_NETGROUP: | |
384 | { | |
385 | vtype = VALIDATION_NETGROUP; | |
386 | break; | |
387 | } | |
388 | case CATEGORY_ALIAS: | |
389 | { | |
390 | vtype = VALIDATION_ALIASES; | |
391 | break; | |
392 | } | |
393 | case CATEGORY_HOST_IPV4: | |
394 | { | |
395 | vtype = VALIDATION_HOSTS; | |
396 | break; | |
397 | } | |
398 | case CATEGORY_HOST_IPV6: | |
399 | { | |
400 | vtype = VALIDATION_HOSTS; | |
401 | break; | |
402 | } | |
403 | case CATEGORY_NETWORK: | |
404 | { | |
405 | vtype = VALIDATION_NETWORKS; | |
406 | break; | |
407 | } | |
408 | case CATEGORY_SERVICE: | |
409 | { | |
410 | vtype = VALIDATION_SERVICES; | |
411 | break; | |
412 | } | |
413 | case CATEGORY_PROTOCOL: | |
414 | { | |
415 | vtype = VALIDATION_PROTOCOLS; | |
416 | break; | |
417 | } | |
418 | case CATEGORY_RPC: | |
419 | { | |
420 | vtype = VALIDATION_RPC; | |
421 | break; | |
422 | } | |
423 | case CATEGORY_FS: | |
424 | { | |
425 | vtype = VALIDATION_FSTAB; | |
426 | break; | |
427 | } | |
428 | case CATEGORY_MAC: | |
429 | { | |
430 | vtype = VALIDATION_ETHERS; | |
431 | break; | |
432 | } | |
433 | default: return 0; | |
434 | } | |
435 | ||
436 | if (pp->notify_token[vtype] < 0) | |
437 | { | |
438 | path = _fsi_validation_path(vtype); | |
439 | if (path == NULL) return 0; | |
440 | ||
441 | memset(&sb, 0, sizeof(struct stat)); | |
442 | if (stat(path, &sb) != 0) return 0; | |
443 | if (va != sb.st_mtimespec.tv_sec) return 0; | |
444 | if (vb != sb.st_mtimespec.tv_nsec) return 0; | |
445 | } | |
446 | else | |
447 | { | |
448 | item_val = va; | |
449 | curr_val = -1; | |
450 | status = notify_peek(pp->notify_token[vtype], &curr_val); | |
451 | if (status != NOTIFY_STATUS_OK) return 0; | |
452 | ||
453 | curr_val = ntohl(curr_val); | |
454 | if (item_val != curr_val) return 0; | |
455 | } | |
53dd3e4a | 456 | #endif |
e44d8d47 A |
457 | |
458 | return 1; | |
459 | } | |
460 | ||
461 | /* netgroup support */ | |
462 | static char * | |
463 | _fsi_append_char_to_line(char c, char *buf, size_t *x) | |
464 | { | |
465 | if (x == NULL) return NULL; | |
466 | ||
467 | if (buf == NULL) *x = 0; | |
468 | ||
469 | if ((*x % CHUNK) == 0) | |
470 | { | |
471 | buf = reallocf(buf, *x + CHUNK); | |
9d0fc09c A |
472 | if (buf == NULL) return NULL; |
473 | ||
e44d8d47 A |
474 | memset(buf + *x, 0, CHUNK); |
475 | } | |
476 | ||
477 | buf[*x] = c; | |
478 | *x = *x + 1; | |
479 | ||
480 | return buf; | |
481 | } | |
482 | ||
483 | static char * | |
484 | _fsi_read_netgroup_line(FILE *f) | |
485 | { | |
486 | char *out = NULL; | |
487 | size_t x = 0; | |
488 | int white = 0; | |
489 | int paren = 0; | |
490 | ||
491 | if (f == NULL) return NULL; | |
492 | forever | |
493 | { | |
494 | int c = getc(f); | |
495 | ||
496 | if (c == EOF) | |
497 | { | |
498 | if (out == NULL) return NULL; | |
499 | return _fsi_append_char_to_line('\0', out, &x); | |
500 | } | |
501 | ||
502 | if (c == '\n') return _fsi_append_char_to_line('\0', out, &x); | |
503 | if (c == '(') paren = 1; | |
504 | else if (c == ')') paren = 0; | |
505 | ||
506 | if ((c == ' ') || (c == '\t')) | |
507 | { | |
508 | if ((white == 0) && (paren == 0)) out = _fsi_append_char_to_line(' ', out, &x); | |
509 | white = 1; | |
510 | } | |
511 | else if (c == '\\') | |
512 | { | |
513 | forever | |
514 | { | |
515 | c = getc(f); | |
516 | if (c == EOF) return _fsi_append_char_to_line('\0', out, &x); | |
517 | if (c == '\n') break; | |
518 | } | |
519 | } | |
520 | else | |
521 | { | |
522 | out = _fsi_append_char_to_line(c, out, &x); | |
523 | white = 0; | |
524 | } | |
525 | } | |
526 | } | |
527 | ||
528 | static file_netgroup_t * | |
529 | _fsi_find_netgroup(file_netgroup_t **list, const char *name, int create) | |
530 | { | |
531 | file_netgroup_t *n; | |
532 | ||
533 | if (list == NULL) return NULL; | |
534 | ||
535 | for (n = *list; n != NULL; n = n->next) | |
536 | { | |
537 | if (!strcmp(name, n->name)) return n; | |
538 | } | |
539 | ||
540 | if (create == 0) return NULL; | |
541 | ||
542 | n = (file_netgroup_t *)calloc(1, sizeof(file_netgroup_t)); | |
543 | if (n == NULL) return NULL; | |
544 | ||
545 | n->name = strdup(name); | |
546 | ||
547 | n->next = *list; | |
548 | *list = n; | |
549 | return n; | |
550 | } | |
551 | ||
552 | void | |
553 | _fsi_free_file_netgroup(file_netgroup_t *n) | |
554 | { | |
555 | file_netgroup_member_t *m; | |
556 | ||
557 | if (n == NULL) return; | |
558 | free(n->name); | |
559 | ||
560 | m = n->members; | |
561 | while (m != NULL) | |
562 | { | |
563 | file_netgroup_member_t *x = m; | |
564 | m = m->next; | |
565 | free(x->host); | |
566 | free(x->user); | |
567 | free(x->domain); | |
568 | free(x); | |
569 | } | |
570 | ||
571 | free(n); | |
572 | } | |
573 | ||
574 | static void | |
575 | _fsi_add_netgroup_group(file_netgroup_t *n, char *grp) | |
576 | { | |
577 | file_netgroup_member_t *g; | |
578 | ||
579 | if (n == NULL) return; | |
580 | ||
581 | g = (file_netgroup_member_t *)calloc(1, sizeof(file_netgroup_member_t)); | |
582 | if (g == NULL) return; | |
583 | ||
584 | g->flags = FNG_GRP; | |
585 | g->host = strdup(grp); | |
586 | ||
587 | g->next = n->members; | |
588 | n->members = g; | |
589 | ||
590 | return; | |
591 | } | |
592 | ||
593 | static void | |
594 | _fsi_add_netgroup_member(file_netgroup_t *n, char *mem) | |
595 | { | |
596 | char **tokens; | |
597 | file_netgroup_member_t *m; | |
598 | int ntokens; | |
599 | ||
600 | if (n == NULL) return; | |
601 | ||
602 | m = (file_netgroup_member_t *)calloc(1, sizeof(file_netgroup_member_t)); | |
603 | if (m == NULL) return; | |
604 | ||
605 | tokens = _fsi_tokenize(mem + 1, ",)", 0, &ntokens); | |
606 | ||
607 | if (tokens == NULL) | |
608 | { | |
609 | free(m); | |
610 | return; | |
611 | } | |
612 | ||
613 | if ((ntokens > 0) && (tokens[0][0] != '\0')) m->host = strdup(tokens[0]); | |
614 | if ((ntokens > 1) && (tokens[1][0] != '\0')) m->user = strdup(tokens[1]); | |
615 | if ((ntokens > 2) && (tokens[2][0] != '\0')) m->domain = strdup(tokens[2]); | |
616 | ||
617 | free(tokens); | |
618 | ||
619 | m->flags = FNG_MEM; | |
620 | m->next = n->members; | |
621 | n->members = m; | |
622 | } | |
623 | ||
624 | static file_netgroup_t * | |
625 | _fsi_process_netgroup_line(file_netgroup_t **pass1, char *line) | |
626 | { | |
627 | file_netgroup_t *n; | |
628 | char **tokens; | |
629 | int i, ntokens = 0; | |
630 | ||
631 | tokens = _fsi_tokenize(line, " ", 0, &ntokens); | |
632 | if (tokens == NULL) return NULL; | |
633 | if (tokens[0] == NULL) | |
634 | { | |
635 | free(tokens); | |
636 | return NULL; | |
637 | } | |
638 | ||
639 | n = _fsi_find_netgroup(pass1, tokens[0], 1); | |
640 | ||
641 | for (i = 1; tokens[i] != NULL; i++) | |
642 | { | |
643 | if (tokens[i][0] == '(') _fsi_add_netgroup_member(n, tokens[i]); | |
644 | else if (tokens[i][0] != '\0') _fsi_add_netgroup_group(n, tokens[i]); | |
645 | } | |
646 | ||
647 | free(tokens); | |
648 | return n; | |
649 | } | |
650 | ||
651 | static void | |
652 | _fsi_flatten_netgroup(file_netgroup_t *pass1, file_netgroup_t **top, file_netgroup_t *n, file_netgroup_member_t *m) | |
653 | { | |
654 | if (n == NULL) return; | |
655 | ||
656 | if (n->flags == 1) return; | |
657 | n->flags = 1; | |
658 | ||
659 | if (*top == NULL) | |
660 | { | |
661 | *top = (file_netgroup_t *)calloc(1, sizeof(file_netgroup_t)); | |
662 | if (*top == NULL) return; | |
663 | (*top)->name = strdup(n->name); | |
664 | if ((*top)->name == NULL) | |
665 | { | |
666 | free(*top); | |
667 | *top = NULL; | |
668 | return; | |
669 | } | |
670 | } | |
671 | ||
672 | while (m!= NULL) | |
673 | { | |
674 | if (m->flags & FNG_MEM) | |
675 | { | |
676 | file_netgroup_member_t *x = (file_netgroup_member_t *)calloc(1, sizeof(file_netgroup_member_t)); | |
677 | if (x == NULL) return; | |
678 | ||
679 | x->flags = FNG_MEM; | |
680 | if (m->host != NULL) x->host = strdup(m->host); | |
681 | if (m->user != NULL) x->user = strdup(m->user); | |
682 | if (m->domain != NULL) x->domain = strdup(m->domain); | |
683 | ||
684 | x->next = (*top)->members; | |
685 | (*top)->members = x; | |
686 | } | |
687 | else | |
688 | { | |
689 | file_netgroup_t *g = _fsi_find_netgroup(&pass1, m->host, 0); | |
690 | if (g == NULL) continue; | |
691 | ||
692 | _fsi_flatten_netgroup(pass1, top, g, g->members); | |
693 | } | |
694 | ||
695 | m = m->next; | |
696 | } | |
697 | } | |
698 | ||
699 | static void | |
700 | _fsi_check_netgroup_cache(si_mod_t *si) | |
701 | { | |
702 | file_netgroup_t *p1, *n, *x, *a; | |
703 | char *line; | |
704 | FILE *f; | |
705 | file_si_private_t *pp; | |
706 | ||
707 | if (si == NULL) return; | |
708 | ||
709 | pp = (file_si_private_t *)si->private; | |
710 | if (pp == NULL) return; | |
711 | ||
712 | pthread_mutex_lock(&file_mutex); | |
713 | ||
714 | if (_fsi_validate(si, CATEGORY_NETGROUP, pp->netgroup_validation_a, pp->netgroup_validation_b)) | |
715 | { | |
716 | pthread_mutex_unlock(&file_mutex); | |
717 | return; | |
718 | } | |
719 | ||
720 | n = pp->file_netgroup_cache; | |
721 | while (n != NULL) | |
722 | { | |
723 | x = n; | |
724 | n = n->next; | |
725 | _fsi_free_file_netgroup(x); | |
726 | } | |
727 | ||
728 | pp->file_netgroup_cache = NULL; | |
729 | ||
730 | f = fopen(_PATH_NETGROUP, "r"); | |
731 | if (f == NULL) | |
732 | { | |
733 | pthread_mutex_unlock(&file_mutex); | |
734 | return; | |
735 | } | |
736 | ||
737 | _fsi_get_validation(si, VALIDATION_NETGROUP, _PATH_NETGROUP, f, &(pp->netgroup_validation_a), &(pp->netgroup_validation_b)); | |
738 | ||
739 | p1 = NULL; | |
740 | ||
741 | line = _fsi_read_netgroup_line(f); | |
742 | while (line != NULL) | |
743 | { | |
744 | n = _fsi_process_netgroup_line(&p1, line); | |
745 | ||
746 | free(line); | |
747 | line = _fsi_read_netgroup_line(f); | |
748 | } | |
749 | ||
750 | fclose(f); | |
751 | ||
752 | for (n = p1; n != NULL; n = n->next) | |
753 | { | |
754 | a = NULL; | |
755 | _fsi_flatten_netgroup(p1, &a, n, n->members); | |
756 | for (x = p1; x != NULL; x = x->next) x->flags = 0; | |
757 | ||
758 | if (a != NULL) | |
759 | { | |
760 | a->next = pp->file_netgroup_cache; | |
761 | pp->file_netgroup_cache = a; | |
762 | } | |
763 | } | |
764 | ||
765 | n = p1; | |
766 | while (n != NULL) | |
767 | { | |
768 | x = n; | |
769 | n = n->next; | |
770 | _fsi_free_file_netgroup(x); | |
771 | } | |
772 | ||
773 | pthread_mutex_unlock(&file_mutex); | |
774 | } | |
775 | ||
d49d4c81 A |
776 | /* USERS */ |
777 | ||
778 | static si_item_t * | |
e44d8d47 | 779 | _fsi_parse_user(si_mod_t *si, const char *name, uid_t uid, int which, char *data, int format, uint64_t va, uint64_t vb) |
d49d4c81 A |
780 | { |
781 | char **tokens; | |
782 | int ntokens, match; | |
e44d8d47 | 783 | time_t change, expire; |
d49d4c81 A |
784 | si_item_t *item; |
785 | uid_t xuid; | |
786 | ||
787 | if (data == NULL) return NULL; | |
788 | ||
789 | ntokens = 0; | |
790 | tokens = _fsi_tokenize(data, ":", 1, &ntokens); | |
791 | if (((format == 0) && (ntokens != 10)) || ((format == 1) && (ntokens != 7))) | |
792 | { | |
793 | free(tokens); | |
794 | return NULL; | |
795 | } | |
796 | ||
797 | xuid = atoi(tokens[2]); | |
798 | match = 0; | |
799 | ||
800 | /* XXX MATCH GECOS? XXX*/ | |
801 | if (which == SEL_ALL) match = 1; | |
802 | else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1; | |
803 | else if ((which == SEL_NUMBER) && (uid == xuid)) match = 1; | |
804 | ||
805 | if (match == 0) | |
806 | { | |
807 | free(tokens); | |
808 | return NULL; | |
809 | } | |
810 | ||
811 | if (format == 0) | |
812 | { | |
e44d8d47 A |
813 | /* master.passwd: name[0] passwd[1] uid[2] gid[3] class[4] change[5] expire[6] gecos[7] dir[8] shell[9] */ |
814 | /* struct pwd: name[0] passwd[1] uid[2] gid[3] change[5] class[4] gecos[7] dir[8] shell[9] expire[6] */ | |
d49d4c81 | 815 | change = atoi(tokens[5]); |
e44d8d47 A |
816 | expire = atoi(tokens[6]); |
817 | item = (si_item_t *)LI_ils_create("L4488ss44LssssL", (unsigned long)si, CATEGORY_USER, 1, va, vb, tokens[0], tokens[1], xuid, atoi(tokens[3]), change, tokens[4], tokens[7], tokens[8], tokens[9], expire); | |
d49d4c81 A |
818 | } |
819 | else | |
820 | { | |
821 | /* passwd: name[0] passwd[1] uid[2] gid[3] gecos[4] dir[5] shell[6] */ | |
e44d8d47 A |
822 | /* struct pwd: name[0] passwd[1] uid[2] gid[3] change[-] class[-] gecos[4] dir[5] shell[6] expire[-] */ |
823 | item = (si_item_t *)LI_ils_create("L4488ss44LssssL", (unsigned long)si, CATEGORY_USER, 1, va, vb, tokens[0], tokens[1], xuid, atoi(tokens[3]), 0, "", tokens[4], tokens[5], tokens[6], 0); | |
d49d4c81 A |
824 | } |
825 | ||
826 | free(tokens); | |
827 | return item; | |
828 | } | |
829 | ||
830 | static void * | |
831 | _fsi_get_user(si_mod_t *si, const char *name, uid_t uid, int which) | |
832 | { | |
833 | char *line; | |
834 | si_item_t *item; | |
835 | int fmt; | |
836 | FILE *f; | |
837 | si_list_t *all; | |
e44d8d47 | 838 | uint64_t va, vb; |
d49d4c81 A |
839 | |
840 | if ((which == SEL_NAME) && (name == NULL)) return NULL; | |
841 | ||
842 | all = NULL; | |
843 | f = NULL; | |
844 | fmt = 0; | |
e44d8d47 A |
845 | va = 0; |
846 | vb = 0; | |
d49d4c81 A |
847 | |
848 | if (geteuid() == 0) | |
849 | { | |
850 | f = fopen(_PATH_MASTERPASSWD, "r"); | |
e44d8d47 | 851 | _fsi_get_validation(si, VALIDATION_MASTER_PASSWD, _PATH_MASTERPASSWD, f, &va, &vb); |
d49d4c81 A |
852 | } |
853 | else | |
854 | { | |
855 | f = fopen(_PATH_PASSWD, "r"); | |
e44d8d47 | 856 | _fsi_get_validation(si, VALIDATION_PASSWD, _PATH_PASSWD, f, &va, &vb); |
d49d4c81 A |
857 | fmt = 1; |
858 | } | |
859 | ||
860 | if (f == NULL) return NULL; | |
861 | ||
d49d4c81 A |
862 | |
863 | forever | |
864 | { | |
865 | line = _fsi_get_line(f); | |
866 | if (line == NULL) break; | |
867 | ||
868 | if (line[0] == '#') | |
869 | { | |
870 | free(line); | |
871 | line = NULL; | |
872 | continue; | |
873 | } | |
874 | ||
e44d8d47 | 875 | item = _fsi_parse_user(si, name, uid, which, line, fmt, va, vb); |
d49d4c81 A |
876 | free(line); |
877 | line = NULL; | |
878 | ||
879 | if (item == NULL) continue; | |
880 | ||
881 | if (which == SEL_ALL) | |
882 | { | |
883 | all = si_list_add(all, item); | |
884 | si_item_release(item); | |
885 | continue; | |
886 | } | |
887 | ||
888 | fclose(f); | |
889 | return item; | |
890 | } | |
891 | fclose(f); | |
892 | return all; | |
893 | } | |
894 | ||
895 | /* GROUPS */ | |
896 | ||
897 | static si_item_t * | |
e44d8d47 | 898 | _fsi_parse_group(si_mod_t *si, const char *name, gid_t gid, int which, char *data, uint64_t va, uint64_t vb) |
d49d4c81 A |
899 | { |
900 | char **tokens, **members; | |
901 | int ntokens, match; | |
902 | si_item_t *item; | |
903 | gid_t xgid; | |
904 | ||
905 | if (data == NULL) return NULL; | |
906 | ||
907 | ntokens = 0; | |
908 | tokens = _fsi_tokenize(data, ":", 1, &ntokens); | |
909 | if (ntokens != 4) | |
910 | { | |
911 | free(tokens); | |
912 | return NULL; | |
913 | } | |
914 | ||
915 | xgid = atoi(tokens[2]); | |
916 | match = 0; | |
917 | ||
918 | if (which == SEL_ALL) match = 1; | |
919 | else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1; | |
920 | else if ((which == SEL_NUMBER) && (gid == xgid)) match = 1; | |
921 | ||
922 | if (match == 0) | |
923 | { | |
924 | free(tokens); | |
925 | return NULL; | |
926 | } | |
927 | ||
928 | ntokens = 0; | |
929 | members = _fsi_tokenize(tokens[3], ",", 1, &ntokens); | |
930 | ||
e44d8d47 | 931 | item = (si_item_t *)LI_ils_create("L4488ss4*", (unsigned long)si, CATEGORY_GROUP, 1, va, vb, tokens[0], tokens[1], xgid, members); |
d49d4c81 A |
932 | |
933 | free(tokens); | |
934 | free(members); | |
935 | ||
936 | return item; | |
937 | } | |
938 | ||
939 | static void * | |
940 | _fsi_get_group(si_mod_t *si, const char *name, gid_t gid, int which) | |
941 | { | |
942 | char *line; | |
943 | si_item_t *item; | |
944 | FILE *f; | |
945 | si_list_t *all; | |
e44d8d47 | 946 | uint64_t va, vb; |
d49d4c81 A |
947 | |
948 | if ((which == SEL_NAME) && (name == NULL)) return NULL; | |
949 | ||
950 | all = NULL; | |
951 | f = NULL; | |
d49d4c81 A |
952 | |
953 | f = fopen(_PATH_GROUP, "r"); | |
954 | if (f == NULL) return NULL; | |
955 | ||
e44d8d47 | 956 | _fsi_get_validation(si, VALIDATION_GROUP, _PATH_GROUP, f, &va, &vb); |
d49d4c81 A |
957 | |
958 | forever | |
959 | { | |
960 | line = _fsi_get_line(f); | |
961 | if (line == NULL) break; | |
962 | ||
963 | if (line[0] == '#') | |
964 | { | |
965 | free(line); | |
966 | line = NULL; | |
967 | continue; | |
968 | } | |
969 | ||
e44d8d47 | 970 | item = _fsi_parse_group(si, name, gid, which, line, va, vb); |
d49d4c81 A |
971 | free(line); |
972 | line = NULL; | |
973 | ||
974 | if (item == NULL) continue; | |
975 | ||
976 | if (which == SEL_ALL) | |
977 | { | |
978 | all = si_list_add(all, item); | |
979 | si_item_release(item); | |
980 | continue; | |
981 | } | |
982 | ||
983 | fclose(f); | |
984 | return item; | |
985 | } | |
986 | ||
987 | fclose(f); | |
988 | return all; | |
989 | } | |
990 | ||
991 | static void * | |
992 | _fsi_get_grouplist(si_mod_t *si, const char *user) | |
993 | { | |
994 | char **tokens, **members; | |
995 | int ntokens, i, match, gidcount; | |
996 | char *line; | |
997 | si_item_t *item; | |
998 | FILE *f; | |
e44d8d47 | 999 | uint64_t va, vb; |
d31dd049 A |
1000 | gid_t gid, basegid; |
1001 | gid_t *gidlist; | |
d49d4c81 A |
1002 | struct passwd *pw; |
1003 | ||
1004 | if (user == NULL) return NULL; | |
1005 | ||
1006 | gidlist = NULL; | |
1007 | gidcount = 0; | |
1008 | f = NULL; | |
d49d4c81 A |
1009 | basegid = -1; |
1010 | ||
e44d8d47 | 1011 | item = si->vtable->sim_user_byname(si, user); |
d49d4c81 A |
1012 | if (item != NULL) |
1013 | { | |
1014 | pw = (struct passwd *)((uintptr_t)item + sizeof(si_item_t)); | |
1015 | basegid = pw->pw_gid; | |
d31dd049 A |
1016 | si_item_release(item); |
1017 | item = NULL; | |
d49d4c81 A |
1018 | } |
1019 | ||
1020 | f = fopen(_PATH_GROUP, "r"); | |
1021 | if (f == NULL) return NULL; | |
1022 | ||
e44d8d47 | 1023 | _fsi_get_validation(si, VALIDATION_GROUP, _PATH_GROUP, f, &va, &vb); |
d49d4c81 A |
1024 | |
1025 | forever | |
1026 | { | |
1027 | line = _fsi_get_line(f); | |
1028 | if (line == NULL) break; | |
1029 | ||
1030 | if (line[0] == '#') | |
1031 | { | |
1032 | free(line); | |
1033 | line = NULL; | |
1034 | continue; | |
1035 | } | |
1036 | ||
1037 | ntokens = 0; | |
1038 | tokens = _fsi_tokenize(line, ":", 1, &ntokens); | |
1039 | if (ntokens != 4) | |
1040 | { | |
1041 | free(tokens); | |
1042 | continue; | |
1043 | } | |
1044 | ||
1045 | ntokens = 0; | |
1046 | members = _fsi_tokenize(tokens[3], ",", 1, &ntokens); | |
1047 | ||
1048 | match = 0; | |
1049 | gid = -2; | |
1050 | ||
d31dd049 | 1051 | for (i = 0; i < ntokens; i++) |
d49d4c81 A |
1052 | { |
1053 | if (string_equal(user, members[i])) | |
1054 | { | |
1055 | gid = atoi(tokens[2]); | |
1056 | match = 1; | |
d31dd049 | 1057 | break; |
d49d4c81 A |
1058 | } |
1059 | } | |
1060 | ||
1061 | free(tokens); | |
1062 | free(members); | |
1063 | free(line); | |
1064 | line = NULL; | |
1065 | ||
1066 | if (match == 1) | |
1067 | { | |
d31dd049 | 1068 | gidlist = (gid_t *) reallocf(gidlist, (gidcount + 1) * sizeof(gid_t)); |
d49d4c81 A |
1069 | if (gidlist == NULL) |
1070 | { | |
1071 | gidcount = 0; | |
1072 | break; | |
1073 | } | |
1074 | ||
d31dd049 | 1075 | gidlist[gidcount++] = gid; |
d49d4c81 A |
1076 | } |
1077 | } | |
1078 | ||
1079 | fclose(f); | |
1080 | ||
d31dd049 A |
1081 | if (gidcount != 0) { |
1082 | item = (si_item_t *)LI_ils_create("L4488s4@", (unsigned long)si, CATEGORY_GROUPLIST, 1, va, vb, user, gidcount, | |
1083 | gidcount * sizeof(gid_t), gidlist); | |
1084 | } | |
d49d4c81 | 1085 | |
d49d4c81 A |
1086 | free(gidlist); |
1087 | ||
1088 | return item; | |
1089 | } | |
1090 | ||
1091 | /* ALIASES */ | |
1092 | ||
1093 | static si_item_t * | |
e44d8d47 | 1094 | _fsi_parse_alias(si_mod_t *si, const char *name, int which, char *data, uint64_t va, uint64_t vb) |
d49d4c81 A |
1095 | { |
1096 | char **tokens, **members; | |
1097 | int ntokens, match; | |
1098 | si_item_t *item; | |
1099 | ||
1100 | if (data == NULL) return NULL; | |
1101 | ||
1102 | ntokens = 0; | |
1103 | tokens = _fsi_tokenize(data, ":", 1, &ntokens); | |
1104 | if (ntokens < 2) | |
1105 | { | |
1106 | free(tokens); | |
1107 | return NULL; | |
1108 | } | |
1109 | ||
1110 | match = 0; | |
1111 | ||
1112 | if (which == SEL_ALL) match = 1; | |
1113 | else if (string_equal(name, tokens[0])) match = 1; | |
1114 | ||
1115 | if (match == 0) | |
1116 | { | |
1117 | free(tokens); | |
1118 | return NULL; | |
1119 | } | |
1120 | ||
1121 | ntokens = 0; | |
e44d8d47 | 1122 | members = _fsi_tokenize(tokens[1], ",", 1, &ntokens); |
d49d4c81 | 1123 | |
e44d8d47 | 1124 | item = (si_item_t *)LI_ils_create("L4488s4*4", (unsigned long)si, CATEGORY_ALIAS, 1, va, vb, tokens[0], ntokens, members, 1); |
d49d4c81 A |
1125 | |
1126 | free(tokens); | |
1127 | free(members); | |
1128 | ||
1129 | return item; | |
1130 | } | |
1131 | ||
1132 | static void * | |
1133 | _fsi_get_alias(si_mod_t *si, const char *name, int which) | |
1134 | { | |
1135 | char *line; | |
1136 | si_item_t *item; | |
1137 | FILE *f; | |
1138 | si_list_t *all; | |
e44d8d47 | 1139 | uint64_t va, vb; |
d49d4c81 A |
1140 | |
1141 | if ((which == SEL_NAME) && (name == NULL)) return NULL; | |
1142 | ||
1143 | all = NULL; | |
1144 | f = NULL; | |
d49d4c81 A |
1145 | |
1146 | f = fopen(_PATH_ALIASES, "r"); | |
1147 | if (f == NULL) return NULL; | |
1148 | ||
e44d8d47 | 1149 | _fsi_get_validation(si, VALIDATION_ALIASES, _PATH_ALIASES, f, &va, &vb); |
d49d4c81 A |
1150 | |
1151 | forever | |
1152 | { | |
1153 | line = _fsi_get_line(f); | |
1154 | if (line == NULL) break; | |
1155 | ||
1156 | if (line[0] == '#') | |
1157 | { | |
1158 | free(line); | |
1159 | line = NULL; | |
1160 | continue; | |
1161 | } | |
1162 | ||
e44d8d47 | 1163 | item = _fsi_parse_alias(si, name, which, line, va, vb); |
d49d4c81 A |
1164 | free(line); |
1165 | line = NULL; | |
1166 | ||
1167 | if (item == NULL) continue; | |
1168 | ||
1169 | if (which == SEL_ALL) | |
1170 | { | |
1171 | all = si_list_add(all, item); | |
1172 | si_item_release(item); | |
1173 | continue; | |
1174 | } | |
1175 | ||
1176 | fclose(f); | |
1177 | return item; | |
1178 | } | |
1179 | ||
1180 | fclose(f); | |
1181 | return all; | |
1182 | } | |
1183 | ||
1184 | /* ETHERS */ | |
1185 | ||
1186 | static si_item_t * | |
e44d8d47 | 1187 | _fsi_parse_ether(si_mod_t *si, const char *name, int which, char *data, uint64_t va, uint64_t vb) |
d49d4c81 A |
1188 | { |
1189 | char **tokens; | |
1190 | char *cmac; | |
1191 | int ntokens, match; | |
1192 | si_item_t *item; | |
1193 | ||
1194 | if (data == NULL) return NULL; | |
1195 | ||
1196 | ntokens = 0; | |
1197 | tokens = _fsi_tokenize(data, " \t", 1, &ntokens); | |
1198 | if (ntokens != 2) | |
1199 | { | |
1200 | free(tokens); | |
1201 | return NULL; | |
1202 | } | |
1203 | ||
e44d8d47 | 1204 | cmac = si_standardize_mac_address(tokens[0]); |
d49d4c81 A |
1205 | if (cmac == NULL) |
1206 | { | |
1207 | free(tokens); | |
1208 | return NULL; | |
1209 | } | |
1210 | ||
1211 | match = 0; | |
1212 | if (which == SEL_ALL) match = 1; | |
e44d8d47 | 1213 | else if ((which == SEL_NAME) && (string_equal(name, tokens[1]))) match = 1; |
d49d4c81 A |
1214 | else if ((which == SEL_NUMBER) && (string_equal(name, cmac))) match = 1; |
1215 | ||
1216 | if (match == 0) | |
1217 | { | |
1218 | free(tokens); | |
1219 | free(cmac); | |
1220 | return NULL; | |
1221 | } | |
1222 | ||
e44d8d47 | 1223 | item = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, va, vb, tokens[1], cmac); |
d49d4c81 A |
1224 | |
1225 | free(tokens); | |
1226 | free(cmac); | |
1227 | ||
1228 | return item; | |
1229 | } | |
1230 | ||
1231 | static void * | |
1232 | _fsi_get_ether(si_mod_t *si, const char *name, int which) | |
1233 | { | |
1234 | char *line, *cmac; | |
1235 | si_item_t *item; | |
1236 | FILE *f; | |
1237 | si_list_t *all; | |
e44d8d47 | 1238 | uint64_t va, vb; |
d49d4c81 A |
1239 | |
1240 | if ((which != SEL_ALL) && (name == NULL)) return NULL; | |
1241 | ||
1242 | cmac = NULL; | |
1243 | if (which == SEL_NUMBER) | |
1244 | { | |
e44d8d47 | 1245 | cmac = si_standardize_mac_address(name); |
d49d4c81 A |
1246 | if (cmac == NULL) return NULL; |
1247 | } | |
1248 | ||
1249 | all = NULL; | |
1250 | f = NULL; | |
d49d4c81 A |
1251 | |
1252 | f = fopen(_PATH_ETHERS, "r"); | |
1253 | if (f == NULL) return NULL; | |
1254 | ||
e44d8d47 | 1255 | _fsi_get_validation(si, VALIDATION_ETHERS, _PATH_ETHERS, f, &va, &vb); |
d49d4c81 A |
1256 | |
1257 | forever | |
1258 | { | |
1259 | line = _fsi_get_line(f); | |
1260 | if (line == NULL) break; | |
1261 | ||
1262 | if (line[0] == '#') | |
1263 | { | |
1264 | free(line); | |
1265 | line = NULL; | |
1266 | continue; | |
1267 | } | |
1268 | ||
1269 | item = NULL; | |
e44d8d47 A |
1270 | if (which == SEL_NUMBER) item = _fsi_parse_ether(si, cmac, which, line, va, vb); |
1271 | else item = _fsi_parse_ether(si, name, which, line, va, vb); | |
d49d4c81 A |
1272 | |
1273 | free(line); | |
1274 | line = NULL; | |
1275 | ||
1276 | if (item == NULL) continue; | |
1277 | ||
1278 | if (which == SEL_ALL) | |
1279 | { | |
1280 | all = si_list_add(all, item); | |
1281 | si_item_release(item); | |
1282 | continue; | |
1283 | } | |
1284 | ||
1285 | fclose(f); | |
1286 | return item; | |
1287 | } | |
1288 | ||
1289 | fclose(f); | |
1290 | return all; | |
1291 | } | |
1292 | ||
1293 | /* HOSTS */ | |
1294 | ||
1295 | static si_item_t * | |
e44d8d47 | 1296 | _fsi_parse_host(si_mod_t *si, const char *name, const void *addr, int af, int which, char *data, uint64_t va, uint64_t vb) |
d49d4c81 A |
1297 | { |
1298 | char **tokens, **h_aliases, *null_alias; | |
e44d8d47 | 1299 | int i, ntokens, match, h_addrtype, h_length; |
d49d4c81 A |
1300 | struct in_addr a4; |
1301 | struct in6_addr a6; | |
1302 | si_item_t *item; | |
1303 | char *h_addr_list[2]; | |
1304 | char h_addr_4[4], h_addr_6[16]; | |
1305 | ||
1306 | if (data == NULL) return NULL; | |
1307 | ||
1308 | null_alias = NULL; | |
1309 | ||
1310 | ntokens = 0; | |
1311 | tokens = _fsi_tokenize(data, " ", 0, &ntokens); | |
1312 | if (ntokens < 2) | |
1313 | { | |
1314 | free(tokens); | |
1315 | return NULL; | |
1316 | } | |
1317 | ||
1318 | h_addr_list[1] = NULL; | |
1319 | ||
e44d8d47 | 1320 | h_addrtype = AF_UNSPEC; |
d49d4c81 A |
1321 | if (inet_pton(AF_INET, tokens[0], &a4) == 1) |
1322 | { | |
e44d8d47 | 1323 | h_addrtype = AF_INET; |
d49d4c81 A |
1324 | h_length = sizeof(struct in_addr); |
1325 | memcpy(h_addr_4, &a4, 4); | |
1326 | h_addr_list[0] = h_addr_4; | |
1327 | } | |
1328 | else if (inet_pton(AF_INET6, tokens[0], &a6) == 1) | |
1329 | { | |
e44d8d47 | 1330 | h_addrtype = AF_INET6; |
d49d4c81 A |
1331 | h_length = sizeof(struct in6_addr); |
1332 | memcpy(h_addr_6, &a6, 16); | |
1333 | h_addr_list[0] = h_addr_6; | |
1334 | } | |
1335 | ||
e44d8d47 | 1336 | if (h_addrtype == AF_UNSPEC) |
d49d4c81 A |
1337 | { |
1338 | free(tokens); | |
1339 | return NULL; | |
1340 | } | |
1341 | ||
1342 | h_aliases = NULL; | |
1343 | if (ntokens > 2) h_aliases = &(tokens[2]); | |
1344 | ||
1345 | match = 0; | |
1346 | ||
1347 | if (which == SEL_ALL) match = 1; | |
1348 | else | |
1349 | { | |
e44d8d47 | 1350 | if (h_addrtype == af) |
d49d4c81 A |
1351 | { |
1352 | if (which == SEL_NAME) | |
1353 | { | |
1354 | if (string_equal(name, tokens[1])) match = 1; | |
1355 | else if (h_aliases != NULL) | |
1356 | { | |
1357 | for (i = 0; (h_aliases[i] != NULL) && (match == 0); i++) | |
1358 | if (string_equal(name, h_aliases[i])) match = 1; | |
1359 | } | |
1360 | } | |
1361 | else if (which == SEL_NUMBER) | |
1362 | { | |
1363 | if (memcmp(addr, h_addr_list[0], h_length) == 0) match = 1; | |
1364 | } | |
1365 | } | |
1366 | } | |
1367 | ||
1368 | if (match == 0) | |
1369 | { | |
1370 | free(tokens); | |
1371 | return NULL; | |
1372 | } | |
1373 | ||
1374 | item = NULL; | |
1375 | ||
1376 | if (h_aliases == NULL) h_aliases = &null_alias; | |
1377 | ||
e44d8d47 | 1378 | if (h_addrtype == AF_INET) |
d49d4c81 | 1379 | { |
e44d8d47 | 1380 | item = (si_item_t *)LI_ils_create("L4488s*44a", (unsigned long)si, CATEGORY_HOST_IPV4, 1, va, vb, tokens[1], h_aliases, h_addrtype, h_length, h_addr_list); |
d49d4c81 A |
1381 | } |
1382 | else | |
1383 | { | |
e44d8d47 | 1384 | item = (si_item_t *)LI_ils_create("L4488s*44c", (unsigned long)si, CATEGORY_HOST_IPV6, 1, va, vb, tokens[1], h_aliases, h_addrtype, h_length, h_addr_list); |
d49d4c81 A |
1385 | } |
1386 | ||
1387 | free(tokens); | |
1388 | ||
1389 | return item; | |
1390 | } | |
1391 | ||
1392 | static void * | |
1393 | _fsi_get_host(si_mod_t *si, const char *name, const void *addr, int af, int which, uint32_t *err) | |
1394 | { | |
1395 | char *line; | |
1396 | si_item_t *item; | |
1397 | FILE *f; | |
1398 | si_list_t *all; | |
e44d8d47 | 1399 | uint64_t va, vb; |
d49d4c81 A |
1400 | |
1401 | if ((which == SEL_NAME) && (name == NULL)) | |
1402 | { | |
1403 | if (err != NULL) *err = NO_RECOVERY; | |
1404 | return NULL; | |
1405 | } | |
1406 | ||
1407 | if ((which == SEL_NUMBER) && (addr == NULL)) | |
1408 | { | |
1409 | if (err != NULL) *err = NO_RECOVERY; | |
1410 | return NULL; | |
1411 | } | |
1412 | ||
1413 | f = fopen(_PATH_HOSTS, "r"); | |
1414 | if (f == NULL) | |
1415 | { | |
1416 | if (err != NULL) *err = NO_RECOVERY; | |
1417 | return NULL; | |
1418 | } | |
1419 | ||
e44d8d47 | 1420 | _fsi_get_validation(si, VALIDATION_HOSTS, _PATH_HOSTS, f, &va, &vb); |
d49d4c81 A |
1421 | |
1422 | all = NULL; | |
1423 | ||
1424 | forever | |
1425 | { | |
1426 | line = _fsi_get_line(f); | |
1427 | if (line == NULL) break; | |
1428 | ||
1429 | if (line[0] == '#') | |
1430 | { | |
1431 | free(line); | |
1432 | line = NULL; | |
1433 | continue; | |
1434 | } | |
1435 | ||
e44d8d47 | 1436 | item = _fsi_parse_host(si, name, addr, af, which, line, va, vb); |
d49d4c81 A |
1437 | free(line); |
1438 | line = NULL; | |
1439 | ||
1440 | if (item == NULL) continue; | |
1441 | ||
1442 | if (which == SEL_ALL) | |
1443 | { | |
1444 | all = si_list_add(all, item); | |
1445 | si_item_release(item); | |
1446 | continue; | |
1447 | } | |
1448 | ||
1449 | fclose(f); | |
1450 | return item; | |
1451 | } | |
1452 | ||
1453 | fclose(f); | |
1454 | return all; | |
1455 | } | |
1456 | ||
1457 | /* SERVICE */ | |
1458 | ||
1459 | static si_item_t * | |
e44d8d47 | 1460 | _fsi_parse_service(si_mod_t *si, const char *name, const char *proto, int port, int which, char *data, uint64_t va, uint64_t vb) |
d49d4c81 A |
1461 | { |
1462 | char **tokens, **s_aliases, *xproto; | |
1463 | int i, ntokens, match; | |
1464 | si_item_t *item; | |
1465 | int xport; | |
1466 | ||
1467 | if (data == NULL) return NULL; | |
1468 | ||
1469 | port = ntohs(port); | |
1470 | ||
1471 | ntokens = 0; | |
1472 | tokens = _fsi_tokenize(data, " ", 0, &ntokens); | |
1473 | if (ntokens < 2) | |
1474 | { | |
1475 | free(tokens); | |
1476 | return NULL; | |
1477 | } | |
1478 | ||
1479 | s_aliases = NULL; | |
1480 | if (ntokens > 2) s_aliases = &(tokens[2]); | |
1481 | ||
1482 | xport = atoi(tokens[1]); | |
1483 | ||
1484 | xproto = strchr(tokens[1], '/'); | |
1485 | ||
1486 | if (xproto == NULL) | |
1487 | { | |
1488 | free(tokens); | |
1489 | return NULL; | |
1490 | } | |
1491 | ||
1492 | *xproto++ = '\0'; | |
1493 | if ((proto != NULL) && (string_not_equal(proto, xproto))) | |
1494 | { | |
1495 | free(tokens); | |
1496 | return NULL; | |
1497 | } | |
1498 | ||
1499 | match = 0; | |
1500 | if (which == SEL_ALL) match = 1; | |
1501 | else if (which == SEL_NAME) | |
1502 | { | |
1503 | if (string_equal(name, tokens[0])) match = 1; | |
1504 | else if (s_aliases != NULL) | |
1505 | { | |
1506 | for (i = 0; (s_aliases[i] != NULL) && (match == 0); i++) | |
1507 | if (string_equal(name, s_aliases[i])) match = 1; | |
1508 | } | |
1509 | } | |
1510 | else if ((which == SEL_NUMBER) && (port == xport)) match = 1; | |
1511 | ||
1512 | if (match == 0) | |
1513 | { | |
1514 | free(tokens); | |
1515 | return NULL; | |
1516 | } | |
1517 | ||
1518 | /* strange but correct */ | |
1519 | xport = htons(xport); | |
1520 | ||
e44d8d47 | 1521 | item = (si_item_t *)LI_ils_create("L4488s*4s", (unsigned long)si, CATEGORY_SERVICE, 1, va, vb, tokens[0], s_aliases, xport, xproto); |
d49d4c81 A |
1522 | |
1523 | free(tokens); | |
1524 | ||
1525 | return item; | |
1526 | } | |
1527 | ||
1528 | static void * | |
1529 | _fsi_get_service(si_mod_t *si, const char *name, const char *proto, int port, int which) | |
1530 | { | |
1531 | char *p, *line; | |
1532 | si_item_t *item; | |
1533 | FILE *f; | |
1534 | si_list_t *all; | |
e44d8d47 | 1535 | uint64_t va, vb; |
d49d4c81 A |
1536 | |
1537 | if ((which == SEL_NAME) && (name == NULL)) return NULL; | |
1538 | if ((which == SEL_NUMBER) && (port == 0)) return NULL; | |
1539 | ||
1540 | f = fopen(_PATH_SERVICES, "r"); | |
1541 | if (f == NULL) return NULL; | |
1542 | ||
e44d8d47 | 1543 | _fsi_get_validation(si, VALIDATION_SERVICES, _PATH_SERVICES, f, &va, &vb); |
d49d4c81 A |
1544 | |
1545 | all = NULL; | |
1546 | ||
1547 | forever | |
1548 | { | |
1549 | line = _fsi_get_line(f); | |
1550 | if (line == NULL) break; | |
1551 | ||
1552 | if (line[0] == '#') | |
1553 | { | |
1554 | free(line); | |
1555 | line = NULL; | |
1556 | continue; | |
1557 | } | |
1558 | ||
1559 | p = strchr(line, '#'); | |
1560 | if (p != NULL) *p = '\0'; | |
1561 | ||
e44d8d47 | 1562 | item = _fsi_parse_service(si, name, proto, port, which, line, va, vb); |
d49d4c81 A |
1563 | free(line); |
1564 | line = NULL; | |
1565 | ||
1566 | if (item == NULL) continue; | |
1567 | ||
1568 | if (which == SEL_ALL) | |
1569 | { | |
1570 | all = si_list_add(all, item); | |
1571 | si_item_release(item); | |
1572 | continue; | |
1573 | } | |
1574 | ||
1575 | fclose(f); | |
1576 | return item; | |
1577 | } | |
1578 | ||
1579 | fclose(f); | |
1580 | return all; | |
1581 | } | |
1582 | ||
1583 | /* | |
1584 | * Generic name/number/aliases lookup | |
1585 | * Works for protocols, networks, and rpcs | |
1586 | */ | |
1587 | ||
1588 | static si_item_t * | |
e44d8d47 | 1589 | _fsi_parse_name_num_aliases(si_mod_t *si, const char *name, int num, int which, char *data, uint64_t va, uint64_t vb, int cat) |
d49d4c81 A |
1590 | { |
1591 | char **tokens, **aliases; | |
1592 | int i, ntokens, match, xnum; | |
1593 | si_item_t *item; | |
1594 | ||
1595 | if (data == NULL) return NULL; | |
1596 | ||
1597 | ntokens = 0; | |
1598 | tokens = _fsi_tokenize(data, " ", 0, &ntokens); | |
1599 | if (ntokens < 2) | |
1600 | { | |
1601 | free(tokens); | |
1602 | return NULL; | |
1603 | } | |
1604 | ||
1605 | xnum = atoi(tokens[1]); | |
1606 | ||
1607 | aliases = NULL; | |
1608 | if (ntokens > 2) aliases = &(tokens[2]); | |
1609 | ||
1610 | match = 0; | |
1611 | ||
1612 | if (which == SEL_ALL) match = 1; | |
1613 | else if (which == SEL_NAME) | |
1614 | { | |
1615 | if (string_equal(name, tokens[0])) match = 1; | |
1616 | else if (aliases != NULL) | |
1617 | { | |
1618 | for (i = 0; (aliases[i] != NULL) && (match == 0); i++) | |
1619 | if (string_equal(name, aliases[i])) match = 1; | |
1620 | } | |
1621 | } | |
1622 | else if ((which == SEL_NUMBER) && (num == xnum)) match = 1; | |
1623 | ||
1624 | if (match == 0) | |
1625 | { | |
1626 | free(tokens); | |
1627 | return NULL; | |
1628 | } | |
1629 | ||
e44d8d47 A |
1630 | switch (cat) { |
1631 | case CATEGORY_NETWORK: | |
1632 | // struct netent | |
1633 | item = (si_item_t *)LI_ils_create("L4488s*44", (unsigned long)si, cat, 1, va, vb, tokens[0], aliases, AF_INET, xnum); | |
1634 | break; | |
1635 | case CATEGORY_PROTOCOL: | |
1636 | case CATEGORY_RPC: | |
1637 | // struct protoent | |
1638 | // struct rpcent | |
1639 | item = (si_item_t *)LI_ils_create("L4488s*4", (unsigned long)si, cat, 1, va, vb, tokens[0], aliases, xnum); | |
1640 | break; | |
1641 | default: | |
1642 | abort(); | |
1643 | } | |
d49d4c81 A |
1644 | |
1645 | free(tokens); | |
1646 | ||
1647 | return item; | |
1648 | } | |
1649 | ||
1650 | static void * | |
e44d8d47 | 1651 | _fsi_get_name_number_aliases(si_mod_t *si, const char *name, int num, int which, int cat) |
d49d4c81 A |
1652 | { |
1653 | char *p, *line; | |
1654 | si_item_t *item; | |
1655 | FILE *f; | |
1656 | si_list_t *all; | |
e44d8d47 A |
1657 | uint64_t va, vb; |
1658 | const char *path; | |
1659 | int vtype; | |
d49d4c81 | 1660 | |
e44d8d47 A |
1661 | switch (cat) { |
1662 | case CATEGORY_NETWORK: | |
1663 | vtype = VALIDATION_NETWORKS; | |
1664 | path = _PATH_NETWORKS; | |
1665 | break; | |
1666 | case CATEGORY_PROTOCOL: | |
1667 | vtype = VALIDATION_PROTOCOLS; | |
1668 | path = _PATH_PROTOCOLS; | |
1669 | break; | |
1670 | case CATEGORY_RPC: | |
1671 | vtype = VALIDATION_RPC; | |
1672 | path = _PATH_RPCS; | |
1673 | break; | |
1674 | default: | |
1675 | abort(); | |
1676 | } | |
d49d4c81 A |
1677 | |
1678 | f = fopen(path, "r"); | |
1679 | if (f == NULL) return NULL; | |
1680 | ||
e44d8d47 | 1681 | _fsi_get_validation(si, vtype, path, f, &va, &vb); |
d49d4c81 A |
1682 | |
1683 | all = NULL; | |
1684 | ||
1685 | forever | |
1686 | { | |
1687 | line = _fsi_get_line(f); | |
1688 | if (line == NULL) break; | |
1689 | ||
1690 | if (line[0] == '#') | |
1691 | { | |
1692 | free(line); | |
1693 | line = NULL; | |
1694 | continue; | |
1695 | } | |
1696 | ||
1697 | p = strchr(line, '#'); | |
1698 | if (p != NULL) *p = '\0'; | |
1699 | ||
e44d8d47 | 1700 | item = _fsi_parse_name_num_aliases(si, name, num, which, line, va, vb, cat); |
d49d4c81 A |
1701 | free(line); |
1702 | line = NULL; | |
1703 | ||
1704 | if (item == NULL) continue; | |
1705 | ||
1706 | if (which == SEL_ALL) | |
1707 | { | |
1708 | all = si_list_add(all, item); | |
1709 | si_item_release(item); | |
1710 | continue; | |
1711 | } | |
1712 | ||
1713 | fclose(f); | |
1714 | return item; | |
1715 | } | |
1716 | ||
1717 | fclose(f); | |
1718 | return all; | |
1719 | } | |
1720 | ||
1721 | /* MOUNT */ | |
1722 | ||
8df84744 A |
1723 | #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) |
1724 | static si_item_t * | |
1725 | _fsi_parse_edt_fs(si_mod_t *si, const char *name, int which, struct edt_fstab *fs, uint64_t va, uint64_t vb) | |
1726 | { | |
1727 | int match; | |
1728 | si_item_t *item; | |
1729 | ||
1730 | if (fs == NULL) return NULL; | |
1731 | ||
1732 | match = 0; | |
1733 | ||
1734 | if (which == SEL_ALL) match = 1; | |
1735 | else if ((which == SEL_NAME) && (string_equal(name, fs->fs_spec))) match = 1; | |
1736 | else if ((which == SEL_NUMBER) && (string_equal(name, fs->fs_file))) match = 1; | |
1737 | ||
1738 | if (match == 0) | |
1739 | { | |
1740 | return NULL; | |
1741 | } | |
1742 | ||
1743 | item = (si_item_t *)LI_ils_create("L4488sssss44", (unsigned long)si, CATEGORY_FS, 1, va, vb, fs->fs_spec, fs->fs_file, fs->fs_vfstype, fs->fs_mntops, fs->fs_type, fs->fs_freq, fs->fs_passno); | |
1744 | ||
1745 | return item; | |
1746 | } | |
1747 | #endif | |
1748 | ||
d49d4c81 | 1749 | static si_item_t * |
e44d8d47 | 1750 | _fsi_parse_fs(si_mod_t *si, const char *name, int which, char *data, uint64_t va, uint64_t vb) |
d49d4c81 A |
1751 | { |
1752 | char **tokens, *tmp, **opts, *fstype; | |
1753 | int ntokens, match, i, freq, passno; | |
1754 | si_item_t *item; | |
1755 | ||
1756 | if (data == NULL) return NULL; | |
1757 | ||
1758 | freq = 0; | |
1759 | passno = 0; | |
1760 | fstype = NULL; | |
1761 | ||
1762 | ntokens = 0; | |
1763 | tokens = _fsi_tokenize(data, " ", 0, &ntokens); | |
1764 | if ((ntokens < 4) || (ntokens > 6)) | |
1765 | { | |
1766 | free(tokens); | |
1767 | return NULL; | |
1768 | } | |
1769 | ||
1770 | if (ntokens >= 5) freq = atoi(tokens[4]); | |
1771 | if (ntokens == 6) passno = atoi(tokens[5]); | |
1772 | ||
1773 | tmp = strdup(tokens[3]); | |
1774 | if (tmp == NULL) | |
1775 | { | |
1776 | free(tokens); | |
1777 | return NULL; | |
1778 | } | |
1779 | ||
1780 | ntokens = 0; | |
1781 | opts = _fsi_tokenize(tmp, ",", 0, &ntokens); | |
1782 | ||
1783 | if (opts == NULL) | |
1784 | { | |
1785 | free(tokens); | |
1786 | free(tmp); | |
1787 | return NULL; | |
1788 | } | |
1789 | ||
1790 | for (i = 0; i < ntokens; i++) | |
1791 | { | |
1792 | if ((string_equal(opts[i], "rw")) || (string_equal(opts[i], "ro")) || (string_equal(opts[i], "sw")) || (string_equal(opts[i], "xx"))) | |
1793 | { | |
1794 | fstype = opts[i]; | |
1795 | break; | |
1796 | } | |
1797 | } | |
1798 | ||
1799 | match = 0; | |
1800 | ||
1801 | if (which == SEL_ALL) match = 1; | |
1802 | else if ((which == SEL_NAME) && (string_equal(name, tokens[0]))) match = 1; | |
1803 | else if ((which == SEL_NUMBER) && (string_equal(name, tokens[1]))) match = 1; | |
1804 | ||
1805 | if (match == 0) | |
1806 | { | |
1807 | free(tokens); | |
1808 | return NULL; | |
1809 | } | |
1810 | ||
e44d8d47 | 1811 | item = (si_item_t *)LI_ils_create("L4488sssss44", (unsigned long)si, CATEGORY_FS, 1, va, vb, tokens[0], tokens[1], tokens[2], tokens[3], (fstype == NULL) ? "rw" : fstype, freq, passno); |
d49d4c81 A |
1812 | |
1813 | free(tokens); | |
1814 | free(opts); | |
1815 | free(tmp); | |
1816 | ||
1817 | return item; | |
1818 | } | |
1819 | ||
1820 | static char * | |
1821 | _fsi_get_device_path(dev_t target_dev) | |
1822 | { | |
1823 | char *result; | |
1824 | char dev[PATH_MAX]; | |
1825 | char *name; | |
1826 | char namebuf[PATH_MAX]; | |
1827 | ||
1828 | result = NULL; | |
1829 | ||
1830 | strlcpy(dev, _PATH_DEV, sizeof(dev)); | |
1831 | ||
1832 | /* The root device in fstab should always be a block special device */ | |
1833 | name = devname_r(target_dev, S_IFBLK, namebuf, sizeof(namebuf)); | |
1834 | if (name == NULL) | |
1835 | { | |
1836 | DIR *dirp; | |
1837 | struct stat devst; | |
1838 | struct dirent *ent, entbuf; | |
1839 | ||
1840 | /* No _PATH_DEVDB. We have to search for it the slow way */ | |
1841 | dirp = opendir(_PATH_DEV); | |
1842 | if (dirp == NULL) return NULL; | |
1843 | ||
1844 | while (readdir_r(dirp, &entbuf, &ent) == 0 && ent != NULL) | |
1845 | { | |
1846 | /* Look for a block special device */ | |
1847 | if (ent->d_type == DT_BLK) | |
1848 | { | |
1849 | strlcat(dev, ent->d_name, sizeof(dev)); | |
1850 | if (stat(dev, &devst) == 0) | |
1851 | { | |
1852 | if (devst.st_rdev == target_dev) { | |
1853 | result = strdup(dev); | |
1854 | break; | |
1855 | } | |
1856 | } | |
1857 | } | |
1858 | ||
1859 | /* reset dev to _PATH_DEV and try again */ | |
1860 | dev[sizeof(_PATH_DEV) - 1] = '\0'; | |
1861 | } | |
e44d8d47 | 1862 | |
d49d4c81 A |
1863 | if (dirp) closedir(dirp); |
1864 | } | |
1865 | else | |
1866 | { | |
1867 | /* We found the _PATH_DEVDB entry */ | |
1868 | strlcat(dev, name, sizeof(dev)); | |
1869 | result = strdup(dev); | |
1870 | } | |
1871 | ||
1872 | return result; | |
1873 | } | |
1874 | ||
1875 | static si_item_t * | |
1876 | _fsi_fs_root(si_mod_t *si) | |
1877 | { | |
e44d8d47 A |
1878 | dispatch_once(&rootfs_once, ^{ |
1879 | struct stat rootstat; | |
1880 | struct statfs rootfsinfo; | |
1881 | char *root_spec; | |
1882 | const char *root_path = "/"; | |
1883 | ||
1884 | if (stat(root_path, &rootstat) < 0) return; | |
1885 | if (statfs(root_path, &rootfsinfo) < 0) return; | |
1886 | ||
1887 | // Check to make sure we're not looking at a synthetic root: | |
1888 | if (string_equal(rootfsinfo.f_fstypename, "synthfs")) { | |
1889 | root_path = "/root"; | |
1890 | if (stat(root_path, &rootstat) < 0) return; | |
1891 | if (statfs(root_path, &rootfsinfo) < 0) return; | |
1892 | } | |
d49d4c81 | 1893 | |
e44d8d47 | 1894 | root_spec = _fsi_get_device_path(rootstat.st_dev); |
ff4fe4c3 A |
1895 | |
1896 | // In case root is mounted from snapshot, _fsi_get_device_path will return NULL as the device name does not comply to | |
1897 | // /dev/diskAAsBB, but in the format of snap@/dev/diskAAsBB, in that case f_mntfromname has the correct device name, so return it | |
1898 | if (root_spec == NULL) { | |
1899 | const char *mntfromname = rootfsinfo.f_mntfromname; | |
1900 | size_t len = sizeof(rootfsinfo.f_mntfromname); | |
1901 | const char *p; | |
1902 | while ((p = strnstr(mntfromname, "@", len))) { | |
1903 | len -= p + 1 - mntfromname; | |
1904 | mntfromname = p + 1; | |
1905 | } | |
1906 | root_spec = strndup(mntfromname, len); | |
1907 | } | |
1908 | ||
e44d8d47 | 1909 | 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); |
53dd3e4a | 1910 | free(root_spec); |
e44d8d47 | 1911 | }); |
d49d4c81 | 1912 | |
e44d8d47 | 1913 | return si_item_retain(rootfs); |
d49d4c81 A |
1914 | } |
1915 | ||
8df84744 A |
1916 | #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) |
1917 | static void * | |
1918 | _fsi_get_edt_fs(si_mod_t *si, const char *name, int which) | |
1919 | { | |
1920 | void *data; | |
1921 | struct edt_fstab *fstab; | |
1922 | size_t i, size; | |
1923 | si_item_t *item; | |
1924 | si_list_t *all; | |
1925 | uint64_t va, vb; | |
1926 | ||
1927 | if ((which != SEL_ALL) && (name == NULL)) return NULL; | |
1928 | ||
1929 | all = NULL; | |
1930 | item = NULL; | |
1931 | fstab = NULL; | |
1932 | i = 0; | |
1933 | size = 0; | |
1934 | ||
1935 | // obtain fstab information from the EDT provided through this sysctl | |
1936 | if (sysctlbyname(APFS_FSTAB_SYSCTL, NULL, &size, NULL, 0) || !size) | |
1937 | { | |
1938 | return all; | |
1939 | } | |
1940 | ||
1941 | fstab = malloc(size); | |
1942 | if (!fstab) | |
1943 | { | |
1944 | return all; | |
1945 | } | |
1946 | ||
1947 | if (sysctlbyname(APFS_FSTAB_SYSCTL, fstab, &size, NULL, 0)) | |
1948 | { | |
1949 | free(fstab); | |
1950 | return all; | |
1951 | } | |
1952 | size = size / sizeof(struct edt_fstab); | |
1953 | ||
1954 | _fsi_get_validation(si, VALIDATION_FSTAB, _PATH_FSTAB, NULL, &va, &vb); | |
1955 | ||
1956 | forever | |
1957 | { | |
1958 | if (i >= size) | |
1959 | { | |
1960 | free(fstab); | |
1961 | break; | |
1962 | } | |
1963 | ||
1964 | data = fstab + i; | |
1965 | i++; | |
1966 | ||
1967 | item = _fsi_parse_edt_fs(si, name, which, data, va, vb); | |
1968 | ||
1969 | if (item == NULL) continue; | |
1970 | ||
1971 | if (which == SEL_ALL) | |
1972 | { | |
1973 | all = si_list_add(all, item); | |
1974 | si_item_release(item); | |
1975 | continue; | |
1976 | } | |
1977 | ||
1978 | return item; | |
1979 | } | |
1980 | ||
1981 | return all; | |
1982 | } | |
1983 | #endif | |
1984 | ||
d49d4c81 A |
1985 | static void * |
1986 | _fsi_get_fs(si_mod_t *si, const char *name, int which) | |
1987 | { | |
1988 | char *line; | |
1989 | si_item_t *item; | |
1990 | FILE *f; | |
1991 | si_list_t *all; | |
e44d8d47 | 1992 | uint64_t va, vb; |
d49d4c81 A |
1993 | int synthesize_root; |
1994 | struct fstab *rfs; | |
1995 | ||
1996 | if ((which != SEL_ALL) && (name == NULL)) return NULL; | |
1997 | ||
1998 | all = NULL; | |
1999 | f = NULL; | |
d49d4c81 A |
2000 | #ifdef SYNTH_ROOTFS |
2001 | synthesize_root = 1; | |
2002 | #else | |
2003 | synthesize_root = 0; | |
2004 | #endif | |
2005 | ||
8df84744 A |
2006 | #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) |
2007 | // We still boot using HFS sometimes (e.g. ramdisks) and therefore | |
2008 | // need to conditionalize using the EDT over the fstab file. | |
2009 | // Certain HFS ramdisks rely on the EDT entries. Prefer the EDT | |
2010 | // over the fstab file, but fall back to use the file upon failure | |
2011 | // to obtain the EDT entries. | |
2012 | struct statfs rootfs; | |
2013 | const char *root_path = "/"; | |
2014 | ||
2015 | if (statfs(root_path, &rootfs)) return NULL; | |
2016 | ||
2017 | all = _fsi_get_edt_fs(si, name, which); | |
2018 | if (all || string_equal(rootfs.f_fstypename, "apfs")) | |
2019 | { | |
2020 | return all; | |
2021 | } | |
2022 | #endif | |
2023 | ||
d49d4c81 A |
2024 | f = fopen(_PATH_FSTAB, "r"); |
2025 | if ((f == NULL) || (synthesize_root == 1)) | |
2026 | { | |
2027 | item = _fsi_fs_root(si); | |
2028 | ||
2029 | rfs = NULL; | |
2030 | if (item != NULL) rfs = (struct fstab *)((uintptr_t)item + sizeof(si_item_t)); | |
2031 | ||
2032 | switch (which) | |
2033 | { | |
2034 | case SEL_NAME: | |
2035 | { | |
2036 | if ((rfs != NULL) && (string_equal(name, rfs->fs_spec))) | |
2037 | { | |
2038 | if (f != NULL) fclose(f); | |
2039 | return item; | |
2040 | } | |
2041 | ||
2042 | break; | |
2043 | } | |
2044 | ||
2045 | case SEL_NUMBER: | |
2046 | { | |
2047 | if ((rfs != NULL) && (string_equal(name, rfs->fs_file))) | |
2048 | { | |
2049 | if (f != NULL) fclose(f); | |
2050 | return item; | |
2051 | } | |
2052 | ||
2053 | break; | |
2054 | } | |
2055 | ||
2056 | case SEL_ALL: | |
2057 | { | |
2058 | all = si_list_add(all, item); | |
2059 | si_item_release(item); | |
2060 | break; | |
2061 | } | |
2062 | } | |
2063 | } | |
2064 | ||
2065 | if (f == NULL) return all; | |
2066 | ||
e44d8d47 | 2067 | _fsi_get_validation(si, VALIDATION_FSTAB, _PATH_FSTAB, f, &va, &vb); |
d49d4c81 A |
2068 | |
2069 | forever | |
2070 | { | |
2071 | line = _fsi_get_line(f); | |
2072 | if (line == NULL) break; | |
2073 | ||
2074 | if (line[0] == '#') | |
2075 | { | |
2076 | free(line); | |
2077 | line = NULL; | |
2078 | continue; | |
2079 | } | |
2080 | ||
e44d8d47 | 2081 | item = _fsi_parse_fs(si, name, which, line, va, vb); |
d49d4c81 A |
2082 | free(line); |
2083 | line = NULL; | |
2084 | ||
2085 | if (item == NULL) continue; | |
2086 | ||
2087 | if (which == SEL_ALL) | |
2088 | { | |
2089 | all = si_list_add(all, item); | |
2090 | si_item_release(item); | |
2091 | continue; | |
2092 | } | |
2093 | ||
2094 | fclose(f); | |
2095 | return item; | |
2096 | } | |
2097 | ||
2098 | fclose(f); | |
2099 | return all; | |
2100 | } | |
2101 | ||
e44d8d47 | 2102 | static int |
d49d4c81 A |
2103 | file_is_valid(si_mod_t *si, si_item_t *item) |
2104 | { | |
d49d4c81 A |
2105 | si_mod_t *src; |
2106 | ||
2107 | if (si == NULL) return 0; | |
2108 | if (item == NULL) return 0; | |
2109 | if (si->name == NULL) return 0; | |
2110 | if (item->src == NULL) return 0; | |
2111 | ||
2112 | src = (si_mod_t *)item->src; | |
2113 | ||
2114 | if (src->name == NULL) return 0; | |
2115 | if (string_not_equal(si->name, src->name)) return 0; | |
2116 | ||
2117 | if (item == rootfs) return 1; | |
2118 | ||
e44d8d47 | 2119 | return _fsi_validate(si, item->type, item->validation_a, item->validation_b); |
d49d4c81 A |
2120 | } |
2121 | ||
e44d8d47 | 2122 | static si_item_t * |
d49d4c81 A |
2123 | file_user_byname(si_mod_t *si, const char *name) |
2124 | { | |
2125 | return _fsi_get_user(si, name, 0, SEL_NAME); | |
2126 | } | |
2127 | ||
e44d8d47 | 2128 | static si_item_t * |
d49d4c81 A |
2129 | file_user_byuid(si_mod_t *si, uid_t uid) |
2130 | { | |
2131 | return _fsi_get_user(si, NULL, uid, SEL_NUMBER); | |
2132 | } | |
2133 | ||
e44d8d47 | 2134 | static si_list_t * |
d49d4c81 A |
2135 | file_user_all(si_mod_t *si) |
2136 | { | |
2137 | return _fsi_get_user(si, NULL, 0, SEL_ALL); | |
2138 | } | |
2139 | ||
e44d8d47 | 2140 | static si_item_t * |
d49d4c81 A |
2141 | file_group_byname(si_mod_t *si, const char *name) |
2142 | { | |
2143 | return _fsi_get_group(si, name, 0, SEL_NAME); | |
2144 | } | |
2145 | ||
e44d8d47 | 2146 | static si_item_t * |
d49d4c81 A |
2147 | file_group_bygid(si_mod_t *si, gid_t gid) |
2148 | { | |
2149 | return _fsi_get_group(si, NULL, gid, SEL_NUMBER); | |
2150 | } | |
2151 | ||
e44d8d47 | 2152 | static si_list_t * |
d49d4c81 A |
2153 | file_group_all(si_mod_t *si) |
2154 | { | |
2155 | return _fsi_get_group(si, NULL, 0, SEL_ALL); | |
2156 | } | |
2157 | ||
e44d8d47 | 2158 | static si_item_t * |
d31dd049 | 2159 | file_grouplist(si_mod_t *si, const char *name, __unused uint32_t ignored) |
d49d4c81 A |
2160 | { |
2161 | return _fsi_get_grouplist(si, name); | |
2162 | } | |
2163 | ||
e44d8d47 A |
2164 | static si_list_t * |
2165 | file_netgroup_byname(si_mod_t *si, const char *name) | |
2166 | { | |
2167 | si_list_t *list = NULL; | |
2168 | si_item_t *item; | |
d31dd049 | 2169 | uint64_t va=0, vb=0; |
e44d8d47 A |
2170 | file_netgroup_t *n; |
2171 | file_si_private_t *pp; | |
2172 | ||
2173 | if (name == NULL) return NULL; | |
2174 | ||
2175 | pp = (file_si_private_t *)si->private; | |
2176 | if (pp == NULL) return NULL; | |
2177 | ||
2178 | _fsi_check_netgroup_cache(si); | |
2179 | ||
2180 | pthread_mutex_lock(&file_mutex); | |
2181 | ||
2182 | n = _fsi_find_netgroup(&(pp->file_netgroup_cache), name, 0); | |
2183 | if (n != NULL) | |
2184 | { | |
2185 | file_netgroup_member_t *m = n->members; | |
2186 | while (m != NULL) | |
2187 | { | |
2188 | item = (si_item_t *)LI_ils_create("L4488sss", (unsigned long)si, CATEGORY_NETGROUP, 1, va, vb, m->host, m->user, m->domain); | |
2189 | list = si_list_add(list, item); | |
2190 | m = m->next; | |
2191 | } | |
2192 | } | |
2193 | ||
2194 | pthread_mutex_unlock(&file_mutex); | |
2195 | ||
2196 | return list; | |
2197 | } | |
2198 | ||
2199 | static int | |
2200 | file_in_netgroup(si_mod_t *si, const char *group, const char *host, const char *user, const char *domain) | |
2201 | { | |
2202 | file_netgroup_t *n; | |
2203 | file_netgroup_member_t *m; | |
2204 | file_si_private_t *pp; | |
2205 | ||
2206 | if (group == NULL) return 0; | |
2207 | ||
2208 | pp = (file_si_private_t *)si->private; | |
2209 | if (pp == NULL) return 0; | |
2210 | ||
2211 | _fsi_check_netgroup_cache(si); | |
2212 | ||
2213 | pthread_mutex_lock(&file_mutex); | |
2214 | ||
2215 | n = _fsi_find_netgroup(&(pp->file_netgroup_cache), group, 0); | |
2216 | if (n == NULL) | |
2217 | { | |
2218 | pthread_mutex_unlock(&file_mutex); | |
2219 | return 0; | |
2220 | } | |
2221 | ||
2222 | m = n->members; | |
2223 | while (m != NULL) | |
2224 | { | |
2225 | file_netgroup_member_t *x = m; | |
2226 | m = m->next; | |
2227 | ||
2228 | if (host != NULL) | |
2229 | { | |
2230 | if (x->host == NULL) continue; | |
2231 | if (strcmp(host, x->host)) continue; | |
2232 | } | |
2233 | ||
2234 | if (user != NULL) | |
2235 | { | |
2236 | if (x->user == NULL) continue; | |
2237 | if (strcmp(user, x->user)) continue; | |
2238 | } | |
2239 | ||
2240 | if (domain != NULL) | |
2241 | { | |
2242 | if (x->domain == NULL) continue; | |
2243 | if (strcmp(domain, x->domain)) continue; | |
2244 | } | |
2245 | ||
2246 | pthread_mutex_unlock(&file_mutex); | |
2247 | return 1; | |
2248 | } | |
2249 | ||
2250 | pthread_mutex_unlock(&file_mutex); | |
2251 | return 0; | |
2252 | } | |
2253 | ||
2254 | static si_item_t * | |
40180321 | 2255 | file_host_byname(si_mod_t *si, const char *name, int af, const char *ignored, uint32_t *err) |
d49d4c81 A |
2256 | { |
2257 | si_item_t *item; | |
2258 | ||
2259 | if (err != NULL) *err = SI_STATUS_NO_ERROR; | |
2260 | ||
2261 | item = _fsi_get_host(si, name, NULL, af, SEL_NAME, err); | |
2262 | if ((item == NULL) && (err != NULL) && (*err == 0)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; | |
2263 | ||
2264 | return item; | |
2265 | } | |
2266 | ||
e44d8d47 | 2267 | static si_item_t * |
40180321 | 2268 | file_host_byaddr(si_mod_t *si, const void *addr, int af, const char *ignored, uint32_t *err) |
d49d4c81 A |
2269 | { |
2270 | si_item_t *item; | |
2271 | ||
2272 | if (err != NULL) *err = SI_STATUS_NO_ERROR; | |
2273 | ||
2274 | item = _fsi_get_host(si, NULL, addr, af, SEL_NUMBER, err); | |
2275 | if ((item == NULL) && (err != NULL) && (*err == 0)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND; | |
2276 | ||
2277 | return item; | |
2278 | } | |
2279 | ||
e44d8d47 | 2280 | static si_list_t * |
d49d4c81 A |
2281 | file_host_all(si_mod_t *si) |
2282 | { | |
2283 | return _fsi_get_host(si, NULL, NULL, 0, SEL_ALL, NULL); | |
2284 | } | |
2285 | ||
e44d8d47 | 2286 | static si_item_t * |
d49d4c81 A |
2287 | file_network_byname(si_mod_t *si, const char *name) |
2288 | { | |
2289 | if (name == NULL) return NULL; | |
e44d8d47 | 2290 | return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_NETWORK); |
d49d4c81 A |
2291 | } |
2292 | ||
e44d8d47 | 2293 | static si_item_t * |
d49d4c81 A |
2294 | file_network_byaddr(si_mod_t *si, uint32_t addr) |
2295 | { | |
e44d8d47 | 2296 | return _fsi_get_name_number_aliases(si, NULL, (int)addr, SEL_NUMBER, CATEGORY_NETWORK); |
d49d4c81 A |
2297 | } |
2298 | ||
e44d8d47 | 2299 | static si_list_t * |
d49d4c81 A |
2300 | file_network_all(si_mod_t *si) |
2301 | { | |
e44d8d47 | 2302 | return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_NETWORK); |
d49d4c81 A |
2303 | } |
2304 | ||
e44d8d47 | 2305 | static si_item_t * |
d49d4c81 A |
2306 | file_service_byname(si_mod_t *si, const char *name, const char *proto) |
2307 | { | |
2308 | return _fsi_get_service(si, name, proto, 0, SEL_NAME); | |
2309 | } | |
2310 | ||
e44d8d47 | 2311 | static si_item_t * |
d49d4c81 A |
2312 | file_service_byport(si_mod_t *si, int port, const char *proto) |
2313 | { | |
2314 | return _fsi_get_service(si, NULL, proto, port, SEL_NUMBER); | |
2315 | } | |
2316 | ||
e44d8d47 | 2317 | static si_list_t * |
d49d4c81 A |
2318 | file_service_all(si_mod_t *si) |
2319 | { | |
2320 | return _fsi_get_service(si, NULL, NULL, 0, SEL_ALL); | |
2321 | } | |
2322 | ||
e44d8d47 | 2323 | static si_item_t * |
d49d4c81 A |
2324 | file_protocol_byname(si_mod_t *si, const char *name) |
2325 | { | |
2326 | if (name == NULL) return NULL; | |
e44d8d47 | 2327 | return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_PROTOCOL); |
d49d4c81 A |
2328 | } |
2329 | ||
e44d8d47 | 2330 | static si_item_t * |
d49d4c81 A |
2331 | file_protocol_bynumber(si_mod_t *si, int number) |
2332 | { | |
e44d8d47 | 2333 | return _fsi_get_name_number_aliases(si, NULL, number, SEL_NUMBER, CATEGORY_PROTOCOL); |
d49d4c81 A |
2334 | } |
2335 | ||
e44d8d47 | 2336 | static si_list_t * |
d49d4c81 A |
2337 | file_protocol_all(si_mod_t *si) |
2338 | { | |
e44d8d47 | 2339 | return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_PROTOCOL); |
d49d4c81 A |
2340 | } |
2341 | ||
e44d8d47 | 2342 | static si_item_t * |
d49d4c81 A |
2343 | file_rpc_byname(si_mod_t *si, const char *name) |
2344 | { | |
2345 | if (name == NULL) return NULL; | |
e44d8d47 | 2346 | return _fsi_get_name_number_aliases(si, name, 0, SEL_NAME, CATEGORY_RPC); |
d49d4c81 A |
2347 | } |
2348 | ||
e44d8d47 | 2349 | static si_item_t * |
d49d4c81 A |
2350 | file_rpc_bynumber(si_mod_t *si, int number) |
2351 | { | |
e44d8d47 | 2352 | return _fsi_get_name_number_aliases(si, NULL, number, SEL_NUMBER, CATEGORY_RPC); |
d49d4c81 A |
2353 | } |
2354 | ||
e44d8d47 | 2355 | static si_list_t * |
d49d4c81 A |
2356 | file_rpc_all(si_mod_t *si) |
2357 | { | |
e44d8d47 | 2358 | return _fsi_get_name_number_aliases(si, NULL, 0, SEL_ALL, CATEGORY_RPC); |
d49d4c81 A |
2359 | } |
2360 | ||
e44d8d47 | 2361 | static si_item_t * |
d49d4c81 A |
2362 | file_fs_byspec(si_mod_t *si, const char *spec) |
2363 | { | |
2364 | return _fsi_get_fs(si, spec, SEL_NAME); | |
2365 | } | |
2366 | ||
e44d8d47 | 2367 | static si_item_t * |
d49d4c81 A |
2368 | file_fs_byfile(si_mod_t *si, const char *file) |
2369 | { | |
2370 | return _fsi_get_fs(si, file, SEL_NUMBER); | |
2371 | } | |
2372 | ||
e44d8d47 | 2373 | static si_list_t * |
d49d4c81 A |
2374 | file_fs_all(si_mod_t *si) |
2375 | { | |
2376 | return _fsi_get_fs(si, NULL, SEL_ALL); | |
2377 | } | |
2378 | ||
e44d8d47 | 2379 | static si_item_t * |
d49d4c81 A |
2380 | file_alias_byname(si_mod_t *si, const char *name) |
2381 | { | |
2382 | return _fsi_get_alias(si, name, SEL_NAME); | |
2383 | } | |
2384 | ||
e44d8d47 | 2385 | static si_list_t * |
d49d4c81 A |
2386 | file_alias_all(si_mod_t *si) |
2387 | { | |
2388 | return _fsi_get_alias(si, NULL, SEL_ALL); | |
2389 | } | |
2390 | ||
e44d8d47 | 2391 | static si_item_t * |
d49d4c81 A |
2392 | file_mac_byname(si_mod_t *si, const char *name) |
2393 | { | |
2394 | return _fsi_get_ether(si, name, SEL_NAME); | |
2395 | } | |
2396 | ||
e44d8d47 | 2397 | static si_item_t * |
d49d4c81 A |
2398 | file_mac_bymac(si_mod_t *si, const char *mac) |
2399 | { | |
2400 | return _fsi_get_ether(si, mac, SEL_NUMBER); | |
2401 | } | |
2402 | ||
e44d8d47 | 2403 | static si_list_t * |
d49d4c81 A |
2404 | file_mac_all(si_mod_t *si) |
2405 | { | |
2406 | return _fsi_get_ether(si, NULL, SEL_ALL); | |
2407 | } | |
2408 | ||
4ffdd164 A |
2409 | static si_list_t * |
2410 | file_addrinfo(si_mod_t *si, const void *node, const void *serv, uint32_t family, uint32_t socktype, uint32_t proto, uint32_t flags, const char *interface, uint32_t *err) | |
2411 | { | |
2412 | if (err != NULL) *err = SI_STATUS_NO_ERROR; | |
2413 | return _gai_simple(si, node, serv, family, socktype, proto, flags, interface, err); | |
2414 | } | |
2415 | ||
e44d8d47 A |
2416 | si_mod_t * |
2417 | si_module_static_file(void) | |
d49d4c81 | 2418 | { |
e44d8d47 A |
2419 | static const struct si_mod_vtable_s file_vtable = |
2420 | { | |
2421 | .sim_is_valid = &file_is_valid, | |
d49d4c81 | 2422 | |
e44d8d47 A |
2423 | .sim_user_byname = &file_user_byname, |
2424 | .sim_user_byuid = &file_user_byuid, | |
d31dd049 | 2425 | .sim_user_byuuid = NULL, |
e44d8d47 | 2426 | .sim_user_all = &file_user_all, |
d49d4c81 | 2427 | |
e44d8d47 A |
2428 | .sim_group_byname = &file_group_byname, |
2429 | .sim_group_bygid = &file_group_bygid, | |
d31dd049 | 2430 | .sim_group_byuuid = NULL, |
e44d8d47 | 2431 | .sim_group_all = &file_group_all, |
d49d4c81 | 2432 | |
e44d8d47 | 2433 | .sim_grouplist = &file_grouplist, |
d49d4c81 | 2434 | |
e44d8d47 A |
2435 | .sim_netgroup_byname = &file_netgroup_byname, |
2436 | .sim_in_netgroup = &file_in_netgroup, | |
d49d4c81 | 2437 | |
e44d8d47 A |
2438 | .sim_alias_byname = &file_alias_byname, |
2439 | .sim_alias_all = &file_alias_all, | |
d49d4c81 | 2440 | |
e44d8d47 A |
2441 | .sim_host_byname = &file_host_byname, |
2442 | .sim_host_byaddr = &file_host_byaddr, | |
2443 | .sim_host_all = &file_host_all, | |
d49d4c81 | 2444 | |
e44d8d47 A |
2445 | .sim_network_byname = &file_network_byname, |
2446 | .sim_network_byaddr = &file_network_byaddr, | |
2447 | .sim_network_all = &file_network_all, | |
d49d4c81 | 2448 | |
e44d8d47 A |
2449 | .sim_service_byname = &file_service_byname, |
2450 | .sim_service_byport = &file_service_byport, | |
2451 | .sim_service_all = &file_service_all, | |
d49d4c81 | 2452 | |
e44d8d47 A |
2453 | .sim_protocol_byname = &file_protocol_byname, |
2454 | .sim_protocol_bynumber = &file_protocol_bynumber, | |
2455 | .sim_protocol_all = &file_protocol_all, | |
d49d4c81 | 2456 | |
e44d8d47 A |
2457 | .sim_rpc_byname = &file_rpc_byname, |
2458 | .sim_rpc_bynumber = &file_rpc_bynumber, | |
2459 | .sim_rpc_all = &file_rpc_all, | |
d49d4c81 | 2460 | |
e44d8d47 A |
2461 | .sim_fs_byspec = &file_fs_byspec, |
2462 | .sim_fs_byfile = &file_fs_byfile, | |
2463 | .sim_fs_all = &file_fs_all, | |
d49d4c81 | 2464 | |
e44d8d47 A |
2465 | .sim_mac_byname = &file_mac_byname, |
2466 | .sim_mac_bymac = &file_mac_bymac, | |
2467 | .sim_mac_all = &file_mac_all, | |
d49d4c81 | 2468 | |
e44d8d47 A |
2469 | .sim_wants_addrinfo = NULL, |
2470 | .sim_addrinfo = &file_addrinfo, | |
d49d4c81 | 2471 | |
e44d8d47 A |
2472 | /* no nameinfo support */ |
2473 | .sim_nameinfo = NULL, | |
2474 | }; | |
d49d4c81 | 2475 | |
e44d8d47 A |
2476 | static si_mod_t si = |
2477 | { | |
2478 | .vers = 1, | |
2479 | .refcount = 1, | |
2480 | .flags = SI_MOD_FLAG_STATIC, | |
d49d4c81 | 2481 | |
e44d8d47 A |
2482 | .private = NULL, |
2483 | .vtable = &file_vtable, | |
2484 | }; | |
d49d4c81 | 2485 | |
e44d8d47 | 2486 | static dispatch_once_t once; |
d49d4c81 | 2487 | |
e44d8d47 A |
2488 | dispatch_once(&once, ^{ |
2489 | si.name = strdup("file"); | |
2490 | file_si_private_t *pp = calloc(1, sizeof(file_si_private_t)); | |
2491 | if (pp != NULL) | |
2492 | { | |
2493 | int i; | |
2494 | for (i = 0; i < VALIDATION_COUNT; i++) pp->notify_token[i] = -1; | |
d49d4c81 | 2495 | |
e44d8d47 | 2496 | /* hardwired for now, but we may want to make this configurable someday */ |
993b5481 | 2497 | pp->validation_notify_mask = VALIDATION_MASK_HOSTS | VALIDATION_MASK_SERVICES | VALIDATION_MASK_PROTOCOLS; |
e44d8d47 | 2498 | } |
d49d4c81 | 2499 | |
e44d8d47 A |
2500 | si.private = pp; |
2501 | }); | |
2502 | ||
2503 | return (si_mod_t *)&si; | |
d49d4c81 | 2504 | } |