2 * Copyright (c) 2008-2015 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <si_module.h>
34 #include <arpa/inet.h>
35 #include <sys/param.h>
36 #include <sys/mount.h>
39 #include <dispatch/dispatch.h>
40 #include <TargetConditionals.h>
41 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
42 #include <sys/sysctl.h>
43 #include <apfs/apfs_sysctl.h>
47 uint32_t notify_peek(int token
, uint32_t *val
);
49 extern uint32_t gL1CacheEnabled
;
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"
55 #define _PATH_NETGROUP "/etc/netgroup"
57 static dispatch_once_t rootfs_once
;
58 static si_item_t
*rootfs
= NULL
;
61 #define FNG_MEM 0x00000010
62 #define FNG_GRP 0x00000020
64 #define forever for(;;)
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
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
93 typedef struct file_netgroup_member_s
99 struct file_netgroup_member_s
*next
;
100 } file_netgroup_member_t
;
102 typedef struct file_netgroup_s
106 file_netgroup_member_t
*members
;
107 struct file_netgroup_s
*next
;
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
;
119 static pthread_mutex_t file_mutex
= PTHREAD_MUTEX_INITIALIZER
;
122 _fsi_copy_string(char *s
)
127 if (s
== NULL
) return NULL
;
131 if (t
== NULL
) return NULL
;
138 _fsi_append_string(char *s
, char **l
)
142 if (s
== NULL
) return l
;
144 for (i
= 0; l
[i
] != NULL
; i
++);
150 l
= (char **) reallocf(l
, (len
+ 2) * sizeof(char *));
151 if (l
== NULL
) return NULL
;
159 _fsi_tokenize(char *data
, const char *sep
, int trailing_empty
, int *ntokens
)
162 int p
, i
, start
, end
, more
, len
, end_on_sep
;
168 if (data
== NULL
) return NULL
;
170 if (ntokens
!= NULL
) *ntokens
= 0;
173 tokens
= _fsi_append_string(data
, tokens
);
174 if (ntokens
!= NULL
) *ntokens
= *ntokens
+ 1;
181 while (data
[p
] != '\0')
184 /* skip leading white space */
185 while ((data
[p
] == ' ') || (data
[p
] == '\t') || (data
[p
] == '\n')) p
++;
187 /* check for end of line */
188 if (data
[p
] == '\0') break;
190 /* scan for separator */
196 while (scanning
== 1)
198 if (data
[p
] == '\0') break;
200 for (i
= 0; i
< len
; i
++)
202 if (data
[p
] == sep
[i
])
210 /* end is last non-whitespace character */
211 if ((scanning
== 1) && (data
[p
] != ' ') && (data
[p
] != '\t') && (data
[p
] != '\n')) end
= p
;
216 /* see if there's data left after p */
218 if (data
[p
] != '\0') more
= 1;
220 /* set the character following the token to nul */
221 if (start
== p
) data
[p
] = '\0';
222 else data
[end
+ 1] = '\0';
224 tokens
= _fsi_append_string(data
+ start
, tokens
);
225 if (ntokens
!= NULL
) *ntokens
= *ntokens
+ 1;
229 if ((end_on_sep
== 1) && (trailing_empty
!= 0))
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;
240 _fsi_get_line(FILE *fp
)
247 x
= fgets(s
, sizeof(s
), fp
);
248 if ((x
== NULL
) || (s
[0] == '\0')) return NULL
;
250 if (s
[0] != '#') s
[strlen(s
) - 1] = '\0';
252 out
= _fsi_copy_string(s
);
257 _fsi_validation_path(int vtype
)
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
;
276 _fsi_get_validation(si_mod_t
*si
, int vtype
, const char *path
, FILE *f
, uint64_t *a
, uint64_t *b
)
279 file_si_private_t
*pp
;
283 if (a
!= NULL
) *a
= 0;
284 if (b
!= NULL
) *b
= 0;
286 if (si
== NULL
) return;
287 if (path
== NULL
) return;
288 if (gL1CacheEnabled
== 0) return;
290 pp
= (file_si_private_t
*)si
->private;
291 if (pp
== NULL
) return;
293 if (vtype
>= VALIDATION_COUNT
) return;
296 if (bit
& pp
->validation_notify_mask
)
298 /* use notify validation for this type */
299 if (pp
->notify_token
[vtype
] < 0)
302 asprintf(&str
, "com.apple.system.info:%s", path
);
303 if (str
== NULL
) return;
305 status
= notify_register_check(str
, &(pp
->notify_token
[vtype
]));
311 status
= notify_peek(pp
->notify_token
[vtype
], &peek
);
312 if (status
== NOTIFY_STATUS_OK
) *a
= ntohl(peek
);
315 if (b
!= NULL
) *b
= vtype
;
319 /* use stat() and last mod time for this type */
320 memset(&sb
, 0, sizeof(struct stat
));
323 if (fstat(fileno(f
), &sb
) == 0)
325 if (a
!= NULL
) *a
= sb
.st_mtimespec
.tv_sec
;
326 if (b
!= NULL
) *b
= sb
.st_mtimespec
.tv_nsec
;
331 path
= _fsi_validation_path(vtype
);
334 memset(&sb
, 0, sizeof(struct stat
));
335 if (stat(path
, &sb
) == 0)
337 if (a
!= NULL
) *a
= sb
.st_mtimespec
.tv_sec
;
338 if (b
!= NULL
) *b
= sb
.st_mtimespec
.tv_nsec
;
346 _fsi_validate(si_mod_t
*si
, int cat
, uint64_t va
, uint64_t vb
)
348 #if !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
351 uint32_t item_val
, curr_val
, vtype
;
352 file_si_private_t
*pp
;
356 if (si
== NULL
) return 0;
358 #if !(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
359 /* /etc is on a read-only filesystem, so no validation is required */
361 pp
= (file_si_private_t
*)si
->private;
362 if (pp
== NULL
) return 0;
369 if (geteuid() == 0) vtype
= VALIDATION_MASTER_PASSWD
;
370 else vtype
= VALIDATION_PASSWD
;
375 vtype
= VALIDATION_GROUP
;
378 case CATEGORY_GROUPLIST
:
380 vtype
= VALIDATION_GROUP
;
383 case CATEGORY_NETGROUP
:
385 vtype
= VALIDATION_NETGROUP
;
390 vtype
= VALIDATION_ALIASES
;
393 case CATEGORY_HOST_IPV4
:
395 vtype
= VALIDATION_HOSTS
;
398 case CATEGORY_HOST_IPV6
:
400 vtype
= VALIDATION_HOSTS
;
403 case CATEGORY_NETWORK
:
405 vtype
= VALIDATION_NETWORKS
;
408 case CATEGORY_SERVICE
:
410 vtype
= VALIDATION_SERVICES
;
413 case CATEGORY_PROTOCOL
:
415 vtype
= VALIDATION_PROTOCOLS
;
420 vtype
= VALIDATION_RPC
;
425 vtype
= VALIDATION_FSTAB
;
430 vtype
= VALIDATION_ETHERS
;
436 if (pp
->notify_token
[vtype
] < 0)
438 path
= _fsi_validation_path(vtype
);
439 if (path
== NULL
) return 0;
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;
450 status
= notify_peek(pp
->notify_token
[vtype
], &curr_val
);
451 if (status
!= NOTIFY_STATUS_OK
) return 0;
453 curr_val
= ntohl(curr_val
);
454 if (item_val
!= curr_val
) return 0;
461 /* netgroup support */
463 _fsi_append_char_to_line(char c
, char *buf
, size_t *x
)
465 if (x
== NULL
) return NULL
;
467 if (buf
== NULL
) *x
= 0;
469 if ((*x
% CHUNK
) == 0)
471 buf
= reallocf(buf
, *x
+ CHUNK
);
472 if (buf
== NULL
) return NULL
;
474 memset(buf
+ *x
, 0, CHUNK
);
484 _fsi_read_netgroup_line(FILE *f
)
491 if (f
== NULL
) return NULL
;
498 if (out
== NULL
) return NULL
;
499 return _fsi_append_char_to_line('\0', out
, &x
);
502 if (c
== '\n') return _fsi_append_char_to_line('\0', out
, &x
);
503 if (c
== '(') paren
= 1;
504 else if (c
== ')') paren
= 0;
506 if ((c
== ' ') || (c
== '\t'))
508 if ((white
== 0) && (paren
== 0)) out
= _fsi_append_char_to_line(' ', out
, &x
);
516 if (c
== EOF
) return _fsi_append_char_to_line('\0', out
, &x
);
517 if (c
== '\n') break;
522 out
= _fsi_append_char_to_line(c
, out
, &x
);
528 static file_netgroup_t
*
529 _fsi_find_netgroup(file_netgroup_t
**list
, const char *name
, int create
)
533 if (list
== NULL
) return NULL
;
535 for (n
= *list
; n
!= NULL
; n
= n
->next
)
537 if (!strcmp(name
, n
->name
)) return n
;
540 if (create
== 0) return NULL
;
542 n
= (file_netgroup_t
*)calloc(1, sizeof(file_netgroup_t
));
543 if (n
== NULL
) return NULL
;
545 n
->name
= strdup(name
);
553 _fsi_free_file_netgroup(file_netgroup_t
*n
)
555 file_netgroup_member_t
*m
;
557 if (n
== NULL
) return;
563 file_netgroup_member_t
*x
= m
;
575 _fsi_add_netgroup_group(file_netgroup_t
*n
, char *grp
)
577 file_netgroup_member_t
*g
;
579 if (n
== NULL
) return;
581 g
= (file_netgroup_member_t
*)calloc(1, sizeof(file_netgroup_member_t
));
582 if (g
== NULL
) return;
585 g
->host
= strdup(grp
);
587 g
->next
= n
->members
;
594 _fsi_add_netgroup_member(file_netgroup_t
*n
, char *mem
)
597 file_netgroup_member_t
*m
;
600 if (n
== NULL
) return;
602 m
= (file_netgroup_member_t
*)calloc(1, sizeof(file_netgroup_member_t
));
603 if (m
== NULL
) return;
605 tokens
= _fsi_tokenize(mem
+ 1, ",)", 0, &ntokens
);
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]);
620 m
->next
= n
->members
;
624 static file_netgroup_t
*
625 _fsi_process_netgroup_line(file_netgroup_t
**pass1
, char *line
)
631 tokens
= _fsi_tokenize(line
, " ", 0, &ntokens
);
632 if (tokens
== NULL
) return NULL
;
633 if (tokens
[0] == NULL
)
639 n
= _fsi_find_netgroup(pass1
, tokens
[0], 1);
641 for (i
= 1; tokens
[i
] != NULL
; i
++)
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
]);
652 _fsi_flatten_netgroup(file_netgroup_t
*pass1
, file_netgroup_t
**top
, file_netgroup_t
*n
, file_netgroup_member_t
*m
)
654 if (n
== NULL
) return;
656 if (n
->flags
== 1) return;
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
)
674 if (m
->flags
& FNG_MEM
)
676 file_netgroup_member_t
*x
= (file_netgroup_member_t
*)calloc(1, sizeof(file_netgroup_member_t
));
677 if (x
== NULL
) return;
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
);
684 x
->next
= (*top
)->members
;
689 file_netgroup_t
*g
= _fsi_find_netgroup(&pass1
, m
->host
, 0);
690 if (g
== NULL
) continue;
692 _fsi_flatten_netgroup(pass1
, top
, g
, g
->members
);
700 _fsi_check_netgroup_cache(si_mod_t
*si
)
702 file_netgroup_t
*p1
, *n
, *x
, *a
;
705 file_si_private_t
*pp
;
707 if (si
== NULL
) return;
709 pp
= (file_si_private_t
*)si
->private;
710 if (pp
== NULL
) return;
712 pthread_mutex_lock(&file_mutex
);
714 if (_fsi_validate(si
, CATEGORY_NETGROUP
, pp
->netgroup_validation_a
, pp
->netgroup_validation_b
))
716 pthread_mutex_unlock(&file_mutex
);
720 n
= pp
->file_netgroup_cache
;
725 _fsi_free_file_netgroup(x
);
728 pp
->file_netgroup_cache
= NULL
;
730 f
= fopen(_PATH_NETGROUP
, "r");
733 pthread_mutex_unlock(&file_mutex
);
737 _fsi_get_validation(si
, VALIDATION_NETGROUP
, _PATH_NETGROUP
, f
, &(pp
->netgroup_validation_a
), &(pp
->netgroup_validation_b
));
741 line
= _fsi_read_netgroup_line(f
);
744 n
= _fsi_process_netgroup_line(&p1
, line
);
747 line
= _fsi_read_netgroup_line(f
);
752 for (n
= p1
; n
!= NULL
; n
= n
->next
)
755 _fsi_flatten_netgroup(p1
, &a
, n
, n
->members
);
756 for (x
= p1
; x
!= NULL
; x
= x
->next
) x
->flags
= 0;
760 a
->next
= pp
->file_netgroup_cache
;
761 pp
->file_netgroup_cache
= a
;
770 _fsi_free_file_netgroup(x
);
773 pthread_mutex_unlock(&file_mutex
);
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
)
783 time_t change
, expire
;
787 if (data
== NULL
) return NULL
;
790 tokens
= _fsi_tokenize(data
, ":", 1, &ntokens
);
791 if (((format
== 0) && (ntokens
!= 10)) || ((format
== 1) && (ntokens
!= 7)))
797 xuid
= atoi(tokens
[2]);
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;
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] */
815 change
= atoi(tokens
[5]);
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
);
821 /* passwd: name[0] passwd[1] uid[2] gid[3] gecos[4] dir[5] shell[6] */
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);
831 _fsi_get_user(si_mod_t
*si
, const char *name
, uid_t uid
, int which
)
840 if ((which
== SEL_NAME
) && (name
== NULL
)) return NULL
;
850 f
= fopen(_PATH_MASTERPASSWD
, "r");
851 _fsi_get_validation(si
, VALIDATION_MASTER_PASSWD
, _PATH_MASTERPASSWD
, f
, &va
, &vb
);
855 f
= fopen(_PATH_PASSWD
, "r");
856 _fsi_get_validation(si
, VALIDATION_PASSWD
, _PATH_PASSWD
, f
, &va
, &vb
);
860 if (f
== NULL
) return NULL
;
865 line
= _fsi_get_line(f
);
866 if (line
== NULL
) break;
875 item
= _fsi_parse_user(si
, name
, uid
, which
, line
, fmt
, va
, vb
);
879 if (item
== NULL
) continue;
881 if (which
== SEL_ALL
)
883 all
= si_list_add(all
, item
);
884 si_item_release(item
);
898 _fsi_parse_group(si_mod_t
*si
, const char *name
, gid_t gid
, int which
, char *data
, uint64_t va
, uint64_t vb
)
900 char **tokens
, **members
;
905 if (data
== NULL
) return NULL
;
908 tokens
= _fsi_tokenize(data
, ":", 1, &ntokens
);
915 xgid
= atoi(tokens
[2]);
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;
929 members
= _fsi_tokenize(tokens
[3], ",", 1, &ntokens
);
931 item
= (si_item_t
*)LI_ils_create("L4488ss4*", (unsigned long)si
, CATEGORY_GROUP
, 1, va
, vb
, tokens
[0], tokens
[1], xgid
, members
);
940 _fsi_get_group(si_mod_t
*si
, const char *name
, gid_t gid
, int which
)
948 if ((which
== SEL_NAME
) && (name
== NULL
)) return NULL
;
953 f
= fopen(_PATH_GROUP
, "r");
954 if (f
== NULL
) return NULL
;
956 _fsi_get_validation(si
, VALIDATION_GROUP
, _PATH_GROUP
, f
, &va
, &vb
);
960 line
= _fsi_get_line(f
);
961 if (line
== NULL
) break;
970 item
= _fsi_parse_group(si
, name
, gid
, which
, line
, va
, vb
);
974 if (item
== NULL
) continue;
976 if (which
== SEL_ALL
)
978 all
= si_list_add(all
, item
);
979 si_item_release(item
);
992 _fsi_get_grouplist(si_mod_t
*si
, const char *user
)
994 char **tokens
, **members
;
995 int ntokens
, i
, match
, gidcount
;
1004 if (user
== NULL
) return NULL
;
1011 item
= si
->vtable
->sim_user_byname(si
, user
);
1014 pw
= (struct passwd
*)((uintptr_t)item
+ sizeof(si_item_t
));
1015 basegid
= pw
->pw_gid
;
1016 si_item_release(item
);
1020 f
= fopen(_PATH_GROUP
, "r");
1021 if (f
== NULL
) return NULL
;
1023 _fsi_get_validation(si
, VALIDATION_GROUP
, _PATH_GROUP
, f
, &va
, &vb
);
1027 line
= _fsi_get_line(f
);
1028 if (line
== NULL
) break;
1038 tokens
= _fsi_tokenize(line
, ":", 1, &ntokens
);
1046 members
= _fsi_tokenize(tokens
[3], ",", 1, &ntokens
);
1051 for (i
= 0; i
< ntokens
; i
++)
1053 if (string_equal(user
, members
[i
]))
1055 gid
= atoi(tokens
[2]);
1068 gidlist
= (gid_t
*) reallocf(gidlist
, (gidcount
+ 1) * sizeof(gid_t
));
1069 if (gidlist
== NULL
)
1075 gidlist
[gidcount
++] = gid
;
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
);
1094 _fsi_parse_alias(si_mod_t
*si
, const char *name
, int which
, char *data
, uint64_t va
, uint64_t vb
)
1096 char **tokens
, **members
;
1100 if (data
== NULL
) return NULL
;
1103 tokens
= _fsi_tokenize(data
, ":", 1, &ntokens
);
1112 if (which
== SEL_ALL
) match
= 1;
1113 else if (string_equal(name
, tokens
[0])) match
= 1;
1122 members
= _fsi_tokenize(tokens
[1], ",", 1, &ntokens
);
1124 item
= (si_item_t
*)LI_ils_create("L4488s4*4", (unsigned long)si
, CATEGORY_ALIAS
, 1, va
, vb
, tokens
[0], ntokens
, members
, 1);
1133 _fsi_get_alias(si_mod_t
*si
, const char *name
, int which
)
1141 if ((which
== SEL_NAME
) && (name
== NULL
)) return NULL
;
1146 f
= fopen(_PATH_ALIASES
, "r");
1147 if (f
== NULL
) return NULL
;
1149 _fsi_get_validation(si
, VALIDATION_ALIASES
, _PATH_ALIASES
, f
, &va
, &vb
);
1153 line
= _fsi_get_line(f
);
1154 if (line
== NULL
) break;
1163 item
= _fsi_parse_alias(si
, name
, which
, line
, va
, vb
);
1167 if (item
== NULL
) continue;
1169 if (which
== SEL_ALL
)
1171 all
= si_list_add(all
, item
);
1172 si_item_release(item
);
1187 _fsi_parse_ether(si_mod_t
*si
, const char *name
, int which
, char *data
, uint64_t va
, uint64_t vb
)
1194 if (data
== NULL
) return NULL
;
1197 tokens
= _fsi_tokenize(data
, " \t", 1, &ntokens
);
1204 cmac
= si_standardize_mac_address(tokens
[0]);
1212 if (which
== SEL_ALL
) match
= 1;
1213 else if ((which
== SEL_NAME
) && (string_equal(name
, tokens
[1]))) match
= 1;
1214 else if ((which
== SEL_NUMBER
) && (string_equal(name
, cmac
))) match
= 1;
1223 item
= (si_item_t
*)LI_ils_create("L4488ss", (unsigned long)si
, CATEGORY_MAC
, 1, va
, vb
, tokens
[1], cmac
);
1232 _fsi_get_ether(si_mod_t
*si
, const char *name
, int which
)
1240 if ((which
!= SEL_ALL
) && (name
== NULL
)) return NULL
;
1243 if (which
== SEL_NUMBER
)
1245 cmac
= si_standardize_mac_address(name
);
1246 if (cmac
== NULL
) return NULL
;
1252 f
= fopen(_PATH_ETHERS
, "r");
1253 if (f
== NULL
) return NULL
;
1255 _fsi_get_validation(si
, VALIDATION_ETHERS
, _PATH_ETHERS
, f
, &va
, &vb
);
1259 line
= _fsi_get_line(f
);
1260 if (line
== NULL
) break;
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
);
1276 if (item
== NULL
) continue;
1278 if (which
== SEL_ALL
)
1280 all
= si_list_add(all
, item
);
1281 si_item_release(item
);
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
)
1298 char **tokens
, **h_aliases
, *null_alias
;
1299 int i
, ntokens
, match
, h_addrtype
, h_length
;
1303 char *h_addr_list
[2];
1304 char h_addr_4
[4], h_addr_6
[16];
1306 if (data
== NULL
) return NULL
;
1311 tokens
= _fsi_tokenize(data
, " ", 0, &ntokens
);
1318 h_addr_list
[1] = NULL
;
1320 h_addrtype
= AF_UNSPEC
;
1321 if (inet_pton(AF_INET
, tokens
[0], &a4
) == 1)
1323 h_addrtype
= AF_INET
;
1324 h_length
= sizeof(struct in_addr
);
1325 memcpy(h_addr_4
, &a4
, 4);
1326 h_addr_list
[0] = h_addr_4
;
1328 else if (inet_pton(AF_INET6
, tokens
[0], &a6
) == 1)
1330 h_addrtype
= AF_INET6
;
1331 h_length
= sizeof(struct in6_addr
);
1332 memcpy(h_addr_6
, &a6
, 16);
1333 h_addr_list
[0] = h_addr_6
;
1336 if (h_addrtype
== AF_UNSPEC
)
1343 if (ntokens
> 2) h_aliases
= &(tokens
[2]);
1347 if (which
== SEL_ALL
) match
= 1;
1350 if (h_addrtype
== af
)
1352 if (which
== SEL_NAME
)
1354 if (string_equal(name
, tokens
[1])) match
= 1;
1355 else if (h_aliases
!= NULL
)
1357 for (i
= 0; (h_aliases
[i
] != NULL
) && (match
== 0); i
++)
1358 if (string_equal(name
, h_aliases
[i
])) match
= 1;
1361 else if (which
== SEL_NUMBER
)
1363 if (memcmp(addr
, h_addr_list
[0], h_length
) == 0) match
= 1;
1376 if (h_aliases
== NULL
) h_aliases
= &null_alias
;
1378 if (h_addrtype
== AF_INET
)
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
);
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
);
1393 _fsi_get_host(si_mod_t
*si
, const char *name
, const void *addr
, int af
, int which
, uint32_t *err
)
1401 if ((which
== SEL_NAME
) && (name
== NULL
))
1403 if (err
!= NULL
) *err
= NO_RECOVERY
;
1407 if ((which
== SEL_NUMBER
) && (addr
== NULL
))
1409 if (err
!= NULL
) *err
= NO_RECOVERY
;
1413 f
= fopen(_PATH_HOSTS
, "r");
1416 if (err
!= NULL
) *err
= NO_RECOVERY
;
1420 _fsi_get_validation(si
, VALIDATION_HOSTS
, _PATH_HOSTS
, f
, &va
, &vb
);
1426 line
= _fsi_get_line(f
);
1427 if (line
== NULL
) break;
1436 item
= _fsi_parse_host(si
, name
, addr
, af
, which
, line
, va
, vb
);
1440 if (item
== NULL
) continue;
1442 if (which
== SEL_ALL
)
1444 all
= si_list_add(all
, item
);
1445 si_item_release(item
);
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
)
1462 char **tokens
, **s_aliases
, *xproto
;
1463 int i
, ntokens
, match
;
1467 if (data
== NULL
) return NULL
;
1472 tokens
= _fsi_tokenize(data
, " ", 0, &ntokens
);
1480 if (ntokens
> 2) s_aliases
= &(tokens
[2]);
1482 xport
= atoi(tokens
[1]);
1484 xproto
= strchr(tokens
[1], '/');
1493 if ((proto
!= NULL
) && (string_not_equal(proto
, xproto
)))
1500 if (which
== SEL_ALL
) match
= 1;
1501 else if (which
== SEL_NAME
)
1503 if (string_equal(name
, tokens
[0])) match
= 1;
1504 else if (s_aliases
!= NULL
)
1506 for (i
= 0; (s_aliases
[i
] != NULL
) && (match
== 0); i
++)
1507 if (string_equal(name
, s_aliases
[i
])) match
= 1;
1510 else if ((which
== SEL_NUMBER
) && (port
== xport
)) match
= 1;
1518 /* strange but correct */
1519 xport
= htons(xport
);
1521 item
= (si_item_t
*)LI_ils_create("L4488s*4s", (unsigned long)si
, CATEGORY_SERVICE
, 1, va
, vb
, tokens
[0], s_aliases
, xport
, xproto
);
1529 _fsi_get_service(si_mod_t
*si
, const char *name
, const char *proto
, int port
, int which
)
1537 if ((which
== SEL_NAME
) && (name
== NULL
)) return NULL
;
1538 if ((which
== SEL_NUMBER
) && (port
== 0)) return NULL
;
1540 f
= fopen(_PATH_SERVICES
, "r");
1541 if (f
== NULL
) return NULL
;
1543 _fsi_get_validation(si
, VALIDATION_SERVICES
, _PATH_SERVICES
, f
, &va
, &vb
);
1549 line
= _fsi_get_line(f
);
1550 if (line
== NULL
) break;
1559 p
= strchr(line
, '#');
1560 if (p
!= NULL
) *p
= '\0';
1562 item
= _fsi_parse_service(si
, name
, proto
, port
, which
, line
, va
, vb
);
1566 if (item
== NULL
) continue;
1568 if (which
== SEL_ALL
)
1570 all
= si_list_add(all
, item
);
1571 si_item_release(item
);
1584 * Generic name/number/aliases lookup
1585 * Works for protocols, networks, and rpcs
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
)
1591 char **tokens
, **aliases
;
1592 int i
, ntokens
, match
, xnum
;
1595 if (data
== NULL
) return NULL
;
1598 tokens
= _fsi_tokenize(data
, " ", 0, &ntokens
);
1605 xnum
= atoi(tokens
[1]);
1608 if (ntokens
> 2) aliases
= &(tokens
[2]);
1612 if (which
== SEL_ALL
) match
= 1;
1613 else if (which
== SEL_NAME
)
1615 if (string_equal(name
, tokens
[0])) match
= 1;
1616 else if (aliases
!= NULL
)
1618 for (i
= 0; (aliases
[i
] != NULL
) && (match
== 0); i
++)
1619 if (string_equal(name
, aliases
[i
])) match
= 1;
1622 else if ((which
== SEL_NUMBER
) && (num
== xnum
)) match
= 1;
1631 case CATEGORY_NETWORK
:
1633 item
= (si_item_t
*)LI_ils_create("L4488s*44", (unsigned long)si
, cat
, 1, va
, vb
, tokens
[0], aliases
, AF_INET
, xnum
);
1635 case CATEGORY_PROTOCOL
:
1639 item
= (si_item_t
*)LI_ils_create("L4488s*4", (unsigned long)si
, cat
, 1, va
, vb
, tokens
[0], aliases
, xnum
);
1651 _fsi_get_name_number_aliases(si_mod_t
*si
, const char *name
, int num
, int which
, int cat
)
1662 case CATEGORY_NETWORK
:
1663 vtype
= VALIDATION_NETWORKS
;
1664 path
= _PATH_NETWORKS
;
1666 case CATEGORY_PROTOCOL
:
1667 vtype
= VALIDATION_PROTOCOLS
;
1668 path
= _PATH_PROTOCOLS
;
1671 vtype
= VALIDATION_RPC
;
1678 f
= fopen(path
, "r");
1679 if (f
== NULL
) return NULL
;
1681 _fsi_get_validation(si
, vtype
, path
, f
, &va
, &vb
);
1687 line
= _fsi_get_line(f
);
1688 if (line
== NULL
) break;
1697 p
= strchr(line
, '#');
1698 if (p
!= NULL
) *p
= '\0';
1700 item
= _fsi_parse_name_num_aliases(si
, name
, num
, which
, line
, va
, vb
, cat
);
1704 if (item
== NULL
) continue;
1706 if (which
== SEL_ALL
)
1708 all
= si_list_add(all
, item
);
1709 si_item_release(item
);
1723 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
1725 _fsi_parse_edt_fs(si_mod_t
*si
, const char *name
, int which
, struct edt_fstab
*fs
, uint64_t va
, uint64_t vb
)
1730 if (fs
== NULL
) return NULL
;
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;
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
);
1750 _fsi_parse_fs(si_mod_t
*si
, const char *name
, int which
, char *data
, uint64_t va
, uint64_t vb
)
1752 char **tokens
, *tmp
, **opts
, *fstype
;
1753 int ntokens
, match
, i
, freq
, passno
;
1756 if (data
== NULL
) return NULL
;
1763 tokens
= _fsi_tokenize(data
, " ", 0, &ntokens
);
1764 if ((ntokens
< 4) || (ntokens
> 6))
1770 if (ntokens
>= 5) freq
= atoi(tokens
[4]);
1771 if (ntokens
== 6) passno
= atoi(tokens
[5]);
1773 tmp
= strdup(tokens
[3]);
1781 opts
= _fsi_tokenize(tmp
, ",", 0, &ntokens
);
1790 for (i
= 0; i
< ntokens
; i
++)
1792 if ((string_equal(opts
[i
], "rw")) || (string_equal(opts
[i
], "ro")) || (string_equal(opts
[i
], "sw")) || (string_equal(opts
[i
], "xx")))
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;
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
);
1821 _fsi_get_device_path(dev_t target_dev
)
1826 char namebuf
[PATH_MAX
];
1830 strlcpy(dev
, _PATH_DEV
, sizeof(dev
));
1832 /* The root device in fstab should always be a block special device */
1833 name
= devname_r(target_dev
, S_IFBLK
, namebuf
, sizeof(namebuf
));
1838 struct dirent
*ent
, entbuf
;
1840 /* No _PATH_DEVDB. We have to search for it the slow way */
1841 dirp
= opendir(_PATH_DEV
);
1842 if (dirp
== NULL
) return NULL
;
1844 while (readdir_r(dirp
, &entbuf
, &ent
) == 0 && ent
!= NULL
)
1846 /* Look for a block special device */
1847 if (ent
->d_type
== DT_BLK
)
1849 strlcat(dev
, ent
->d_name
, sizeof(dev
));
1850 if (stat(dev
, &devst
) == 0)
1852 if (devst
.st_rdev
== target_dev
) {
1853 result
= strdup(dev
);
1859 /* reset dev to _PATH_DEV and try again */
1860 dev
[sizeof(_PATH_DEV
) - 1] = '\0';
1863 if (dirp
) closedir(dirp
);
1867 /* We found the _PATH_DEVDB entry */
1868 strlcat(dev
, name
, sizeof(dev
));
1869 result
= strdup(dev
);
1876 _fsi_fs_root(si_mod_t
*si
)
1878 dispatch_once(&rootfs_once
, ^{
1879 struct stat rootstat
;
1880 struct statfs rootfsinfo
;
1882 const char *root_path
= "/";
1884 if (stat(root_path
, &rootstat
) < 0) return;
1885 if (statfs(root_path
, &rootfsinfo
) < 0) return;
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;
1894 root_spec
= _fsi_get_device_path(rootstat
.st_dev
);
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
);
1902 while ((p
= strnstr(mntfromname
, "@", len
))) {
1903 len
-= p
+ 1 - mntfromname
;
1904 mntfromname
= p
+ 1;
1906 root_spec
= strndup(mntfromname
, len
);
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);
1913 return si_item_retain(rootfs
);
1916 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
1918 _fsi_get_edt_fs(si_mod_t
*si
, const char *name
, int which
)
1921 struct edt_fstab
*fstab
;
1927 if ((which
!= SEL_ALL
) && (name
== NULL
)) return NULL
;
1935 // obtain fstab information from the EDT provided through this sysctl
1936 if (sysctlbyname(APFS_FSTAB_SYSCTL
, NULL
, &size
, NULL
, 0) || !size
)
1941 fstab
= malloc(size
);
1947 if (sysctlbyname(APFS_FSTAB_SYSCTL
, fstab
, &size
, NULL
, 0))
1952 size
= size
/ sizeof(struct edt_fstab
);
1954 _fsi_get_validation(si
, VALIDATION_FSTAB
, _PATH_FSTAB
, NULL
, &va
, &vb
);
1967 item
= _fsi_parse_edt_fs(si
, name
, which
, data
, va
, vb
);
1969 if (item
== NULL
) continue;
1971 if (which
== SEL_ALL
)
1973 all
= si_list_add(all
, item
);
1974 si_item_release(item
);
1986 _fsi_get_fs(si_mod_t
*si
, const char *name
, int which
)
1993 int synthesize_root
;
1996 if ((which
!= SEL_ALL
) && (name
== NULL
)) return NULL
;
2001 synthesize_root
= 1;
2003 synthesize_root
= 0;
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
= "/";
2015 if (statfs(root_path
, &rootfs
)) return NULL
;
2017 all
= _fsi_get_edt_fs(si
, name
, which
);
2018 if (all
|| string_equal(rootfs
.f_fstypename
, "apfs"))
2024 f
= fopen(_PATH_FSTAB
, "r");
2025 if ((f
== NULL
) || (synthesize_root
== 1))
2027 item
= _fsi_fs_root(si
);
2030 if (item
!= NULL
) rfs
= (struct fstab
*)((uintptr_t)item
+ sizeof(si_item_t
));
2036 if ((rfs
!= NULL
) && (string_equal(name
, rfs
->fs_spec
)))
2038 if (f
!= NULL
) fclose(f
);
2047 if ((rfs
!= NULL
) && (string_equal(name
, rfs
->fs_file
)))
2049 if (f
!= NULL
) fclose(f
);
2058 all
= si_list_add(all
, item
);
2059 si_item_release(item
);
2065 if (f
== NULL
) return all
;
2067 _fsi_get_validation(si
, VALIDATION_FSTAB
, _PATH_FSTAB
, f
, &va
, &vb
);
2071 line
= _fsi_get_line(f
);
2072 if (line
== NULL
) break;
2081 item
= _fsi_parse_fs(si
, name
, which
, line
, va
, vb
);
2085 if (item
== NULL
) continue;
2087 if (which
== SEL_ALL
)
2089 all
= si_list_add(all
, item
);
2090 si_item_release(item
);
2103 file_is_valid(si_mod_t
*si
, si_item_t
*item
)
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;
2112 src
= (si_mod_t
*)item
->src
;
2114 if (src
->name
== NULL
) return 0;
2115 if (string_not_equal(si
->name
, src
->name
)) return 0;
2117 if (item
== rootfs
) return 1;
2119 return _fsi_validate(si
, item
->type
, item
->validation_a
, item
->validation_b
);
2123 file_user_byname(si_mod_t
*si
, const char *name
)
2125 return _fsi_get_user(si
, name
, 0, SEL_NAME
);
2129 file_user_byuid(si_mod_t
*si
, uid_t uid
)
2131 return _fsi_get_user(si
, NULL
, uid
, SEL_NUMBER
);
2135 file_user_all(si_mod_t
*si
)
2137 return _fsi_get_user(si
, NULL
, 0, SEL_ALL
);
2141 file_group_byname(si_mod_t
*si
, const char *name
)
2143 return _fsi_get_group(si
, name
, 0, SEL_NAME
);
2147 file_group_bygid(si_mod_t
*si
, gid_t gid
)
2149 return _fsi_get_group(si
, NULL
, gid
, SEL_NUMBER
);
2153 file_group_all(si_mod_t
*si
)
2155 return _fsi_get_group(si
, NULL
, 0, SEL_ALL
);
2159 file_grouplist(si_mod_t
*si
, const char *name
, __unused
uint32_t ignored
)
2161 return _fsi_get_grouplist(si
, name
);
2165 file_netgroup_byname(si_mod_t
*si
, const char *name
)
2167 si_list_t
*list
= NULL
;
2169 uint64_t va
=0, vb
=0;
2171 file_si_private_t
*pp
;
2173 if (name
== NULL
) return NULL
;
2175 pp
= (file_si_private_t
*)si
->private;
2176 if (pp
== NULL
) return NULL
;
2178 _fsi_check_netgroup_cache(si
);
2180 pthread_mutex_lock(&file_mutex
);
2182 n
= _fsi_find_netgroup(&(pp
->file_netgroup_cache
), name
, 0);
2185 file_netgroup_member_t
*m
= n
->members
;
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
);
2194 pthread_mutex_unlock(&file_mutex
);
2200 file_in_netgroup(si_mod_t
*si
, const char *group
, const char *host
, const char *user
, const char *domain
)
2203 file_netgroup_member_t
*m
;
2204 file_si_private_t
*pp
;
2206 if (group
== NULL
) return 0;
2208 pp
= (file_si_private_t
*)si
->private;
2209 if (pp
== NULL
) return 0;
2211 _fsi_check_netgroup_cache(si
);
2213 pthread_mutex_lock(&file_mutex
);
2215 n
= _fsi_find_netgroup(&(pp
->file_netgroup_cache
), group
, 0);
2218 pthread_mutex_unlock(&file_mutex
);
2225 file_netgroup_member_t
*x
= m
;
2230 if (x
->host
== NULL
) continue;
2231 if (strcmp(host
, x
->host
)) continue;
2236 if (x
->user
== NULL
) continue;
2237 if (strcmp(user
, x
->user
)) continue;
2242 if (x
->domain
== NULL
) continue;
2243 if (strcmp(domain
, x
->domain
)) continue;
2246 pthread_mutex_unlock(&file_mutex
);
2250 pthread_mutex_unlock(&file_mutex
);
2255 file_host_byname(si_mod_t
*si
, const char *name
, int af
, const char *ignored
, uint32_t *err
)
2259 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
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
;
2268 file_host_byaddr(si_mod_t
*si
, const void *addr
, int af
, const char *ignored
, uint32_t *err
)
2272 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
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
;
2281 file_host_all(si_mod_t
*si
)
2283 return _fsi_get_host(si
, NULL
, NULL
, 0, SEL_ALL
, NULL
);
2287 file_network_byname(si_mod_t
*si
, const char *name
)
2289 if (name
== NULL
) return NULL
;
2290 return _fsi_get_name_number_aliases(si
, name
, 0, SEL_NAME
, CATEGORY_NETWORK
);
2294 file_network_byaddr(si_mod_t
*si
, uint32_t addr
)
2296 return _fsi_get_name_number_aliases(si
, NULL
, (int)addr
, SEL_NUMBER
, CATEGORY_NETWORK
);
2300 file_network_all(si_mod_t
*si
)
2302 return _fsi_get_name_number_aliases(si
, NULL
, 0, SEL_ALL
, CATEGORY_NETWORK
);
2306 file_service_byname(si_mod_t
*si
, const char *name
, const char *proto
)
2308 return _fsi_get_service(si
, name
, proto
, 0, SEL_NAME
);
2312 file_service_byport(si_mod_t
*si
, int port
, const char *proto
)
2314 return _fsi_get_service(si
, NULL
, proto
, port
, SEL_NUMBER
);
2318 file_service_all(si_mod_t
*si
)
2320 return _fsi_get_service(si
, NULL
, NULL
, 0, SEL_ALL
);
2324 file_protocol_byname(si_mod_t
*si
, const char *name
)
2326 if (name
== NULL
) return NULL
;
2327 return _fsi_get_name_number_aliases(si
, name
, 0, SEL_NAME
, CATEGORY_PROTOCOL
);
2331 file_protocol_bynumber(si_mod_t
*si
, int number
)
2333 return _fsi_get_name_number_aliases(si
, NULL
, number
, SEL_NUMBER
, CATEGORY_PROTOCOL
);
2337 file_protocol_all(si_mod_t
*si
)
2339 return _fsi_get_name_number_aliases(si
, NULL
, 0, SEL_ALL
, CATEGORY_PROTOCOL
);
2343 file_rpc_byname(si_mod_t
*si
, const char *name
)
2345 if (name
== NULL
) return NULL
;
2346 return _fsi_get_name_number_aliases(si
, name
, 0, SEL_NAME
, CATEGORY_RPC
);
2350 file_rpc_bynumber(si_mod_t
*si
, int number
)
2352 return _fsi_get_name_number_aliases(si
, NULL
, number
, SEL_NUMBER
, CATEGORY_RPC
);
2356 file_rpc_all(si_mod_t
*si
)
2358 return _fsi_get_name_number_aliases(si
, NULL
, 0, SEL_ALL
, CATEGORY_RPC
);
2362 file_fs_byspec(si_mod_t
*si
, const char *spec
)
2364 return _fsi_get_fs(si
, spec
, SEL_NAME
);
2368 file_fs_byfile(si_mod_t
*si
, const char *file
)
2370 return _fsi_get_fs(si
, file
, SEL_NUMBER
);
2374 file_fs_all(si_mod_t
*si
)
2376 return _fsi_get_fs(si
, NULL
, SEL_ALL
);
2380 file_alias_byname(si_mod_t
*si
, const char *name
)
2382 return _fsi_get_alias(si
, name
, SEL_NAME
);
2386 file_alias_all(si_mod_t
*si
)
2388 return _fsi_get_alias(si
, NULL
, SEL_ALL
);
2392 file_mac_byname(si_mod_t
*si
, const char *name
)
2394 return _fsi_get_ether(si
, name
, SEL_NAME
);
2398 file_mac_bymac(si_mod_t
*si
, const char *mac
)
2400 return _fsi_get_ether(si
, mac
, SEL_NUMBER
);
2404 file_mac_all(si_mod_t
*si
)
2406 return _fsi_get_ether(si
, NULL
, SEL_ALL
);
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
)
2412 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
2413 return _gai_simple(si
, node
, serv
, family
, socktype
, proto
, flags
, interface
, err
);
2417 si_module_static_file(void)
2419 static const struct si_mod_vtable_s file_vtable
=
2421 .sim_is_valid
= &file_is_valid
,
2423 .sim_user_byname
= &file_user_byname
,
2424 .sim_user_byuid
= &file_user_byuid
,
2425 .sim_user_byuuid
= NULL
,
2426 .sim_user_all
= &file_user_all
,
2428 .sim_group_byname
= &file_group_byname
,
2429 .sim_group_bygid
= &file_group_bygid
,
2430 .sim_group_byuuid
= NULL
,
2431 .sim_group_all
= &file_group_all
,
2433 .sim_grouplist
= &file_grouplist
,
2435 .sim_netgroup_byname
= &file_netgroup_byname
,
2436 .sim_in_netgroup
= &file_in_netgroup
,
2438 .sim_alias_byname
= &file_alias_byname
,
2439 .sim_alias_all
= &file_alias_all
,
2441 .sim_host_byname
= &file_host_byname
,
2442 .sim_host_byaddr
= &file_host_byaddr
,
2443 .sim_host_all
= &file_host_all
,
2445 .sim_network_byname
= &file_network_byname
,
2446 .sim_network_byaddr
= &file_network_byaddr
,
2447 .sim_network_all
= &file_network_all
,
2449 .sim_service_byname
= &file_service_byname
,
2450 .sim_service_byport
= &file_service_byport
,
2451 .sim_service_all
= &file_service_all
,
2453 .sim_protocol_byname
= &file_protocol_byname
,
2454 .sim_protocol_bynumber
= &file_protocol_bynumber
,
2455 .sim_protocol_all
= &file_protocol_all
,
2457 .sim_rpc_byname
= &file_rpc_byname
,
2458 .sim_rpc_bynumber
= &file_rpc_bynumber
,
2459 .sim_rpc_all
= &file_rpc_all
,
2461 .sim_fs_byspec
= &file_fs_byspec
,
2462 .sim_fs_byfile
= &file_fs_byfile
,
2463 .sim_fs_all
= &file_fs_all
,
2465 .sim_mac_byname
= &file_mac_byname
,
2466 .sim_mac_bymac
= &file_mac_bymac
,
2467 .sim_mac_all
= &file_mac_all
,
2469 .sim_wants_addrinfo
= NULL
,
2470 .sim_addrinfo
= &file_addrinfo
,
2472 /* no nameinfo support */
2473 .sim_nameinfo
= NULL
,
2476 static si_mod_t si
=
2480 .flags
= SI_MOD_FLAG_STATIC
,
2483 .vtable
= &file_vtable
,
2486 static dispatch_once_t once
;
2488 dispatch_once(&once
, ^{
2489 si
.name
= strdup("file");
2490 file_si_private_t
*pp
= calloc(1, sizeof(file_si_private_t
));
2494 for (i
= 0; i
< VALIDATION_COUNT
; i
++) pp
->notify_token
[i
] = -1;
2496 /* hardwired for now, but we may want to make this configurable someday */
2497 pp
->validation_notify_mask
= VALIDATION_MASK_HOSTS
| VALIDATION_MASK_SERVICES
| VALIDATION_MASK_PROTOCOLS
;
2503 return (si_mod_t
*)&si
;