2 * Copyright (c) 2008-2010 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This ds 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 ds 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 <mach/mach.h>
27 libinfoDSmig_do_Response_async(mach_port_t server
, char *reply
, mach_msg_type_number_t replyCnt
, vm_offset_t ooreply
, mach_msg_type_number_t ooreplyCnt
, mach_vm_address_t callbackAddr
, security_token_t servertoken
)
40 #include <arpa/inet.h>
49 #include <notify_keys.h>
51 #include <si_module.h>
52 #include <netdb_async.h>
54 #include <servers/bootstrap.h>
55 #include <bootstrap_priv.h>
56 #include "DSlibinfoMIG.h"
57 #include "DSmemberdMIG.h"
63 #define IPPROTO_UNSPEC 0
65 #define IPV6_ADDR_LEN 16
66 #define IPV4_ADDR_LEN 4
68 #define WANT_NOTHING 0
69 #define WANT_A4_ONLY 1
70 #define WANT_A6_ONLY 2
71 #define WANT_A6_PLUS_MAPPED_A4 3
72 #define WANT_MAPPED_A4_ONLY 4
74 /* ONLY TO BE USED BY getipv6nodebyaddr */
75 #define WANT_A6_OR_MAPPED_A4_IF_NO_A6 5
77 #define MAX_LOOKUP_ATTEMPTS 10
79 #define INET_NTOP_AF_INET_OFFSET 4
80 #define INET_NTOP_AF_INET6_OFFSET 8
83 mach_port_t _mbr_port
;
85 extern uint32_t gL1CacheEnabled
;
87 static pthread_key_t _ds_serv_cache_key
= 0;
92 _ds_port
= MACH_PORT_NULL
;
93 _mbr_port
= MACH_PORT_NULL
;
96 static int _si_opendirectory_disabled
;
99 _si_disable_opendirectory(void)
101 _si_opendirectory_disabled
= 1;
102 _ds_port
= MACH_PORT_NULL
;
103 _mbr_port
= MACH_PORT_NULL
;
109 kern_return_t status
;
110 char *od_debug_mode
= NULL
;
112 if (_ds_port
!= MACH_PORT_NULL
) return 1;
114 if (_si_opendirectory_disabled
) return 0;
115 pthread_atfork(NULL
, NULL
, _ds_child
);
118 od_debug_mode
= getenv("OD_DEBUG_MODE");
122 status
= bootstrap_look_up(bootstrap_port
, kDSStdMachDSLookupPortName
"_debug", &_ds_port
);
124 status
= bootstrap_look_up2(bootstrap_port
, kDSStdMachDSLookupPortName
,
125 &_ds_port
, 0, BOOTSTRAP_PRIVILEGED_SERVER
);
127 if ((status
!= BOOTSTRAP_SUCCESS
) && (status
!= BOOTSTRAP_UNKNOWN_SERVICE
)) _ds_port
= MACH_PORT_NULL
;
130 status
= bootstrap_look_up(bootstrap_port
, kDSStdMachDSMembershipPortName
"_debug", &_mbr_port
);
132 status
= bootstrap_look_up2(bootstrap_port
, kDSStdMachDSMembershipPortName
,
133 &_mbr_port
, 0, BOOTSTRAP_PRIVILEGED_SERVER
);
135 if ((status
!= BOOTSTRAP_SUCCESS
) && (status
!= BOOTSTRAP_UNKNOWN_SERVICE
)) _mbr_port
= MACH_PORT_NULL
;
137 return (_ds_port
!= MACH_PORT_NULL
);
141 _ds_serv_cache_free(void *x
)
143 if (x
!= NULL
) si_item_release(x
);
147 LI_DSLookupGetProcedureNumber(const char *name
, int32_t *procno
)
149 kern_return_t status
;
150 security_token_t token
;
153 if (name
== NULL
) return KERN_FAILURE
;
155 len
= strlen(name
) + 1;
156 if (len
== 1) return KERN_FAILURE
;
161 if (_ds_running() == 0) return KERN_FAILURE
;
162 if (_ds_port
== MACH_PORT_NULL
) return KERN_FAILURE
;
164 status
= MIG_SERVER_DIED
;
165 for (n
= 0; (_ds_port
!= MACH_PORT_NULL
) && (status
== MIG_SERVER_DIED
) && (n
< MAX_LOOKUP_ATTEMPTS
); n
++)
167 status
= libinfoDSmig_GetProcedureNumber(_ds_port
, (char *)name
, procno
, &token
);
169 if (status
== MACH_SEND_INVALID_DEST
)
171 mach_port_mod_refs(mach_task_self(), _ds_port
, MACH_PORT_RIGHT_SEND
, -1);
172 status
= bootstrap_look_up2(bootstrap_port
, kDSStdMachDSLookupPortName
, &_ds_port
, 0, BOOTSTRAP_PRIVILEGED_SERVER
);
173 if ((status
!= BOOTSTRAP_SUCCESS
) && (status
!= BOOTSTRAP_UNKNOWN_SERVICE
)) _ds_port
= MACH_PORT_NULL
;
174 status
= MIG_SERVER_DIED
;
178 if (status
!= KERN_SUCCESS
)
181 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupGetProcedureNumber %s status %u", name
, status
);
186 if (token
.val
[0] != 0)
189 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupGetProcedureNumber %s auth failure uid=%d", name
, token
.val
[0]);
195 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupGetProcedureNumber %s = %d", name
, *procno
);
201 LI_DSLookupQuery(int32_t procno
, kvbuf_t
*request
, kvarray_t
**reply
)
203 kern_return_t status
;
204 security_token_t token
;
206 mach_msg_type_number_t illen
, oolen
;
207 char ilbuf
[MAX_MIG_INLINE_DATA
];
211 if (reply
== NULL
) return KERN_FAILURE
;
212 if ((request
!= NULL
) && ((request
->databuf
== NULL
) || (request
->datalen
== 0))) return KERN_FAILURE
;
218 if (_ds_running() == 0) return KERN_FAILURE
;
219 if (_ds_port
== MACH_PORT_NULL
) return KERN_FAILURE
;
221 status
= MIG_SERVER_DIED
;
222 for (n
= 0; (_ds_port
!= MACH_PORT_NULL
) && (status
== MIG_SERVER_DIED
) && (n
< MAX_LOOKUP_ATTEMPTS
); n
++)
230 status
= libinfoDSmig_Query(_ds_port
, procno
, request
->databuf
, request
->datalen
, ilbuf
, &illen
, &oobuf
, &oolen
, &token
);
234 status
= libinfoDSmig_Query(_ds_port
, procno
, "", 0, ilbuf
, &illen
, &oobuf
, &oolen
, &token
);
237 if (status
== MACH_SEND_INVALID_DEST
)
239 mach_port_mod_refs(mach_task_self(), _ds_port
, MACH_PORT_RIGHT_SEND
, -1);
240 status
= bootstrap_look_up2(bootstrap_port
, kDSStdMachDSLookupPortName
, &_ds_port
, 0, BOOTSTRAP_PRIVILEGED_SERVER
);
241 if ((status
!= BOOTSTRAP_SUCCESS
) && (status
!= BOOTSTRAP_UNKNOWN_SERVICE
)) _ds_port
= MACH_PORT_NULL
;
242 status
= MIG_SERVER_DIED
;
246 if (status
!= KERN_SUCCESS
)
249 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupQuery %d status %u", procno
, status
);
254 if (token
.val
[0] != 0)
257 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupQuery %d auth failure uid=%d", procno
, token
.val
[0]);
259 if ((oolen
> 0) && (oobuf
!= 0)) vm_deallocate(mach_task_self(), (vm_address_t
)oobuf
, oolen
);
263 out
= (kvbuf_t
*)calloc(1, sizeof(kvbuf_t
));
266 if ((oolen
> 0) && (oobuf
!= 0)) vm_deallocate(mach_task_self(), (vm_address_t
)oobuf
, oolen
);
270 if ((oolen
> 0) && (oobuf
!= 0))
272 out
->datalen
= oolen
;
273 out
->databuf
= malloc(oolen
);
274 if (out
->databuf
== NULL
)
278 vm_deallocate(mach_task_self(), (vm_address_t
)oobuf
, oolen
);
282 memcpy(out
->databuf
, (char *)oobuf
, oolen
);
283 vm_deallocate(mach_task_self(), (vm_address_t
)oobuf
, oolen
);
287 out
->datalen
= illen
;
288 out
->databuf
= malloc(illen
);
289 if (out
->databuf
== NULL
)
296 memcpy(out
->databuf
, ilbuf
, illen
);
299 *reply
= kvbuf_decode(out
);
302 /* DS returned no data */
308 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupQuery %d status OK", procno
);
314 uint32_t notify_peek(int token
, uint32_t *val
);
318 int notify_token_global
;
319 int notify_token_user
;
320 int notify_token_group
;
321 int notify_token_host
;
322 int notify_token_service
;
326 audit_token_uid(audit_token_t a
)
329 * This should really call audit_token_to_au32,
330 * but that's in libbsm, not in a Libsystem library.
332 return (uid_t
)a
.val
[1];
336 ds_get_validation(si_mod_t
*si
, uint64_t *a
, uint64_t *b
, int cat
)
342 if (si
== NULL
) return;
344 pp
= (ds_si_private_t
*)si
->private;
345 if (pp
== NULL
) return;
350 status
= notify_peek(pp
->notify_token_global
, &peek
);
351 if (status
== NOTIFY_STATUS_OK
) *a
= ntohl(peek
);
358 status
= NOTIFY_STATUS_FAILED
;
360 if (cat
== CATEGORY_USER
) status
= notify_peek(pp
->notify_token_user
, &peek
);
361 else if (cat
== CATEGORY_GROUP
) status
= notify_peek(pp
->notify_token_group
, &peek
);
362 else if (cat
== CATEGORY_GROUPLIST
) status
= notify_peek(pp
->notify_token_group
, &peek
);
363 else if (cat
== CATEGORY_HOST_IPV4
) status
= notify_peek(pp
->notify_token_host
, &peek
);
364 else if (cat
== CATEGORY_HOST_IPV6
) status
= notify_peek(pp
->notify_token_host
, &peek
);
365 else if (cat
== CATEGORY_SERVICE
) status
= notify_peek(pp
->notify_token_service
, &peek
);
367 if (status
== NOTIFY_STATUS_OK
) *b
= ntohl(peek
);
372 ds_list(si_mod_t
*si
, int cat
, const char *procname
, int *procnum
, void *extra
, si_item_t
*(*extract
)(si_mod_t
*, kvarray_t
*, void *, uint64_t, uint64_t), kvbuf_t
*request
)
377 kern_return_t status
;
382 status
= LI_DSLookupGetProcedureNumber(procname
, procnum
);
383 if (status
!= KERN_SUCCESS
) return NULL
;
387 ds_get_validation(si
, &va
, &vb
, cat
);
388 status
= LI_DSLookupQuery(*procnum
, request
, &reply
);
390 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
)) return NULL
;
393 while (reply
->curr
< reply
->count
)
395 item
= extract(si
, reply
, extra
, va
, vb
);
396 list
= si_list_add(list
, item
);
397 si_item_release(item
);
406 ds_item(si_mod_t
*si
, int cat
, const char *procname
, int *procnum
, void *extra
, si_item_t
*(*extract
)(si_mod_t
*, kvarray_t
*, void *, uint64_t, uint64_t), kvbuf_t
*request
)
410 kern_return_t status
;
415 status
= LI_DSLookupGetProcedureNumber(procname
, procnum
);
416 if (status
!= KERN_SUCCESS
) return NULL
;
420 ds_get_validation(si
, &va
, &vb
, cat
);
421 status
= LI_DSLookupQuery(*procnum
, request
, &reply
);
423 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
)) return NULL
;
425 item
= extract(si
, reply
, extra
, va
, vb
);
432 * Extract the next user entry from a kvarray.
435 extract_user(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
438 uint32_t d
, k
, kcount
;
440 if (si
== NULL
) return NULL
;
441 if (in
== NULL
) return NULL
;
446 if (d
>= in
->count
) return NULL
;
448 memset(&tmp
, 0, sizeof(struct passwd
));
453 kcount
= in
->dict
[d
].kcount
;
455 for (k
= 0; k
< kcount
; k
++)
457 if (string_equal(in
->dict
[d
].key
[k
], "pw_name"))
459 if (tmp
.pw_name
!= NULL
) continue;
460 if (in
->dict
[d
].vcount
[k
] == 0) continue;
462 tmp
.pw_name
= (char *)in
->dict
[d
].val
[k
][0];
464 else if (string_equal(in
->dict
[d
].key
[k
], "pw_passwd"))
466 if (tmp
.pw_passwd
!= NULL
) continue;
467 if (in
->dict
[d
].vcount
[k
] == 0) continue;
469 tmp
.pw_passwd
= (char *)in
->dict
[d
].val
[k
][0];
471 else if (string_equal(in
->dict
[d
].key
[k
], "pw_uid"))
473 if (in
->dict
[d
].vcount
[k
] == 0) continue;
474 tmp
.pw_uid
= atoi(in
->dict
[d
].val
[k
][0]);
476 else if (string_equal(in
->dict
[d
].key
[k
], "pw_gid"))
478 if (in
->dict
[d
].vcount
[k
] == 0) continue;
479 tmp
.pw_gid
= atoi(in
->dict
[d
].val
[k
][0]);
481 else if (string_equal(in
->dict
[d
].key
[k
], "pw_change"))
483 if (in
->dict
[d
].vcount
[k
] == 0) continue;
484 tmp
.pw_change
= atol(in
->dict
[d
].val
[k
][0]);
486 else if (string_equal(in
->dict
[d
].key
[k
], "pw_expire"))
488 if (in
->dict
[d
].vcount
[k
] == 0) continue;
489 tmp
.pw_expire
= atol(in
->dict
[d
].val
[k
][0]);
491 else if (string_equal(in
->dict
[d
].key
[k
], "pw_class"))
493 if (tmp
.pw_class
!= NULL
) continue;
494 if (in
->dict
[d
].vcount
[k
] == 0) continue;
496 tmp
.pw_class
= (char *)in
->dict
[d
].val
[k
][0];
498 else if (string_equal(in
->dict
[d
].key
[k
], "pw_gecos"))
500 if (tmp
.pw_gecos
!= NULL
) continue;
501 if (in
->dict
[d
].vcount
[k
] == 0) continue;
503 tmp
.pw_gecos
= (char *)in
->dict
[d
].val
[k
][0];
505 else if (string_equal(in
->dict
[d
].key
[k
], "pw_dir"))
507 if (tmp
.pw_dir
!= NULL
) continue;
508 if (in
->dict
[d
].vcount
[k
] == 0) continue;
510 tmp
.pw_dir
= (char *)in
->dict
[d
].val
[k
][0];
512 else if (string_equal(in
->dict
[d
].key
[k
], "pw_shell"))
514 if (tmp
.pw_shell
!= NULL
) continue;
515 if (in
->dict
[d
].vcount
[k
] == 0) continue;
517 tmp
.pw_shell
= (char *)in
->dict
[d
].val
[k
][0];
521 if (tmp
.pw_name
== NULL
) tmp
.pw_name
= "";
522 if (tmp
.pw_passwd
== NULL
) tmp
.pw_passwd
= "";
523 if (tmp
.pw_class
== NULL
) tmp
.pw_class
= "";
524 if (tmp
.pw_gecos
== NULL
) tmp
.pw_gecos
= "";
525 if (tmp
.pw_dir
== NULL
) tmp
.pw_dir
= "";
526 if (tmp
.pw_shell
== NULL
) tmp
.pw_shell
= "";
528 return (si_item_t
*)LI_ils_create("L4488ss44LssssL", (unsigned long)si
, CATEGORY_USER
, 1, valid_global
, valid_cat
, tmp
.pw_name
, tmp
.pw_passwd
, tmp
.pw_uid
, tmp
.pw_gid
, tmp
.pw_change
, tmp
.pw_class
, tmp
.pw_gecos
, tmp
.pw_dir
, tmp
.pw_shell
, tmp
.pw_expire
);
532 extract_group(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
536 uint32_t d
, k
, kcount
;
538 if (si
== NULL
) return NULL
;
539 if (in
== NULL
) return NULL
;
544 if (d
>= in
->count
) return NULL
;
547 memset(&tmp
, 0, sizeof(struct group
));
551 kcount
= in
->dict
[d
].kcount
;
553 for (k
= 0; k
< kcount
; k
++)
555 if (string_equal(in
->dict
[d
].key
[k
], "gr_name"))
557 if (tmp
.gr_name
!= NULL
) continue;
558 if (in
->dict
[d
].vcount
[k
] == 0) continue;
560 tmp
.gr_name
= (char *)in
->dict
[d
].val
[k
][0];
562 else if (string_equal(in
->dict
[d
].key
[k
], "gr_passwd"))
564 if (tmp
.gr_passwd
!= NULL
) continue;
565 if (in
->dict
[d
].vcount
[k
] == 0) continue;
567 tmp
.gr_passwd
= (char *)in
->dict
[d
].val
[k
][0];
569 else if (string_equal(in
->dict
[d
].key
[k
], "gr_gid"))
571 if (in
->dict
[d
].vcount
[k
] == 0) continue;
572 tmp
.gr_gid
= atoi(in
->dict
[d
].val
[k
][0]);
574 else if (string_equal(in
->dict
[d
].key
[k
], "gr_mem"))
576 if (tmp
.gr_mem
!= NULL
) continue;
577 if (in
->dict
[d
].vcount
[k
] == 0) continue;
579 tmp
.gr_mem
= (char **)in
->dict
[d
].val
[k
];
583 if (tmp
.gr_name
== NULL
) tmp
.gr_name
= "";
584 if (tmp
.gr_passwd
== NULL
) tmp
.gr_passwd
= "";
585 if (tmp
.gr_mem
== NULL
) tmp
.gr_mem
= empty
;
587 return (si_item_t
*)LI_ils_create("L4488ss4*", (unsigned long)si
, CATEGORY_GROUP
, 1, valid_global
, valid_cat
, tmp
.gr_name
, tmp
.gr_passwd
, tmp
.gr_gid
, tmp
.gr_mem
);
591 _free_addr_list(char **l
)
595 if (l
== NULL
) return;
596 for (i
= 0; l
[i
] != NULL
; i
++) free(l
[i
]);
600 /* map ipv4 addresses and append to v6 list */
602 _map_v4(char ***v6
, uint32_t n6
, char **v4
, uint32_t n4
)
607 a6
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
608 a6
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
609 a6
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
613 *v6
= (char **)calloc(n4
+ 1, sizeof(char *));
617 *v6
= (char **)reallocf(*v6
, (n6
+ n4
+ 1) * sizeof(char *));
620 if (*v6
== NULL
) return -1;
622 for (i
= 0; i
< n4
; i
++)
624 (*v6
)[n6
] = (char *)calloc(1, IPV6_ADDR_LEN
);
625 if ((*v6
)[n6
] == NULL
) return -1;
627 memcpy(&(a6
.__u6_addr
.__u6_addr32
[3]), v4
[i
], IPV4_ADDR_LEN
);
628 memcpy((*v6
)[n6
], &(a6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
637 extract_netgroup(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
639 const char *host
, *user
, *domain
;
640 uint32_t d
, k
, kcount
;
642 if (si
== NULL
) return NULL
;
643 if (in
== NULL
) return NULL
;
648 if (d
>= in
->count
) return NULL
;
650 kcount
= in
->dict
[d
].kcount
;
656 for (k
= 0; k
< kcount
; k
++)
658 if (string_equal(in
->dict
[d
].key
[k
], "host"))
660 if (host
!= NULL
) continue;
661 if (in
->dict
[d
].vcount
[k
] == 0) continue;
663 host
= (char *)in
->dict
[d
].val
[k
][0];
665 else if (string_equal(in
->dict
[d
].key
[k
], "user"))
667 if (user
!= NULL
) continue;
668 if (in
->dict
[d
].vcount
[k
] == 0) continue;
670 user
= (char *)in
->dict
[d
].val
[k
][0];
672 else if (string_equal(in
->dict
[d
].key
[k
], "domain"))
674 if (domain
!= NULL
) continue;
675 if (in
->dict
[d
].vcount
[k
] == 0) continue;
677 domain
= (char *)in
->dict
[d
].val
[k
][0];
681 if (host
== NULL
) host
= "";
682 if (user
== NULL
) user
= "";
683 if (domain
== NULL
) domain
= "";
685 return (si_item_t
*)LI_ils_create("L4488sss", (unsigned long)si
, CATEGORY_ALIAS
, 1, valid_global
, valid_cat
, host
, user
, domain
);
689 extract_alias(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
693 uint32_t d
, k
, kcount
;
695 if (si
== NULL
) return NULL
;
696 if (in
== NULL
) return NULL
;
701 if (d
>= in
->count
) return NULL
;
704 memset(&tmp
, 0, sizeof(struct group
));
706 kcount
= in
->dict
[d
].kcount
;
708 for (k
= 0; k
< kcount
; k
++)
710 if (string_equal(in
->dict
[d
].key
[k
], "alias_name"))
712 if (tmp
.alias_name
!= NULL
) continue;
713 if (in
->dict
[d
].vcount
[k
] == 0) continue;
715 tmp
.alias_name
= (char *)in
->dict
[d
].val
[k
][0];
717 else if (string_equal(in
->dict
[d
].key
[k
], "alias_members"))
719 if (tmp
.alias_members
!= NULL
) continue;
720 if (in
->dict
[d
].vcount
[k
] == 0) continue;
722 tmp
.alias_members_len
= in
->dict
[d
].vcount
[k
];
723 tmp
.alias_members
= (char **)in
->dict
[d
].val
[k
];
725 else if (string_equal(in
->dict
[d
].key
[k
], "alias_local"))
727 if (in
->dict
[d
].vcount
[k
] == 0) continue;
728 tmp
.alias_local
= atoi(in
->dict
[d
].val
[k
][0]);
732 return (si_item_t
*)LI_ils_create("L4488s4*4", (unsigned long)si
, CATEGORY_ALIAS
, 1, valid_global
, valid_cat
, tmp
.alias_name
, tmp
.alias_members_len
, tmp
.alias_members
, tmp
.alias_local
);
736 extract_host(si_mod_t
*si
, kvarray_t
*in
, void *extra
, uint64_t valid_global
, uint64_t valid_cat
)
740 uint32_t i
, d
, k
, kcount
, vcount
, v4count
, v6count
, want
;
741 int status
, addr_len
;
742 int family
, addr_count
;
745 char **v4addrs
, **v6addrs
;
753 addr_len
= sizeof(void *);
755 if (si
== NULL
) return NULL
;
756 if (in
== NULL
) return NULL
;
761 if (d
>= in
->count
) return NULL
;
764 memset(&tmp
, 0, sizeof(struct hostent
));
767 tmp
.h_length
= IPV4_ADDR_LEN
;
770 if (extra
!= NULL
) want
= *(uint32_t *)extra
;
772 if (want
!= WANT_A4_ONLY
)
775 tmp
.h_length
= IPV6_ADDR_LEN
;
778 tmp
.h_addrtype
= family
;
780 kcount
= in
->dict
[d
].kcount
;
782 for (k
= 0; k
< kcount
; k
++)
784 if (string_equal(in
->dict
[d
].key
[k
], "h_name"))
786 if (tmp
.h_name
!= NULL
) continue;
788 vcount
= in
->dict
[d
].vcount
[k
];
789 if (vcount
== 0) continue;
791 tmp
.h_name
= (char *)in
->dict
[d
].val
[k
][0];
793 else if (string_equal(in
->dict
[d
].key
[k
], "h_aliases"))
795 if (tmp
.h_aliases
!= NULL
) continue;
797 vcount
= in
->dict
[d
].vcount
[k
];
798 if (vcount
== 0) continue;
800 tmp
.h_aliases
= (char **)in
->dict
[d
].val
[k
];
802 else if (string_equal(in
->dict
[d
].key
[k
], "h_ipv4_addr_list"))
804 if (v4addrs
!= NULL
) continue;
806 v4count
= in
->dict
[d
].vcount
[k
];
807 if (v4count
== 0) continue;
809 v4addrs
= (char **)calloc(v4count
+ 1, sizeof(char *));
812 _free_addr_list(v6addrs
);
816 for (i
= 0; i
< v4count
; i
++)
818 v4addrs
[i
] = calloc(1, IPV4_ADDR_LEN
);
819 if (v4addrs
[i
] == NULL
)
821 _free_addr_list(v4addrs
);
822 _free_addr_list(v6addrs
);
826 memset(&a4
, 0, sizeof(struct in_addr
));
827 status
= inet_pton(AF_INET
, in
->dict
[d
].val
[k
][i
], &a4
);
830 _free_addr_list(v4addrs
);
831 _free_addr_list(v6addrs
);
835 memcpy(v4addrs
[i
], &a4
, IPV4_ADDR_LEN
);
838 else if (string_equal(in
->dict
[d
].key
[k
], "h_ipv6_addr_list"))
840 if (v6addrs
!= NULL
) continue;
842 v6count
= in
->dict
[d
].vcount
[k
];
843 if (v6count
== 0) continue;
845 v6addrs
= (char **)calloc(v6count
+ 1, sizeof(char *));
848 _free_addr_list(v4addrs
);
852 for (i
= 0; i
< v6count
; i
++)
854 v6addrs
[i
] = calloc(1, IPV6_ADDR_LEN
);
855 if (v6addrs
[i
] == NULL
)
857 _free_addr_list(v4addrs
);
858 _free_addr_list(v6addrs
);
862 memset(&a6
, 0, sizeof(struct in6_addr
));
863 status
= inet_pton(AF_INET6
, in
->dict
[d
].val
[k
][i
], &a6
);
866 _free_addr_list(v4addrs
);
867 _free_addr_list(v6addrs
);
871 memcpy(v6addrs
[i
], &(a6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
876 if (tmp
.h_name
== NULL
) tmp
.h_name
= "";
877 if (tmp
.h_aliases
== NULL
) tmp
.h_aliases
= empty
;
879 if (want
== WANT_A4_ONLY
)
881 _free_addr_list(v6addrs
);
882 if (v4addrs
== NULL
) return NULL
;
884 tmp
.h_addr_list
= v4addrs
;
885 out
= (si_item_t
*)LI_ils_create("L4488s*44a", (unsigned long)si
, CATEGORY_HOST_IPV4
, 1, valid_global
, valid_cat
, tmp
.h_name
, tmp
.h_aliases
, tmp
.h_addrtype
, tmp
.h_length
, tmp
.h_addr_list
);
886 _free_addr_list(v4addrs
);
889 else if ((want
== WANT_A6_ONLY
) || ((want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) && (v6count
> 0)))
891 _free_addr_list(v4addrs
);
892 if (v6addrs
== NULL
) return NULL
;
894 tmp
.h_addr_list
= v6addrs
;
895 out
= (si_item_t
*)LI_ils_create("L4488s*44c", (unsigned long)si
, CATEGORY_HOST_IPV6
, 1, valid_global
, valid_cat
, tmp
.h_name
, tmp
.h_aliases
, tmp
.h_addrtype
, tmp
.h_length
, tmp
.h_addr_list
);
896 _free_addr_list(v6addrs
);
901 * At this point, want is WANT_A6_PLUS_MAPPED_A4, WANT_MAPPED_A4_ONLY,
902 * or WANT_A6_OR_MAPPED_A4_IF_NO_A6. In the last case, there are no ipv6
903 * addresses, so that case degenerates into WANT_MAPPED_A4_ONLY.
905 if (want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) want
= WANT_MAPPED_A4_ONLY
;
907 if (want
== WANT_MAPPED_A4_ONLY
)
909 _free_addr_list(v6addrs
);
914 status
= _map_v4(&v6addrs
, v6count
, v4addrs
, v4count
);
915 _free_addr_list(v4addrs
);
918 _free_addr_list(v6addrs
);
922 if (v6addrs
== NULL
) return NULL
;
924 tmp
.h_addr_list
= v6addrs
;
925 out
= (si_item_t
*)LI_ils_create("L4488s*44c", (unsigned long)si
, CATEGORY_HOST_IPV6
, 1, valid_global
, valid_cat
, tmp
.h_name
, tmp
.h_aliases
, tmp
.h_addrtype
, tmp
.h_length
, tmp
.h_addr_list
);
926 _free_addr_list(v6addrs
);
931 extract_network(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
934 uint32_t d
, k
, kcount
;
937 if (si
== NULL
) return NULL
;
938 if (in
== NULL
) return NULL
;
943 if (d
>= in
->count
) return NULL
;
946 memset(&tmp
, 0, sizeof(struct netent
));
948 tmp
.n_addrtype
= AF_INET
;
950 kcount
= in
->dict
[d
].kcount
;
952 for (k
= 0; k
< kcount
; k
++)
954 if (string_equal(in
->dict
[d
].key
[k
], "n_name"))
956 if (tmp
.n_name
!= NULL
) continue;
957 if (in
->dict
[d
].vcount
[k
] == 0) continue;
959 tmp
.n_name
= (char *)in
->dict
[d
].val
[k
][0];
961 else if (string_equal(in
->dict
[d
].key
[k
], "n_net"))
963 if (in
->dict
[d
].vcount
[k
] == 0) continue;
964 tmp
.n_net
= inet_network(in
->dict
[d
].val
[k
][0]);
966 else if (string_equal(in
->dict
[d
].key
[k
], "n_addrtype"))
968 if (in
->dict
[d
].vcount
[k
] == 0) continue;
969 tmp
.n_addrtype
= atoi(in
->dict
[d
].val
[k
][0]);
971 else if (string_equal(in
->dict
[d
].key
[k
], "n_aliases"))
973 if (tmp
.n_aliases
!= NULL
) continue;
974 if (in
->dict
[d
].vcount
[k
] == 0) continue;
976 tmp
.n_aliases
= (char **)in
->dict
[d
].val
[k
];
980 if (tmp
.n_name
== NULL
) tmp
.n_name
= "";
981 if (tmp
.n_aliases
== NULL
) tmp
.n_aliases
= empty
;
983 return (si_item_t
*)LI_ils_create("L4488s*44", (unsigned long)si
, CATEGORY_NETWORK
, 1, valid_global
, valid_cat
, tmp
.n_name
, tmp
.n_aliases
, tmp
.n_addrtype
, tmp
.n_net
);
987 extract_service(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
991 uint32_t d
, k
, kcount
;
993 if (si
== NULL
) return NULL
;
994 if (in
== NULL
) return NULL
;
999 if (d
>= in
->count
) return NULL
;
1002 memset(&tmp
, 0, sizeof(struct servent
));
1004 kcount
= in
->dict
[d
].kcount
;
1006 for (k
= 0; k
< kcount
; k
++)
1008 if (string_equal(in
->dict
[d
].key
[k
], "s_name"))
1010 if (tmp
.s_name
!= NULL
) continue;
1011 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1013 tmp
.s_name
= (char *)in
->dict
[d
].val
[k
][0];
1015 else if (string_equal(in
->dict
[d
].key
[k
], "s_aliases"))
1017 if (tmp
.s_aliases
!= NULL
) continue;
1018 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1020 tmp
.s_aliases
= (char **)in
->dict
[d
].val
[k
];
1022 else if (string_equal(in
->dict
[d
].key
[k
], "s_port"))
1024 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1025 tmp
.s_port
= atoi(in
->dict
[d
].val
[k
][0]);
1027 else if (string_equal(in
->dict
[d
].key
[k
], "s_proto"))
1029 if (tmp
.s_proto
!= NULL
) continue;
1030 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1032 tmp
.s_proto
= (char *)in
->dict
[d
].val
[k
][0];
1036 if (tmp
.s_name
== NULL
) tmp
.s_name
= "";
1037 if (tmp
.s_proto
== NULL
) tmp
.s_proto
= "";
1038 if (tmp
.s_aliases
== NULL
) tmp
.s_aliases
= empty
;
1040 /* strange but correct */
1041 tmp
.s_port
= htons(tmp
.s_port
);
1043 return (si_item_t
*)LI_ils_create("L4488s*4s", (unsigned long)si
, CATEGORY_SERVICE
, 1, valid_global
, valid_cat
, tmp
.s_name
, tmp
.s_aliases
, tmp
.s_port
, tmp
.s_proto
);
1047 extract_protocol(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
1049 struct protoent tmp
;
1050 uint32_t d
, k
, kcount
;
1053 if (si
== NULL
) return NULL
;
1054 if (in
== NULL
) return NULL
;
1059 if (d
>= in
->count
) return NULL
;
1062 memset(&tmp
, 0, sizeof(struct protoent
));
1064 kcount
= in
->dict
[d
].kcount
;
1066 for (k
= 0; k
< kcount
; k
++)
1068 if (string_equal(in
->dict
[d
].key
[k
], "p_name"))
1070 if (tmp
.p_name
!= NULL
) continue;
1071 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1073 tmp
.p_name
= (char *)in
->dict
[d
].val
[k
][0];
1075 else if (string_equal(in
->dict
[d
].key
[k
], "p_proto"))
1077 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1078 tmp
.p_proto
= atoi(in
->dict
[d
].val
[k
][0]);
1080 else if (string_equal(in
->dict
[d
].key
[k
], "p_aliases"))
1082 if (tmp
.p_aliases
!= NULL
) continue;
1083 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1085 tmp
.p_aliases
= (char **)in
->dict
[d
].val
[k
];
1089 if (tmp
.p_name
== NULL
) tmp
.p_name
= "";
1090 if (tmp
.p_aliases
== NULL
) tmp
.p_aliases
= empty
;
1092 return (si_item_t
*)LI_ils_create("L4488s*4", (unsigned long)si
, CATEGORY_PROTOCOL
, 1, valid_global
, valid_cat
, tmp
.p_name
, tmp
.p_aliases
, tmp
.p_proto
);
1096 extract_rpc(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
1099 uint32_t d
, k
, kcount
;
1102 if (si
== NULL
) return NULL
;
1103 if (in
== NULL
) return NULL
;
1108 if (d
>= in
->count
) return NULL
;
1111 memset(&tmp
, 0, sizeof(struct rpcent
));
1113 kcount
= in
->dict
[d
].kcount
;
1115 for (k
= 0; k
< kcount
; k
++)
1117 if (string_equal(in
->dict
[d
].key
[k
], "r_name"))
1119 if (tmp
.r_name
!= NULL
) continue;
1120 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1122 tmp
.r_name
= (char *)in
->dict
[d
].val
[k
][0];
1124 else if (string_equal(in
->dict
[d
].key
[k
], "r_number"))
1126 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1127 tmp
.r_number
= atoi(in
->dict
[d
].val
[k
][0]);
1129 else if (string_equal(in
->dict
[d
].key
[k
], "r_aliases"))
1131 if (tmp
.r_aliases
!= NULL
) continue;
1132 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1134 tmp
.r_aliases
= (char **)in
->dict
[d
].val
[k
];
1138 if (tmp
.r_name
== NULL
) tmp
.r_name
= "";
1139 if (tmp
.r_aliases
== NULL
) tmp
.r_aliases
= empty
;
1141 return (si_item_t
*)LI_ils_create("L4488s*4", (unsigned long)si
, CATEGORY_RPC
, 1, valid_global
, valid_cat
, tmp
.r_name
, tmp
.r_aliases
, tmp
.r_number
);
1145 extract_fstab(si_mod_t
*si
, kvarray_t
*in
, void *extra
, uint64_t valid_global
, uint64_t valid_cat
)
1148 uint32_t d
, k
, kcount
;
1151 if (si
== NULL
) return NULL
;
1152 if (in
== NULL
) return NULL
;
1155 if (extra
!= NULL
) file
= (char *)extra
;
1160 if (d
>= in
->count
) return NULL
;
1162 memset(&tmp
, 0, sizeof(struct fstab
));
1164 kcount
= in
->dict
[d
].kcount
;
1166 for (k
= 0; k
< kcount
; k
++)
1168 if (string_equal(in
->dict
[d
].key
[k
], "fs_spec"))
1170 if (tmp
.fs_spec
!= NULL
) continue;
1171 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1173 tmp
.fs_spec
= (char *)in
->dict
[d
].val
[k
][0];
1175 else if (string_equal(in
->dict
[d
].key
[k
], "fs_file"))
1177 if (tmp
.fs_file
!= NULL
) continue;
1178 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1180 tmp
.fs_file
= (char *)in
->dict
[d
].val
[k
][0];
1182 else if (string_equal(in
->dict
[d
].key
[k
], "fs_vfstype"))
1184 if (tmp
.fs_vfstype
!= NULL
) continue;
1185 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1187 tmp
.fs_vfstype
= (char *)in
->dict
[d
].val
[k
][0];
1189 else if (string_equal(in
->dict
[d
].key
[k
], "fs_mntops"))
1191 if (tmp
.fs_mntops
!= NULL
) continue;
1192 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1194 tmp
.fs_mntops
= (char *)in
->dict
[d
].val
[k
][0];
1196 else if (string_equal(in
->dict
[d
].key
[k
], "fs_type"))
1198 if (tmp
.fs_type
!= NULL
) continue;
1199 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1201 tmp
.fs_type
= (char *)in
->dict
[d
].val
[k
][0];
1203 else if (string_equal(in
->dict
[d
].key
[k
], "fs_freq"))
1205 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1206 tmp
.fs_freq
= atoi(in
->dict
[d
].val
[k
][0]);
1208 else if (string_equal(in
->dict
[d
].key
[k
], "fs_passno"))
1210 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1211 tmp
.fs_passno
= atoi(in
->dict
[d
].val
[k
][0]);
1215 if (tmp
.fs_spec
== NULL
) tmp
.fs_spec
= "";
1216 if (tmp
.fs_file
== NULL
) tmp
.fs_file
= "";
1217 if (tmp
.fs_vfstype
== NULL
) tmp
.fs_vfstype
= "";
1218 if (tmp
.fs_mntops
== NULL
) tmp
.fs_mntops
= "";
1219 if (tmp
.fs_type
== NULL
) tmp
.fs_type
= "";
1221 if ((file
!= NULL
) && string_not_equal(file
, tmp
.fs_file
)) return NULL
;
1223 return (si_item_t
*)LI_ils_create("L4488sssss44", (unsigned long)si
, CATEGORY_FS
, 1, valid_global
, valid_cat
, tmp
.fs_spec
, tmp
.fs_file
, tmp
.fs_vfstype
, tmp
.fs_mntops
, tmp
.fs_type
, tmp
.fs_freq
, tmp
.fs_passno
);
1227 extract_mac_mac(si_mod_t
*si
, kvarray_t
*in
, void *extra
, uint64_t valid_global
, uint64_t valid_cat
)
1229 uint32_t d
, k
, kcount
;
1233 if (si
== NULL
) return NULL
;
1234 if (in
== NULL
) return NULL
;
1235 if (extra
== NULL
) return NULL
;
1240 if (d
>= in
->count
) return NULL
;
1242 kcount
= in
->dict
[d
].kcount
;
1245 for (k
= 0; k
< kcount
; k
++)
1247 if ((cmac
== NULL
) && (string_equal(in
->dict
[d
].key
[k
], "mac")))
1249 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1250 cmac
= si_standardize_mac_address(in
->dict
[d
].val
[k
][0]);
1251 if (cmac
== NULL
) return NULL
;
1255 if (cmac
== NULL
) return NULL
;
1257 out
= (si_item_t
*)LI_ils_create("L4488ss", (unsigned long)si
, CATEGORY_MAC
, 1, valid_global
, valid_cat
, extra
, cmac
);
1263 extract_mac_name(si_mod_t
*si
, kvarray_t
*in
, void *extra
, uint64_t valid_global
, uint64_t valid_cat
)
1265 uint32_t d
, k
, kcount
;
1269 if (si
== NULL
) return NULL
;
1270 if (in
== NULL
) return NULL
;
1271 if (extra
== NULL
) return NULL
;
1276 if (d
>= in
->count
) return NULL
;
1278 kcount
= in
->dict
[d
].kcount
;
1281 for (k
= 0; k
< kcount
; k
++)
1283 if ((name
== NULL
) && (string_equal(in
->dict
[d
].key
[k
], "name")))
1285 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1286 name
= in
->dict
[d
].val
[k
][0];
1290 if (name
== NULL
) return NULL
;
1292 out
= (si_item_t
*)LI_ils_create("L4488ss", (unsigned long)si
, CATEGORY_MAC
, 1, valid_global
, valid_cat
, name
, extra
);
1297 ds_user_byname(si_mod_t
*si
, const char *name
)
1299 static int proc
= -1;
1303 request
= kvbuf_query_key_val("login", name
);
1304 if (request
== NULL
) return NULL
;
1306 item
= ds_item(si
, CATEGORY_USER
, "getpwnam", &proc
, NULL
, extract_user
, request
);
1308 kvbuf_free(request
);
1313 ds_user_byuid(si_mod_t
*si
, uid_t uid
)
1315 static int proc
= -1;
1320 snprintf(val
, sizeof(val
), "%d", (int)uid
);
1321 request
= kvbuf_query_key_val("uid", val
);
1322 if (request
== NULL
) return NULL
;
1324 item
= ds_item(si
, CATEGORY_USER
, "getpwuid", &proc
, NULL
, extract_user
, request
);
1326 kvbuf_free(request
);
1331 ds_user_all(si_mod_t
*si
)
1333 static int proc
= -1;
1335 return ds_list(si
, CATEGORY_USER
, "getpwent", &proc
, NULL
, extract_user
, NULL
);
1339 ds_group_byname(si_mod_t
*si
, const char *name
)
1341 static int proc
= -1;
1345 request
= kvbuf_query_key_val("name", name
);
1346 if (request
== NULL
) return NULL
;
1348 item
= ds_item(si
, CATEGORY_GROUP
, "getgrnam", &proc
, NULL
, extract_group
, request
);
1350 kvbuf_free(request
);
1355 ds_group_bygid(si_mod_t
*si
, gid_t gid
)
1357 static int proc
= -1;
1362 snprintf(val
, sizeof(val
), "%d", (int)gid
);
1363 request
= kvbuf_query_key_val("gid", val
);
1364 if (request
== NULL
) return NULL
;
1366 item
= ds_item(si
, CATEGORY_GROUP
, "getgrgid", &proc
, NULL
, extract_group
, request
);
1368 kvbuf_free(request
);
1373 ds_group_all(si_mod_t
*si
)
1375 static int proc
= -1;
1377 return ds_list(si
, CATEGORY_GROUP
, "getgrent", &proc
, NULL
, extract_group
, NULL
);
1381 ds_grouplist(si_mod_t
*si
, const char *name
)
1384 kern_return_t kstatus
, ks2
;
1385 uint32_t i
, j
, count
, uid
, basegid
, gidptrCnt
;
1388 audit_token_t token
;
1389 si_item_t
*user
, *item
;
1395 if (name
== NULL
) return NULL
;
1397 user
= ds_user_byname(si
, name
);
1398 if (user
== NULL
) return NULL
;
1400 pw
= (struct passwd
*)((uintptr_t)user
+ sizeof(si_item_t
));
1402 basegid
= pw
->pw_gid
;
1410 memset(&token
, 0, sizeof(audit_token_t
));
1412 if (_mbr_port
== MACH_PORT_NULL
)
1414 kstatus
= bootstrap_look_up2(bootstrap_port
, kDSStdMachDSMembershipPortName
, &_mbr_port
, 0, BOOTSTRAP_PRIVILEGED_SERVER
);
1417 for (n
= 0; n
< MAX_LOOKUP_ATTEMPTS
; n
++)
1419 kstatus
= memberdDSmig_GetAllGroups(_mbr_port
, uid
, &count
, &gidptr
, &gidptrCnt
, &token
);
1420 if (kstatus
!= MACH_SEND_INVALID_DEST
) break;
1422 mach_port_mod_refs(mach_task_self(), _mbr_port
, MACH_PORT_RIGHT_SEND
, -1);
1424 ks2
= bootstrap_look_up2(bootstrap_port
, kDSStdMachDSMembershipPortName
, &_mbr_port
, 0, BOOTSTRAP_PRIVILEGED_SERVER
);
1425 if ((ks2
!= BOOTSTRAP_SUCCESS
) && (ks2
!= BOOTSTRAP_UNKNOWN_SERVICE
))
1427 _mbr_port
= MACH_PORT_NULL
;
1432 if (kstatus
!= KERN_SUCCESS
) return NULL
;
1433 if (gidptr
== NULL
) return NULL
;
1435 /* gidptrCnt is the size, but it was set to number of groups (by DS) in 10.6 and earlier */
1436 gidptrsz
= gidptrCnt
;
1437 if (count
== gidptrCnt
) gidptrsz
= gidptrCnt
* sizeof(gid_t
);
1439 if ((audit_token_uid(token
) != 0) || (count
== 0))
1441 if (gidptr
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)gidptr
, gidptrsz
);
1445 gidlist
= (char **)calloc(count
+ 1, sizeof(char *));
1446 if (gidlist
== NULL
)
1448 if (gidptr
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)gidptr
, gidptrsz
);
1452 for (i
= 0; i
< count
; i
++)
1454 gidp
= (int32_t *)calloc(1, sizeof(int32_t));
1457 for (j
= 0; j
< i
; j
++) free(gidlist
[j
]);
1464 gidlist
[i
] = (char *)gidp
;
1469 if (gidptr
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)gidptr
, gidptrsz
);
1475 ds_get_validation(si
, &va
, &vb
, CATEGORY_GROUPLIST
);
1477 item
= (si_item_t
*)LI_ils_create("L4488s44a", (unsigned long)si
, CATEGORY_GROUPLIST
, 1, va
, vb
, name
, basegid
, count
, gidlist
);
1479 if (gidptr
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)gidptr
, gidptrsz
);
1481 for (i
= 0; i
<= count
; i
++) free(gidlist
[i
]);
1488 ds_netgroup_byname(si_mod_t
*si
, const char *name
)
1490 static int proc
= -1;
1494 request
= kvbuf_query_key_val("netgroup", name
);
1495 if (request
== NULL
) return NULL
;
1497 list
= ds_list(si
, CATEGORY_NETGROUP
, "getnetgrent", &proc
, NULL
, extract_netgroup
, request
);
1499 kvbuf_free(request
);
1505 check_innetgr(kvarray_t
*in
)
1507 uint32_t d
, k
, kcount
;
1509 if (in
== NULL
) return 0;
1512 if (d
>= in
->count
) return 0;
1514 kcount
= in
->dict
[d
].kcount
;
1516 for (k
= 0; k
< kcount
; k
++)
1518 if (string_equal(in
->dict
[d
].key
[k
], "result"))
1520 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1521 return atoi(in
->dict
[d
].val
[k
][0]);
1529 ds_in_netgroup(si_mod_t
*si
, const char *group
, const char *host
, const char *user
, const char *domain
)
1534 kern_return_t status
;
1535 static int proc
= -1;
1539 status
= LI_DSLookupGetProcedureNumber("innetgr", &proc
);
1540 if (status
!= KERN_SUCCESS
) return 0;
1544 if (group
== NULL
) group
= "";
1545 if (host
== NULL
) host
= "";
1546 if (user
== NULL
) user
= "";
1547 if (domain
== NULL
) domain
= "";
1549 request
= kvbuf_query("ksksksks", "netgroup", group
, "host", host
, "user", user
, "domain", domain
);
1550 if (request
== NULL
) return 0;
1553 status
= LI_DSLookupQuery(proc
, request
, &reply
);
1554 kvbuf_free(request
);
1556 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
)) return 0;
1558 is_innetgr
= check_innetgr(reply
);
1560 kvarray_free(reply
);
1566 ds_alias_byname(si_mod_t
*si
, const char *name
)
1568 static int proc
= -1;
1572 request
= kvbuf_query_key_val("name", name
);
1573 if (request
== NULL
) return NULL
;
1575 item
= ds_item(si
, CATEGORY_ALIAS
, "alias_getbyname", &proc
, NULL
, extract_alias
, request
);
1577 kvbuf_free(request
);
1582 ds_alias_all(si_mod_t
*si
)
1584 static int proc
= -1;
1586 return ds_list(si
, CATEGORY_ALIAS
, "alias_getent", &proc
, NULL
, extract_alias
, NULL
);
1590 ds_host_byname(si_mod_t
*si
, const char *name
, int af
, const char *ignored
, uint32_t *err
)
1592 static int proc
= -1;
1595 uint32_t want4
, want6
;
1598 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
1602 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1609 cat
= CATEGORY_HOST_IPV4
;
1615 else if (af
== AF_INET6
)
1618 cat
= CATEGORY_HOST_IPV6
;
1622 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1626 request
= kvbuf_query("kskuku", "name", name
, "ipv4", want4
, "ipv6", want6
);
1627 if (request
== NULL
)
1629 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1633 item
= ds_item(si
, cat
, "gethostbyname", &proc
, NULL
, extract_host
, request
);
1635 if ((item
== NULL
) && (err
!= NULL
)) *err
= SI_STATUS_H_ERRNO_HOST_NOT_FOUND
;
1637 kvbuf_free(request
);
1642 ds_host_byaddr(si_mod_t
*si
, const void *addr
, int af
, const char *ignored
, uint32_t *err
)
1644 static int proc
= -1;
1647 struct in_addr addr4
;
1648 struct in6_addr addr6
;
1649 char val
[64 + 1 + IF_NAMESIZE
];
1653 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
1655 cat
= CATEGORY_HOST_IPV4
;
1657 memset(&addr4
, 0, sizeof(struct in_addr
));
1658 memset(&addr6
, 0, sizeof(struct in6_addr
));
1659 memset(val
, 0, sizeof(val
));
1661 want
= WANT_A4_ONLY
;
1665 memcpy(&addr4
.s_addr
, addr
, IPV4_ADDR_LEN
);
1666 if (inet_ntop(af
, &addr4
, val
, sizeof(val
)) == NULL
)
1668 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1672 else if (af
== AF_INET6
)
1674 want
= WANT_A6_ONLY
;
1675 cat
= CATEGORY_HOST_IPV6
;
1676 memcpy(&addr6
, addr
, IPV6_ADDR_LEN
);
1677 if (inet_ntop(af
, &addr6
, val
, sizeof(val
)) == NULL
)
1679 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1685 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1689 request
= kvbuf_query("ksku", "address", val
, "family", af
);
1690 if (request
== NULL
)
1692 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1696 item
= ds_item(si
, cat
, "gethostbyaddr", &proc
, &want
, extract_host
, request
);
1698 if ((item
== NULL
) && (err
!= NULL
)) *err
= SI_STATUS_H_ERRNO_HOST_NOT_FOUND
;
1700 kvbuf_free(request
);
1705 ds_host_all(si_mod_t
*si
)
1707 static int proc
= -1;
1709 return ds_list(si
, CATEGORY_HOST_IPV4
, "gethostent", &proc
, NULL
, extract_host
, NULL
);
1713 ds_network_byname(si_mod_t
*si
, const char *name
)
1715 static int proc
= -1;
1719 request
= kvbuf_query_key_val("name", name
);
1720 if (request
== NULL
) return NULL
;
1722 item
= ds_item(si
, CATEGORY_NETWORK
, "getnetbyname", &proc
, NULL
, extract_network
, request
);
1724 kvbuf_free(request
);
1729 ds_network_byaddr(si_mod_t
*si
, uint32_t addr
)
1731 static int proc
= -1;
1732 unsigned char f1
, f2
, f3
;
1743 if (f3
!= 0) snprintf(val
, sizeof(val
), "%u.%u.%u", f3
, f2
, f1
);
1744 else if (f2
!= 0) snprintf(val
, sizeof(val
), "%u.%u", f2
, f1
);
1745 else snprintf(val
, sizeof(val
), "%u", f1
);
1747 request
= kvbuf_query_key_val("net", val
);
1748 if (request
== NULL
) return NULL
;
1750 item
= ds_item(si
, CATEGORY_NETWORK
, "getnetbyaddr", &proc
, NULL
, extract_network
, request
);
1752 kvbuf_free(request
);
1757 ds_network_all(si_mod_t
*si
)
1759 static int proc
= -1;
1761 return ds_list(si
, CATEGORY_NETWORK
, "getnetent", &proc
, NULL
, extract_network
, NULL
);
1765 ds_service_byname(si_mod_t
*si
, const char *name
, const char *proto
)
1767 static int proc
= -1;
1772 if (name
== NULL
) name
= "";
1773 if (proto
== NULL
) proto
= "";
1775 /* Check our local service cache (see ds_addrinfo). */
1776 item
= pthread_getspecific(_ds_serv_cache_key
);
1779 s
= (struct servent
*)((uintptr_t)item
+ sizeof(si_item_t
));
1780 if (string_equal(name
, s
->s_name
)) return si_item_retain(item
);
1783 request
= kvbuf_query("ksks", "name", name
, "proto", proto
);
1784 if (request
== NULL
) return NULL
;
1786 item
= ds_item(si
, CATEGORY_SERVICE
, "getservbyname", &proc
, NULL
, extract_service
, request
);
1788 kvbuf_free(request
);
1793 ds_service_byport(si_mod_t
*si
, int port
, const char *proto
)
1795 static int proc
= -1;
1801 if (proto
== NULL
) proto
= "";
1804 snprintf(val
, sizeof(val
), "%d", ntohs(sport
));
1806 request
= kvbuf_query("ksks", "port", val
, "proto", proto
);
1807 if (request
== NULL
) return NULL
;
1809 item
= ds_item(si
, CATEGORY_SERVICE
, "getservbyport", &proc
, NULL
, extract_service
, request
);
1811 kvbuf_free(request
);
1816 ds_service_all(si_mod_t
*si
)
1818 static int proc
= -1;
1820 return ds_list(si
, CATEGORY_SERVICE
, "getservent", &proc
, NULL
, extract_service
, NULL
);
1824 ds_protocol_byname(si_mod_t
*si
, const char *name
)
1826 static int proc
= -1;
1830 request
= kvbuf_query_key_val("name", name
);
1831 if (request
== NULL
) return NULL
;
1833 item
= ds_item(si
, CATEGORY_PROTOCOL
, "getprotobyname", &proc
, NULL
, extract_protocol
, request
);
1835 kvbuf_free(request
);
1840 ds_protocol_bynumber(si_mod_t
*si
, int number
)
1842 static int proc
= -1;
1847 snprintf(val
, sizeof(val
), "%d", number
);
1848 request
= kvbuf_query_key_val("number", val
);
1849 if (request
== NULL
) return NULL
;
1851 item
= ds_item(si
, CATEGORY_PROTOCOL
, "getprotobynumber", &proc
, NULL
, extract_protocol
, request
);
1853 kvbuf_free(request
);
1858 ds_protocol_all(si_mod_t
*si
)
1860 static int proc
= -1;
1862 return ds_list(si
, CATEGORY_PROTOCOL
, "getprotoent", &proc
, NULL
, extract_protocol
, NULL
);
1866 ds_rpc_byname(si_mod_t
*si
, const char *name
)
1868 static int proc
= -1;
1872 request
= kvbuf_query_key_val("name", name
);
1873 if (request
== NULL
) return NULL
;
1875 item
= ds_item(si
, CATEGORY_RPC
, "getrpcbyname", &proc
, NULL
, extract_rpc
, request
);
1877 kvbuf_free(request
);
1882 ds_rpc_bynumber(si_mod_t
*si
, int number
)
1884 static int proc
= -1;
1889 snprintf(val
, sizeof(val
), "%u", (uint32_t)number
);
1890 request
= kvbuf_query_key_val("number", val
);
1891 if (request
== NULL
) return NULL
;
1893 item
= ds_item(si
, CATEGORY_RPC
, "getrpcbynumber", &proc
, NULL
, extract_rpc
, request
);
1895 kvbuf_free(request
);
1900 ds_rpc_all(si_mod_t
*si
)
1902 static int proc
= -1;
1904 return ds_list(si
, CATEGORY_RPC
, "getrpcent", &proc
, NULL
, extract_rpc
, NULL
);
1908 ds_fs_byspec(si_mod_t
*si
, const char *name
)
1910 static int proc
= -1;
1914 request
= kvbuf_query_key_val("name", name
);
1915 if (request
== NULL
) return NULL
;
1917 item
= ds_item(si
, CATEGORY_FS
, "getfsbyname", &proc
, NULL
, extract_fstab
, request
);
1919 kvbuf_free(request
);
1924 ds_fs_all(si_mod_t
*si
)
1926 static int proc
= -1;
1928 return ds_list(si
, CATEGORY_FS
, "getfsent", &proc
, NULL
, extract_fstab
, NULL
);
1932 ds_fs_byfile(si_mod_t
*si
, const char *name
)
1939 if (name
== NULL
) return NULL
;
1941 list
= ds_fs_all(si
);
1942 if (list
== NULL
) return NULL
;
1945 for (i
= 0; (i
< list
->count
) && (item
== NULL
); i
++)
1947 f
= (struct fstab
*)((uintptr_t)(list
->entry
[i
]) + sizeof(si_item_t
));
1948 if (string_equal(name
, f
->fs_file
)) item
= si_item_retain(list
->entry
[i
]);
1951 si_list_release(list
);
1956 ds_mac_byname(si_mod_t
*si
, const char *name
)
1958 static int proc
= -1;
1962 request
= kvbuf_query_key_val("name", name
);
1963 if (request
== NULL
) return NULL
;
1965 item
= ds_item(si
, CATEGORY_MAC
, "getmacbyname", &proc
, (void *)name
, extract_mac_mac
, request
);
1967 kvbuf_free(request
);
1972 ds_mac_bymac(si_mod_t
*si
, const char *mac
)
1974 static int proc
= -1;
1979 cmac
= si_standardize_mac_address(mac
);
1980 if (cmac
== NULL
) return NULL
;
1982 request
= kvbuf_query_key_val("mac", cmac
);
1983 if (request
== NULL
) return NULL
;
1985 item
= ds_item(si
, CATEGORY_MAC
, "gethostbymac", &proc
, cmac
, extract_mac_name
, request
);
1988 kvbuf_free(request
);
1993 ds_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 *ignored
, uint32_t *err
)
1995 static int proc
= -1;
1996 si_list_t
*list
, *out
;
1998 kvbuf_t
*request
= NULL
;
2000 kvarray_t
*reply
= NULL
;
2001 kern_return_t status
= 0;
2003 int i
, k
, kcount
, d
;
2007 char *h_name
= NULL
;
2008 int h_aliases_cnt
= 0;
2009 const char **h_aliases
= NULL
;
2010 struct in_addr
*a4
= NULL
;
2011 struct in6_addr
*a6
= NULL
;
2015 const char *s_name
= NULL
;
2016 int s_aliases_cnt
= 0;
2017 const char **s_aliases
= NULL
;
2018 uint16_t s_port
= 0;
2019 const char *s_proto
= NULL
;
2020 const char *protoname
;
2023 int numericserv
= ((flags
& AI_NUMERICSERV
) != 0);
2024 int numerichost
= ((flags
& AI_NUMERICHOST
) != 0);
2031 wantv4
= ((family
!= AF_INET6
) || (flags
& AI_V4MAPPED
));
2032 wantv6
= (family
!= AF_INET
);
2035 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
2039 status
= LI_DSLookupGetProcedureNumber("gethostbyname_service", &proc
);
2040 if (status
!= KERN_SUCCESS
)
2042 if (err
!= NULL
) *err
= SI_STATUS_EAI_SYSTEM
;
2047 /* look up canonical name of numeric host */
2048 if ((numerichost
== 1) && (flags
& AI_CANONNAME
) && (node
!= NULL
))
2050 item
= si_host_byaddr(si
, node
, family
, NULL
, NULL
);
2053 h
= (struct hostent
*)((uintptr_t)item
+ sizeof(si_item_t
));
2054 h_name
= strdup(h
->h_name
);
2055 si_item_release(item
);
2059 if (numericserv
== 1)
2061 s_port
= *(int16_t *)serv
;
2064 if ((numericserv
== 0) || (numerichost
== 0))
2066 request
= kvbuf_new();
2067 if (request
!= NULL
)
2069 kvbuf_add_dict(request
);
2071 if (numerichost
== 0)
2073 kvbuf_add_key(request
, "name");
2074 kvbuf_add_val(request
, node
);
2075 kvbuf_add_key(request
, "ipv4");
2076 kvbuf_add_val(request
, wantv4
? "1" : "0");
2077 kvbuf_add_key(request
, "ipv6");
2078 kvbuf_add_val(request
, wantv6
? "1" : "0");
2081 if (numericserv
== 0)
2084 if (proto
== IPPROTO_UDP
) protoname
= "udp";
2085 if (proto
== IPPROTO_TCP
) protoname
= "tcp";
2087 kvbuf_add_key(request
, "s_name");
2088 kvbuf_add_val(request
, serv
);
2089 if (protoname
!= NULL
)
2091 kvbuf_add_key(request
, "s_proto");
2092 kvbuf_add_val(request
, protoname
);
2096 status
= LI_DSLookupQuery(proc
, request
, &reply
);
2097 kvbuf_free(request
);
2101 if (err
!= NULL
) *err
= SI_STATUS_EAI_SYSTEM
;
2105 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
))
2111 for (d
= 0; d
< reply
->count
; d
++)
2113 dict
= reply
->dict
+ d
;
2114 kcount
= dict
->kcount
;
2116 for (k
= 0; k
< kcount
; k
++)
2118 if (string_equal(dict
->key
[k
], "h_name"))
2120 if (dict
->vcount
[k
] == 0) continue;
2121 h_name
= strdup(dict
->val
[k
][0]);
2123 else if (string_equal(dict
->key
[k
], "h_aliases"))
2125 h_aliases_cnt
= dict
->vcount
[k
];
2126 h_aliases
= (const char **)calloc(h_aliases_cnt
, sizeof(char *));
2127 if (h_aliases
== NULL
) h_aliases_cnt
= 0;
2129 for (i
= 0; i
< h_aliases_cnt
; ++i
)
2131 h_aliases
[i
] = dict
->val
[k
][i
];
2134 else if (wantv4
&& (string_equal(dict
->key
[k
], "h_ipv4_addr_list")))
2136 a4_cnt
= dict
->vcount
[k
];
2137 a4
= calloc(a4_cnt
, sizeof(struct in_addr
));
2138 if (a4
== NULL
) a4_cnt
= 0;
2140 for (i
= 0; i
< a4_cnt
; ++i
)
2142 memset(&a4
[i
], 0, sizeof(struct in_addr
));
2143 inet_pton(AF_INET
, dict
->val
[k
][i
], &a4
[i
]);
2146 else if (wantv6
&& (string_equal(dict
->key
[k
], "h_ipv6_addr_list")))
2148 a6_cnt
= dict
->vcount
[k
];
2149 a6
= calloc(a6_cnt
, sizeof(struct in6_addr
));
2150 if (a6
== NULL
) a6_cnt
= 0;
2152 for (i
= 0; i
< a6_cnt
; ++i
)
2154 memset(&a6
[i
], 0, sizeof(struct in6_addr
));
2155 inet_pton(AF_INET6
, dict
->val
[k
][i
], &a6
[i
]);
2158 else if (string_equal(dict
->key
[k
], "s_name"))
2160 if (dict
->vcount
[k
] == 0) continue;
2161 s_name
= dict
->val
[k
][0];
2163 else if (string_equal(dict
->key
[k
], "s_port"))
2165 if (dict
->vcount
[k
] == 0) continue;
2166 s_port
= atoi(dict
->val
[k
][0]);
2168 else if (string_equal(dict
->key
[k
], "s_aliases"))
2170 s_aliases_cnt
= dict
->vcount
[k
];
2171 s_aliases
= (const char **)calloc(s_aliases_cnt
+1, sizeof(char *));
2172 if (s_aliases
== NULL
) s_aliases_cnt
= 0;
2174 for (i
= 0; i
< s_aliases_cnt
; ++i
)
2176 s_aliases
[i
] = dict
->val
[k
][i
];
2179 else if (string_equal(dict
->key
[k
], "s_proto"))
2181 if (dict
->vcount
[k
] == 0) continue;
2182 s_proto
= dict
->val
[k
][0];
2187 kvarray_free(reply
);
2189 /* check if we actually got back what we wanted */
2190 if (((wantv4
|| wantv6
) && (a4_cnt
== 0) && (a6_cnt
== 0)) || ((serv
!= NULL
) && (s_port
== 0)))
2192 if (err
!= NULL
) *err
= SI_STATUS_EAI_NONAME
;
2204 * Cache the service entry regardless of whether there is a host match.
2205 * This allows later modules to get the service entry quickly.
2206 * This should really be part of the general cache mechanism, but that's
2207 * not currently visible outside of the search module.
2209 if ((s_name
!= NULL
) && (s_port
!= 0))
2211 port
= htons(s_port
);
2213 item
= pthread_getspecific(_ds_serv_cache_key
);
2216 s
= (struct servent
*)((uintptr_t)item
+ sizeof(si_item_t
));
2217 if ((port
!= s
->s_port
) || string_not_equal(s_name
, s
->s_name
))
2219 si_item_release(item
);
2226 item
= LI_ils_create("L4488s*4s", (unsigned long)si
, CATEGORY_SERVICE
, 1, (uint64_t)1, (uint64_t)1, s_name
, s_aliases
, port
, s_proto
);
2227 pthread_setspecific(_ds_serv_cache_key
, item
);
2231 /* Construct the addrinfo list from the returned addresses (if found). */
2233 for (i
= 0; i
< a6_cnt
; i
++)
2235 list
= si_addrinfo_list(si
, flags
, socktype
, proto
, NULL
, &a6
[i
], s_port
, scope
, NULL
, h_name
);
2236 out
= si_list_concat(out
, list
);
2237 si_list_release(list
);
2240 for (i
= 0; i
< a4_cnt
; i
++)
2242 list
= si_addrinfo_list(si
, flags
, socktype
, proto
, &a4
[i
], NULL
, s_port
, 0, h_name
, NULL
);
2243 out
= si_list_concat(out
, list
);
2244 si_list_release(list
);
2257 ds_is_valid(si_mod_t
*si
, si_item_t
*item
)
2260 ds_si_private_t
*pp
;
2262 uint32_t oldval
, newval
;
2264 if (si
== NULL
) return 0;
2265 if (item
== NULL
) return 0;
2266 if (si
->name
== NULL
) return 0;
2267 if (item
->src
== NULL
) return 0;
2269 pp
= (ds_si_private_t
*)si
->private;
2270 if (pp
== NULL
) return 0;
2272 src
= (si_mod_t
*)item
->src
;
2274 if (src
->name
== NULL
) return 0;
2275 if (string_not_equal(si
->name
, src
->name
)) return 0;
2277 /* check global invalidation */
2278 oldval
= item
->validation_a
;
2280 status
= notify_peek(pp
->notify_token_global
, &newval
);
2281 if (status
!= NOTIFY_STATUS_OK
) return 0;
2283 newval
= ntohl(newval
);
2284 if (oldval
!= newval
) return 0;
2286 oldval
= item
->validation_b
;
2288 if (item
->type
== CATEGORY_USER
) status
= notify_peek(pp
->notify_token_user
, &newval
);
2289 else if (item
->type
== CATEGORY_GROUP
) status
= notify_peek(pp
->notify_token_group
, &newval
);
2290 else if (item
->type
== CATEGORY_HOST_IPV4
) status
= notify_peek(pp
->notify_token_host
, &newval
);
2291 else if (item
->type
== CATEGORY_HOST_IPV6
) status
= notify_peek(pp
->notify_token_host
, &newval
);
2292 else if (item
->type
== CATEGORY_SERVICE
) status
= notify_peek(pp
->notify_token_service
, &newval
);
2295 if (status
!= NOTIFY_STATUS_OK
) return 0;
2297 newval
= ntohl(newval
);
2298 if (oldval
!= newval
) return 0;
2304 si_module_static_ds(void)
2306 static const struct si_mod_vtable_s ds_vtable
=
2308 .sim_is_valid
= &ds_is_valid
,
2310 .sim_user_byname
= &ds_user_byname
,
2311 .sim_user_byuid
= &ds_user_byuid
,
2312 .sim_user_all
= &ds_user_all
,
2314 .sim_group_byname
= &ds_group_byname
,
2315 .sim_group_bygid
= &ds_group_bygid
,
2316 .sim_group_all
= &ds_group_all
,
2318 .sim_grouplist
= &ds_grouplist
,
2320 .sim_netgroup_byname
= &ds_netgroup_byname
,
2321 .sim_in_netgroup
= &ds_in_netgroup
,
2323 .sim_alias_byname
= &ds_alias_byname
,
2324 .sim_alias_all
= &ds_alias_all
,
2326 .sim_host_byname
= &ds_host_byname
,
2327 .sim_host_byaddr
= &ds_host_byaddr
,
2328 .sim_host_all
= &ds_host_all
,
2330 .sim_network_byname
= &ds_network_byname
,
2331 .sim_network_byaddr
= &ds_network_byaddr
,
2332 .sim_network_all
= &ds_network_all
,
2334 .sim_service_byname
= &ds_service_byname
,
2335 .sim_service_byport
= &ds_service_byport
,
2336 .sim_service_all
= &ds_service_all
,
2338 .sim_protocol_byname
= &ds_protocol_byname
,
2339 .sim_protocol_bynumber
= &ds_protocol_bynumber
,
2340 .sim_protocol_all
= &ds_protocol_all
,
2342 .sim_rpc_byname
= &ds_rpc_byname
,
2343 .sim_rpc_bynumber
= &ds_rpc_bynumber
,
2344 .sim_rpc_all
= &ds_rpc_all
,
2346 .sim_fs_byspec
= &ds_fs_byspec
,
2347 .sim_fs_byfile
= &ds_fs_byfile
,
2348 .sim_fs_all
= &ds_fs_all
,
2350 .sim_mac_byname
= &ds_mac_byname
,
2351 .sim_mac_bymac
= &ds_mac_bymac
,
2353 /* si_mac_all not supported */
2354 .sim_mac_all
= NULL
,
2356 /* si_addrinfo not supported */
2357 .sim_wants_addrinfo
= NULL
,
2358 .sim_addrinfo
= NULL
,
2361 static si_mod_t si
=
2365 .flags
= SI_MOD_FLAG_STATIC
,
2368 .vtable
= &ds_vtable
,
2371 static dispatch_once_t once
;
2372 dispatch_once(&once
, ^{
2373 pthread_key_create(&_ds_serv_cache_key
, _ds_serv_cache_free
);
2375 si
.name
= strdup("ds");
2376 ds_si_private_t
*pp
= calloc(1, sizeof(ds_si_private_t
));
2380 pp
->notify_token_global
= -1;
2381 pp
->notify_token_user
= -1;
2382 pp
->notify_token_group
= -1;
2383 pp
->notify_token_host
= -1;
2384 pp
->notify_token_service
= -1;
2388 * Don't register for notifications if the cache is disabled.
2389 * notifyd (notably) disables the cache to prevent deadlocks.
2391 if (gL1CacheEnabled
!= 0)
2394 * Errors in registering for cache invalidation notifications are ignored.
2395 * If there are failures, the tokens remain set to -1 which just causes
2396 * cached items to be invalidated.
2398 notify_register_check(kNotifyDSCacheInvalidation
, &(pp
->notify_token_global
));
2399 notify_register_check(kNotifyDSCacheInvalidationUser
, &(pp
->notify_token_user
));
2400 notify_register_check(kNotifyDSCacheInvalidationGroup
, &(pp
->notify_token_group
));
2401 notify_register_check(kNotifyDSCacheInvalidationHost
, &(pp
->notify_token_host
));
2402 notify_register_check(kNotifyDSCacheInvalidationService
, &(pp
->notify_token_service
));
2411 #endif /* DS_AVAILABLE */