2 * Copyright (c) 2008-2009 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@
29 #include <arpa/inet.h>
31 #include <mach/mach.h>
40 #include <si_module.h>
41 #include <netdb_async.h>
43 #include <servers/bootstrap.h>
44 #include <DSlibinfoMIG.h>
45 #include <DSmemberdMIG.h>
51 #define IPPROTO_UNSPEC 0
53 #define IPV6_ADDR_LEN 16
54 #define IPV4_ADDR_LEN 4
56 #define WANT_NOTHING 0
57 #define WANT_A4_ONLY 1
58 #define WANT_A6_ONLY 2
59 #define WANT_A6_PLUS_MAPPED_A4 3
60 #define WANT_MAPPED_A4_ONLY 4
62 /* ONLY TO BE USED BY getipv6nodebyaddr */
63 #define WANT_A6_OR_MAPPED_A4_IF_NO_A6 5
65 #define DS_NOTIFICATION_KEY_GLOBAL "com.apple.system.DirectoryService.InvalidateCache"
66 #define DS_NOTIFICATION_KEY_USER "com.apple.system.DirectoryService.InvalidateCache.user"
67 #define DS_NOTIFICATION_KEY_GROUP "com.apple.system.DirectoryService.InvalidateCache.group"
68 #define DS_NOTIFICATION_KEY_HOST "com.apple.system.DirectoryService.InvalidateCache.host"
69 #define DS_NOTIFICATION_KEY_SERVICE "com.apple.system.DirectoryService.InvalidateCache.service"
71 #define MAX_LOOKUP_ATTEMPTS 10
73 #define INET_NTOP_AF_INET_OFFSET 4
74 #define INET_NTOP_AF_INET6_OFFSET 8
76 extern mach_port_t _ds_port
;
77 extern int _ds_running();
78 extern uint32_t gL1CacheEnabled
;
80 static pthread_key_t _ds_serv_cache_key
= 0;
83 _ds_serv_cache_free(void *x
)
85 if (x
!= NULL
) si_item_release(x
);
88 __private_extern__ kern_return_t
89 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
)
94 __private_extern__ kern_return_t
95 LI_DSLookupGetProcedureNumber(const char *name
, int32_t *procno
)
98 security_token_t token
;
101 if (name
== NULL
) return KERN_FAILURE
;
103 len
= strlen(name
) + 1;
104 if (len
== 1) return KERN_FAILURE
;
109 if (_ds_running() == 0) return KERN_FAILURE
;
110 if (_ds_port
== MACH_PORT_NULL
) return KERN_FAILURE
;
112 status
= MIG_SERVER_DIED
;
113 for (n
= 0; (_ds_port
!= MACH_PORT_NULL
) && (status
== MIG_SERVER_DIED
) && (n
< MAX_LOOKUP_ATTEMPTS
); n
++)
115 status
= libinfoDSmig_GetProcedureNumber(_ds_port
, (char *)name
, procno
, &token
);
117 if (status
== MACH_SEND_INVALID_DEST
)
119 mach_port_mod_refs(mach_task_self(), _ds_port
, MACH_PORT_RIGHT_SEND
, -1);
120 status
= bootstrap_look_up(bootstrap_port
, kDSStdMachDSLookupPortName
, &_ds_port
);
121 if ((status
!= BOOTSTRAP_SUCCESS
) && (status
!= BOOTSTRAP_UNKNOWN_SERVICE
)) _ds_port
= MACH_PORT_NULL
;
122 status
= MIG_SERVER_DIED
;
126 if (status
!= KERN_SUCCESS
)
129 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupGetProcedureNumber %s status %u", name
, status
);
134 if (token
.val
[0] != 0)
137 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupGetProcedureNumber %s auth failure uid=%d", name
, token
.val
[0]);
143 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupGetProcedureNumber %s = %d", name
, *procno
);
148 __private_extern__ kern_return_t
149 LI_DSLookupQuery(int32_t procno
, kvbuf_t
*request
, kvarray_t
**reply
)
151 kern_return_t status
;
152 security_token_t token
;
154 mach_msg_type_number_t illen
, oolen
;
155 char ilbuf
[MAX_MIG_INLINE_DATA
];
159 if (reply
== NULL
) return KERN_FAILURE
;
160 if ((request
!= NULL
) && ((request
->databuf
== NULL
) || (request
->datalen
== 0))) return KERN_FAILURE
;
166 if (_ds_running() == 0) return KERN_FAILURE
;
167 if (_ds_port
== MACH_PORT_NULL
) return KERN_FAILURE
;
169 status
= MIG_SERVER_DIED
;
170 for (n
= 0; (_ds_port
!= MACH_PORT_NULL
) && (status
== MIG_SERVER_DIED
) && (n
< MAX_LOOKUP_ATTEMPTS
); n
++)
178 status
= libinfoDSmig_Query(_ds_port
, procno
, request
->databuf
, request
->datalen
, ilbuf
, &illen
, &oobuf
, &oolen
, &token
);
182 status
= libinfoDSmig_Query(_ds_port
, procno
, "", 0, ilbuf
, &illen
, &oobuf
, &oolen
, &token
);
185 if (status
== MACH_SEND_INVALID_DEST
)
187 mach_port_mod_refs(mach_task_self(), _ds_port
, MACH_PORT_RIGHT_SEND
, -1);
188 status
= bootstrap_look_up(bootstrap_port
, kDSStdMachDSLookupPortName
, &_ds_port
);
189 if ((status
!= BOOTSTRAP_SUCCESS
) && (status
!= BOOTSTRAP_UNKNOWN_SERVICE
)) _ds_port
= MACH_PORT_NULL
;
190 status
= MIG_SERVER_DIED
;
194 if (status
!= KERN_SUCCESS
)
197 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupQuery %d status %u", procno
, status
);
202 if (token
.val
[0] != 0)
205 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupQuery %d auth failure uid=%d", procno
, token
.val
[0]);
207 if (oolen
> 0) vm_deallocate(mach_task_self(), (vm_address_t
)oobuf
, oolen
);
211 out
= (kvbuf_t
*)calloc(1, sizeof(kvbuf_t
));
214 if (oolen
> 0) vm_deallocate(mach_task_self(), (vm_address_t
)oobuf
, oolen
);
220 out
->datalen
= oolen
;
221 out
->databuf
= malloc(oolen
);
222 if (out
->databuf
== NULL
)
226 vm_deallocate(mach_task_self(), (vm_address_t
)oobuf
, oolen
);
230 memcpy(out
->databuf
, (char *)oobuf
, oolen
);
231 vm_deallocate(mach_task_self(), (vm_address_t
)oobuf
, oolen
);
235 out
->datalen
= illen
;
236 out
->databuf
= malloc(illen
);
237 if (out
->databuf
== NULL
)
244 memcpy(out
->databuf
, ilbuf
, illen
);
247 *reply
= kvbuf_decode(out
);
250 /* DS returned no data */
256 asl_log(NULL
, NULL
, ASL_LEVEL_DEBUG
, "_DSLookupQuery %d status OK", procno
);
262 uint32_t notify_peek(int token
, uint32_t *val
);
266 int notify_token_global
;
267 int notify_token_user
;
268 int notify_token_group
;
269 int notify_token_host
;
270 int notify_token_service
;
274 audit_token_uid(audit_token_t a
)
277 * This should really call audit_token_to_au32,
278 * but that's in libbsm, not in a Libsystem library.
280 return (uid_t
)a
.val
[1];
284 ds_get_validation(si_mod_t
*si
, uint64_t *a
, uint64_t *b
, int cat
)
290 if (si
== NULL
) return;
292 pp
= (ds_si_private_t
*)si
->private;
293 if (pp
== NULL
) return;
298 status
= notify_peek(pp
->notify_token_global
, &peek
);
299 if (status
== NOTIFY_STATUS_OK
) *a
= ntohl(peek
);
306 status
= NOTIFY_STATUS_FAILED
;
308 if (cat
== CATEGORY_USER
) status
= notify_peek(pp
->notify_token_user
, &peek
);
309 else if (cat
== CATEGORY_GROUP
) status
= notify_peek(pp
->notify_token_group
, &peek
);
310 else if (cat
== CATEGORY_GROUPLIST
) status
= notify_peek(pp
->notify_token_group
, &peek
);
311 else if (cat
== CATEGORY_HOST_IPV4
) status
= notify_peek(pp
->notify_token_host
, &peek
);
312 else if (cat
== CATEGORY_HOST_IPV6
) status
= notify_peek(pp
->notify_token_host
, &peek
);
313 else if (cat
== CATEGORY_SERVICE
) status
= notify_peek(pp
->notify_token_service
, &peek
);
315 if (status
== NOTIFY_STATUS_OK
) *b
= ntohl(peek
);
320 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
)
325 kern_return_t status
;
330 status
= LI_DSLookupGetProcedureNumber(procname
, procnum
);
331 if (status
!= KERN_SUCCESS
) return NULL
;
335 ds_get_validation(si
, &va
, &vb
, cat
);
336 status
= LI_DSLookupQuery(*procnum
, request
, &reply
);
338 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
)) return NULL
;
341 while (reply
->curr
< reply
->count
)
343 item
= extract(si
, reply
, extra
, va
, vb
);
344 list
= si_list_add(list
, item
);
345 si_item_release(item
);
354 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
)
358 kern_return_t status
;
363 status
= LI_DSLookupGetProcedureNumber(procname
, procnum
);
364 if (status
!= KERN_SUCCESS
) return NULL
;
368 ds_get_validation(si
, &va
, &vb
, cat
);
369 status
= LI_DSLookupQuery(*procnum
, request
, &reply
);
371 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
)) return NULL
;
373 item
= extract(si
, reply
, extra
, va
, vb
);
380 * Extract the next user entry from a kvarray.
383 extract_user(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
386 uint32_t d
, k
, kcount
;
388 if (si
== NULL
) return NULL
;
389 if (in
== NULL
) return NULL
;
394 if (d
>= in
->count
) return NULL
;
396 memset(&tmp
, 0, sizeof(struct passwd
));
401 kcount
= in
->dict
[d
].kcount
;
403 for (k
= 0; k
< kcount
; k
++)
405 if (string_equal(in
->dict
[d
].key
[k
], "pw_name"))
407 if (tmp
.pw_name
!= NULL
) continue;
408 if (in
->dict
[d
].vcount
[k
] == 0) continue;
410 tmp
.pw_name
= (char *)in
->dict
[d
].val
[k
][0];
412 else if (string_equal(in
->dict
[d
].key
[k
], "pw_passwd"))
414 if (tmp
.pw_passwd
!= NULL
) continue;
415 if (in
->dict
[d
].vcount
[k
] == 0) continue;
417 tmp
.pw_passwd
= (char *)in
->dict
[d
].val
[k
][0];
419 else if (string_equal(in
->dict
[d
].key
[k
], "pw_uid"))
421 if (in
->dict
[d
].vcount
[k
] == 0) continue;
422 tmp
.pw_uid
= atoi(in
->dict
[d
].val
[k
][0]);
424 else if (string_equal(in
->dict
[d
].key
[k
], "pw_gid"))
426 if (in
->dict
[d
].vcount
[k
] == 0) continue;
427 tmp
.pw_gid
= atoi(in
->dict
[d
].val
[k
][0]);
429 else if (string_equal(in
->dict
[d
].key
[k
], "pw_change"))
431 if (in
->dict
[d
].vcount
[k
] == 0) continue;
432 tmp
.pw_change
= atol(in
->dict
[d
].val
[k
][0]);
434 else if (string_equal(in
->dict
[d
].key
[k
], "pw_expire"))
436 if (in
->dict
[d
].vcount
[k
] == 0) continue;
437 tmp
.pw_expire
= atol(in
->dict
[d
].val
[k
][0]);
439 else if (string_equal(in
->dict
[d
].key
[k
], "pw_class"))
441 if (tmp
.pw_class
!= NULL
) continue;
442 if (in
->dict
[d
].vcount
[k
] == 0) continue;
444 tmp
.pw_class
= (char *)in
->dict
[d
].val
[k
][0];
446 else if (string_equal(in
->dict
[d
].key
[k
], "pw_gecos"))
448 if (tmp
.pw_gecos
!= NULL
) continue;
449 if (in
->dict
[d
].vcount
[k
] == 0) continue;
451 tmp
.pw_gecos
= (char *)in
->dict
[d
].val
[k
][0];
453 else if (string_equal(in
->dict
[d
].key
[k
], "pw_dir"))
455 if (tmp
.pw_dir
!= NULL
) continue;
456 if (in
->dict
[d
].vcount
[k
] == 0) continue;
458 tmp
.pw_dir
= (char *)in
->dict
[d
].val
[k
][0];
460 else if (string_equal(in
->dict
[d
].key
[k
], "pw_shell"))
462 if (tmp
.pw_shell
!= NULL
) continue;
463 if (in
->dict
[d
].vcount
[k
] == 0) continue;
465 tmp
.pw_shell
= (char *)in
->dict
[d
].val
[k
][0];
469 if (tmp
.pw_name
== NULL
) tmp
.pw_name
= "";
470 if (tmp
.pw_passwd
== NULL
) tmp
.pw_passwd
= "";
471 if (tmp
.pw_class
== NULL
) tmp
.pw_class
= "";
472 if (tmp
.pw_gecos
== NULL
) tmp
.pw_gecos
= "";
473 if (tmp
.pw_dir
== NULL
) tmp
.pw_dir
= "";
474 if (tmp
.pw_shell
== NULL
) tmp
.pw_shell
= "";
476 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
);
480 extract_group(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
484 uint32_t d
, k
, kcount
;
486 if (si
== NULL
) return NULL
;
487 if (in
== NULL
) return NULL
;
492 if (d
>= in
->count
) return NULL
;
495 memset(&tmp
, 0, sizeof(struct group
));
499 kcount
= in
->dict
[d
].kcount
;
501 for (k
= 0; k
< kcount
; k
++)
503 if (string_equal(in
->dict
[d
].key
[k
], "gr_name"))
505 if (tmp
.gr_name
!= NULL
) continue;
506 if (in
->dict
[d
].vcount
[k
] == 0) continue;
508 tmp
.gr_name
= (char *)in
->dict
[d
].val
[k
][0];
510 else if (string_equal(in
->dict
[d
].key
[k
], "gr_passwd"))
512 if (tmp
.gr_passwd
!= NULL
) continue;
513 if (in
->dict
[d
].vcount
[k
] == 0) continue;
515 tmp
.gr_passwd
= (char *)in
->dict
[d
].val
[k
][0];
517 else if (string_equal(in
->dict
[d
].key
[k
], "gr_gid"))
519 if (in
->dict
[d
].vcount
[k
] == 0) continue;
520 tmp
.gr_gid
= atoi(in
->dict
[d
].val
[k
][0]);
522 else if (string_equal(in
->dict
[d
].key
[k
], "gr_mem"))
524 if (tmp
.gr_mem
!= NULL
) continue;
525 if (in
->dict
[d
].vcount
[k
] == 0) continue;
527 tmp
.gr_mem
= (char **)in
->dict
[d
].val
[k
];
531 if (tmp
.gr_name
== NULL
) tmp
.gr_name
= "";
532 if (tmp
.gr_passwd
== NULL
) tmp
.gr_passwd
= "";
533 if (tmp
.gr_mem
== NULL
) tmp
.gr_mem
= empty
;
535 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
);
539 _free_addr_list(char **l
)
543 if (l
== NULL
) return;
544 for (i
= 0; l
[i
] != NULL
; i
++) free(l
[i
]);
548 /* map ipv4 addresses and append to v6 list */
550 _map_v4(char ***v6
, uint32_t n6
, char **v4
, uint32_t n4
)
555 a6
.__u6_addr
.__u6_addr32
[0] = 0x00000000;
556 a6
.__u6_addr
.__u6_addr32
[1] = 0x00000000;
557 a6
.__u6_addr
.__u6_addr32
[2] = htonl(0x0000ffff);
561 *v6
= (char **)calloc(n4
+ 1, sizeof(char *));
565 *v6
= (char **)reallocf(*v6
, (n6
+ n4
+ 1) * sizeof(char *));
568 if (*v6
== NULL
) return -1;
570 for (i
= 0; i
< n4
; i
++)
572 (*v6
)[n6
] = (char *)calloc(1, IPV6_ADDR_LEN
);
573 if ((*v6
)[n6
] == NULL
) return -1;
575 memcpy(&(a6
.__u6_addr
.__u6_addr32
[3]), v4
[i
], IPV4_ADDR_LEN
);
576 memcpy((*v6
)[n6
], &(a6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
585 extract_netgroup(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
587 const char *host
, *user
, *domain
;
588 uint32_t d
, k
, kcount
;
590 if (si
== NULL
) return NULL
;
591 if (in
== NULL
) return NULL
;
596 if (d
>= in
->count
) return NULL
;
598 kcount
= in
->dict
[d
].kcount
;
604 for (k
= 0; k
< kcount
; k
++)
606 if (string_equal(in
->dict
[d
].key
[k
], "host"))
608 if (host
!= NULL
) continue;
609 if (in
->dict
[d
].vcount
[k
] == 0) continue;
611 host
= (char *)in
->dict
[d
].val
[k
][0];
613 else if (string_equal(in
->dict
[d
].key
[k
], "user"))
615 if (user
!= NULL
) continue;
616 if (in
->dict
[d
].vcount
[k
] == 0) continue;
618 user
= (char *)in
->dict
[d
].val
[k
][0];
620 else if (string_equal(in
->dict
[d
].key
[k
], "domain"))
622 if (domain
!= NULL
) continue;
623 if (in
->dict
[d
].vcount
[k
] == 0) continue;
625 domain
= (char *)in
->dict
[d
].val
[k
][0];
629 if (host
== NULL
) host
= "";
630 if (user
== NULL
) user
= "";
631 if (domain
== NULL
) domain
= "";
633 return (si_item_t
*)LI_ils_create("L4488sss", (unsigned long)si
, CATEGORY_ALIAS
, 1, valid_global
, valid_cat
, host
, user
, domain
);
637 extract_alias(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
641 uint32_t d
, k
, kcount
;
643 if (si
== NULL
) return NULL
;
644 if (in
== NULL
) return NULL
;
649 if (d
>= in
->count
) return NULL
;
652 memset(&tmp
, 0, sizeof(struct group
));
654 kcount
= in
->dict
[d
].kcount
;
656 for (k
= 0; k
< kcount
; k
++)
658 if (string_equal(in
->dict
[d
].key
[k
], "alias_name"))
660 if (tmp
.alias_name
!= NULL
) continue;
661 if (in
->dict
[d
].vcount
[k
] == 0) continue;
663 tmp
.alias_name
= (char *)in
->dict
[d
].val
[k
][0];
665 else if (string_equal(in
->dict
[d
].key
[k
], "alias_members"))
667 if (tmp
.alias_members
!= NULL
) continue;
668 if (in
->dict
[d
].vcount
[k
] == 0) continue;
670 tmp
.alias_members_len
= in
->dict
[d
].vcount
[k
];
671 tmp
.alias_members
= (char **)in
->dict
[d
].val
[k
];
673 else if (string_equal(in
->dict
[d
].key
[k
], "alias_local"))
675 if (in
->dict
[d
].vcount
[k
] == 0) continue;
676 tmp
.alias_local
= atoi(in
->dict
[d
].val
[k
][0]);
680 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
);
684 extract_host(si_mod_t
*si
, kvarray_t
*in
, void *extra
, uint64_t valid_global
, uint64_t valid_cat
)
688 uint32_t i
, d
, k
, kcount
, vcount
, v4count
, v6count
, want
;
689 int status
, addr_len
;
690 int family
, addr_count
;
693 char **v4addrs
, **v6addrs
;
701 addr_len
= sizeof(void *);
703 if (si
== NULL
) return NULL
;
704 if (in
== NULL
) return NULL
;
709 if (d
>= in
->count
) return NULL
;
712 memset(&tmp
, 0, sizeof(struct hostent
));
715 tmp
.h_length
= IPV4_ADDR_LEN
;
718 if (extra
!= NULL
) want
= *(uint32_t *)extra
;
720 if (want
!= WANT_A4_ONLY
)
723 tmp
.h_length
= IPV6_ADDR_LEN
;
726 tmp
.h_addrtype
= family
;
728 kcount
= in
->dict
[d
].kcount
;
730 for (k
= 0; k
< kcount
; k
++)
732 if (string_equal(in
->dict
[d
].key
[k
], "h_name"))
734 if (tmp
.h_name
!= NULL
) continue;
736 vcount
= in
->dict
[d
].vcount
[k
];
737 if (vcount
== 0) continue;
739 tmp
.h_name
= (char *)in
->dict
[d
].val
[k
][0];
741 else if (string_equal(in
->dict
[d
].key
[k
], "h_aliases"))
743 if (tmp
.h_aliases
!= NULL
) continue;
745 vcount
= in
->dict
[d
].vcount
[k
];
746 if (vcount
== 0) continue;
748 tmp
.h_aliases
= (char **)in
->dict
[d
].val
[k
];
750 else if (string_equal(in
->dict
[d
].key
[k
], "h_ipv4_addr_list"))
752 if (v4addrs
!= NULL
) continue;
754 v4count
= in
->dict
[d
].vcount
[k
];
755 if (v4count
== 0) continue;
757 v4addrs
= (char **)calloc(v4count
+ 1, sizeof(char *));
760 _free_addr_list(v6addrs
);
764 for (i
= 0; i
< v4count
; i
++)
766 v4addrs
[i
] = calloc(1, IPV4_ADDR_LEN
);
767 if (v4addrs
[i
] == NULL
)
769 _free_addr_list(v4addrs
);
770 _free_addr_list(v6addrs
);
774 memset(&a4
, 0, sizeof(struct in_addr
));
775 status
= inet_pton(AF_INET
, in
->dict
[d
].val
[k
][i
], &a4
);
778 _free_addr_list(v4addrs
);
779 _free_addr_list(v6addrs
);
783 memcpy(v4addrs
[i
], &a4
, IPV4_ADDR_LEN
);
786 else if (string_equal(in
->dict
[d
].key
[k
], "h_ipv6_addr_list"))
788 if (v6addrs
!= NULL
) continue;
790 v6count
= in
->dict
[d
].vcount
[k
];
791 if (v6count
== 0) continue;
793 v6addrs
= (char **)calloc(v6count
+ 1, sizeof(char *));
796 _free_addr_list(v4addrs
);
800 for (i
= 0; i
< v6count
; i
++)
802 v6addrs
[i
] = calloc(1, IPV6_ADDR_LEN
);
803 if (v6addrs
[i
] == NULL
)
805 _free_addr_list(v4addrs
);
806 _free_addr_list(v6addrs
);
810 memset(&a6
, 0, sizeof(struct in6_addr
));
811 status
= inet_pton(AF_INET6
, in
->dict
[d
].val
[k
][i
], &a6
);
814 _free_addr_list(v4addrs
);
815 _free_addr_list(v6addrs
);
819 memcpy(v6addrs
[i
], &(a6
.__u6_addr
.__u6_addr32
[0]), IPV6_ADDR_LEN
);
824 if (tmp
.h_name
== NULL
) tmp
.h_name
= "";
825 if (tmp
.h_aliases
== NULL
) tmp
.h_aliases
= empty
;
827 if (want
== WANT_A4_ONLY
)
829 _free_addr_list(v6addrs
);
830 if (v4addrs
== NULL
) return NULL
;
832 tmp
.h_addr_list
= v4addrs
;
833 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
);
834 _free_addr_list(v4addrs
);
837 else if ((want
== WANT_A6_ONLY
) || ((want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) && (v6count
> 0)))
839 _free_addr_list(v4addrs
);
840 if (v6addrs
== NULL
) return NULL
;
842 tmp
.h_addr_list
= v6addrs
;
843 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
);
844 _free_addr_list(v6addrs
);
849 * At this point, want is WANT_A6_PLUS_MAPPED_A4, WANT_MAPPED_A4_ONLY,
850 * or WANT_A6_OR_MAPPED_A4_IF_NO_A6. In the last case, there are no ipv6
851 * addresses, so that case degenerates into WANT_MAPPED_A4_ONLY.
853 if (want
== WANT_A6_OR_MAPPED_A4_IF_NO_A6
) want
= WANT_MAPPED_A4_ONLY
;
855 if (want
== WANT_MAPPED_A4_ONLY
)
857 _free_addr_list(v6addrs
);
862 status
= _map_v4(&v6addrs
, v6count
, v4addrs
, v4count
);
863 _free_addr_list(v4addrs
);
866 _free_addr_list(v6addrs
);
870 if (v6addrs
== NULL
) return NULL
;
872 tmp
.h_addr_list
= v6addrs
;
873 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
);
874 _free_addr_list(v6addrs
);
879 extract_network(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
882 uint32_t d
, k
, kcount
;
885 if (si
== NULL
) return NULL
;
886 if (in
== NULL
) return NULL
;
891 if (d
>= in
->count
) return NULL
;
894 memset(&tmp
, 0, sizeof(struct netent
));
896 tmp
.n_addrtype
= AF_INET
;
898 kcount
= in
->dict
[d
].kcount
;
900 for (k
= 0; k
< kcount
; k
++)
902 if (string_equal(in
->dict
[d
].key
[k
], "n_name"))
904 if (tmp
.n_name
!= NULL
) continue;
905 if (in
->dict
[d
].vcount
[k
] == 0) continue;
907 tmp
.n_name
= (char *)in
->dict
[d
].val
[k
][0];
909 else if (string_equal(in
->dict
[d
].key
[k
], "n_net"))
911 if (in
->dict
[d
].vcount
[k
] == 0) continue;
912 tmp
.n_net
= inet_network(in
->dict
[d
].val
[k
][0]);
914 else if (string_equal(in
->dict
[d
].key
[k
], "n_addrtype"))
916 if (in
->dict
[d
].vcount
[k
] == 0) continue;
917 tmp
.n_addrtype
= atoi(in
->dict
[d
].val
[k
][0]);
919 else if (string_equal(in
->dict
[d
].key
[k
], "n_aliases"))
921 if (tmp
.n_aliases
!= NULL
) continue;
922 if (in
->dict
[d
].vcount
[k
] == 0) continue;
924 tmp
.n_aliases
= (char **)in
->dict
[d
].val
[k
];
928 if (tmp
.n_name
== NULL
) tmp
.n_name
= "";
929 if (tmp
.n_aliases
== NULL
) tmp
.n_aliases
= empty
;
931 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
);
935 extract_service(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
939 uint32_t d
, k
, kcount
;
941 if (si
== NULL
) return NULL
;
942 if (in
== NULL
) return NULL
;
947 if (d
>= in
->count
) return NULL
;
950 memset(&tmp
, 0, sizeof(struct servent
));
952 kcount
= in
->dict
[d
].kcount
;
954 for (k
= 0; k
< kcount
; k
++)
956 if (string_equal(in
->dict
[d
].key
[k
], "s_name"))
958 if (tmp
.s_name
!= NULL
) continue;
959 if (in
->dict
[d
].vcount
[k
] == 0) continue;
961 tmp
.s_name
= (char *)in
->dict
[d
].val
[k
][0];
963 else if (string_equal(in
->dict
[d
].key
[k
], "s_aliases"))
965 if (tmp
.s_aliases
!= NULL
) continue;
966 if (in
->dict
[d
].vcount
[k
] == 0) continue;
968 tmp
.s_aliases
= (char **)in
->dict
[d
].val
[k
];
970 else if (string_equal(in
->dict
[d
].key
[k
], "s_port"))
972 if (in
->dict
[d
].vcount
[k
] == 0) continue;
973 tmp
.s_port
= atoi(in
->dict
[d
].val
[k
][0]);
975 else if (string_equal(in
->dict
[d
].key
[k
], "s_proto"))
977 if (tmp
.s_proto
!= NULL
) continue;
978 if (in
->dict
[d
].vcount
[k
] == 0) continue;
980 tmp
.s_proto
= (char *)in
->dict
[d
].val
[k
][0];
984 if (tmp
.s_name
== NULL
) tmp
.s_name
= "";
985 if (tmp
.s_proto
== NULL
) tmp
.s_proto
= "";
986 if (tmp
.s_aliases
== NULL
) tmp
.s_aliases
= empty
;
988 /* strange but correct */
989 tmp
.s_port
= htons(tmp
.s_port
);
991 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
);
995 extract_protocol(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
998 uint32_t d
, k
, kcount
;
1001 if (si
== NULL
) return NULL
;
1002 if (in
== NULL
) return NULL
;
1007 if (d
>= in
->count
) return NULL
;
1010 memset(&tmp
, 0, sizeof(struct protoent
));
1012 kcount
= in
->dict
[d
].kcount
;
1014 for (k
= 0; k
< kcount
; k
++)
1016 if (string_equal(in
->dict
[d
].key
[k
], "p_name"))
1018 if (tmp
.p_name
!= NULL
) continue;
1019 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1021 tmp
.p_name
= (char *)in
->dict
[d
].val
[k
][0];
1023 else if (string_equal(in
->dict
[d
].key
[k
], "p_proto"))
1025 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1026 tmp
.p_proto
= atoi(in
->dict
[d
].val
[k
][0]);
1028 else if (string_equal(in
->dict
[d
].key
[k
], "p_aliases"))
1030 if (tmp
.p_aliases
!= NULL
) continue;
1031 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1033 tmp
.p_aliases
= (char **)in
->dict
[d
].val
[k
];
1037 if (tmp
.p_name
== NULL
) tmp
.p_name
= "";
1038 if (tmp
.p_aliases
== NULL
) tmp
.p_aliases
= empty
;
1040 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
);
1044 extract_rpc(si_mod_t
*si
, kvarray_t
*in
, void *ignored
, uint64_t valid_global
, uint64_t valid_cat
)
1047 uint32_t d
, k
, kcount
;
1050 if (si
== NULL
) return NULL
;
1051 if (in
== NULL
) return NULL
;
1056 if (d
>= in
->count
) return NULL
;
1059 memset(&tmp
, 0, sizeof(struct rpcent
));
1061 kcount
= in
->dict
[d
].kcount
;
1063 for (k
= 0; k
< kcount
; k
++)
1065 if (string_equal(in
->dict
[d
].key
[k
], "r_name"))
1067 if (tmp
.r_name
!= NULL
) continue;
1068 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1070 tmp
.r_name
= (char *)in
->dict
[d
].val
[k
][0];
1072 else if (string_equal(in
->dict
[d
].key
[k
], "r_number"))
1074 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1075 tmp
.r_number
= atoi(in
->dict
[d
].val
[k
][0]);
1077 else if (string_equal(in
->dict
[d
].key
[k
], "r_aliases"))
1079 if (tmp
.r_aliases
!= NULL
) continue;
1080 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1082 tmp
.r_aliases
= (char **)in
->dict
[d
].val
[k
];
1086 if (tmp
.r_name
== NULL
) tmp
.r_name
= "";
1087 if (tmp
.r_aliases
== NULL
) tmp
.r_aliases
= empty
;
1089 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
);
1093 extract_fstab(si_mod_t
*si
, kvarray_t
*in
, void *extra
, uint64_t valid_global
, uint64_t valid_cat
)
1096 uint32_t d
, k
, kcount
;
1099 if (si
== NULL
) return NULL
;
1100 if (in
== NULL
) return NULL
;
1103 if (extra
!= NULL
) file
= (char *)extra
;
1108 if (d
>= in
->count
) return NULL
;
1110 memset(&tmp
, 0, sizeof(struct fstab
));
1112 kcount
= in
->dict
[d
].kcount
;
1114 for (k
= 0; k
< kcount
; k
++)
1116 if (string_equal(in
->dict
[d
].key
[k
], "fs_spec"))
1118 if (tmp
.fs_spec
!= NULL
) continue;
1119 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1121 tmp
.fs_spec
= (char *)in
->dict
[d
].val
[k
][0];
1123 else if (string_equal(in
->dict
[d
].key
[k
], "fs_file"))
1125 if (tmp
.fs_file
!= NULL
) continue;
1126 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1128 tmp
.fs_file
= (char *)in
->dict
[d
].val
[k
][0];
1130 else if (string_equal(in
->dict
[d
].key
[k
], "fs_vfstype"))
1132 if (tmp
.fs_vfstype
!= NULL
) continue;
1133 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1135 tmp
.fs_vfstype
= (char *)in
->dict
[d
].val
[k
][0];
1137 else if (string_equal(in
->dict
[d
].key
[k
], "fs_mntops"))
1139 if (tmp
.fs_mntops
!= NULL
) continue;
1140 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1142 tmp
.fs_mntops
= (char *)in
->dict
[d
].val
[k
][0];
1144 else if (string_equal(in
->dict
[d
].key
[k
], "fs_type"))
1146 if (tmp
.fs_type
!= NULL
) continue;
1147 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1149 tmp
.fs_type
= (char *)in
->dict
[d
].val
[k
][0];
1151 else if (string_equal(in
->dict
[d
].key
[k
], "fs_freq"))
1153 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1154 tmp
.fs_freq
= atoi(in
->dict
[d
].val
[k
][0]);
1156 else if (string_equal(in
->dict
[d
].key
[k
], "fs_passno"))
1158 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1159 tmp
.fs_passno
= atoi(in
->dict
[d
].val
[k
][0]);
1163 if (tmp
.fs_spec
== NULL
) tmp
.fs_spec
= "";
1164 if (tmp
.fs_file
== NULL
) tmp
.fs_file
= "";
1165 if (tmp
.fs_vfstype
== NULL
) tmp
.fs_vfstype
= "";
1166 if (tmp
.fs_mntops
== NULL
) tmp
.fs_mntops
= "";
1167 if (tmp
.fs_type
== NULL
) tmp
.fs_type
= "";
1169 if ((file
!= NULL
) && string_not_equal(file
, tmp
.fs_file
)) return NULL
;
1171 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
);
1175 extract_mac_mac(si_mod_t
*si
, kvarray_t
*in
, void *extra
, uint64_t valid_global
, uint64_t valid_cat
)
1177 uint32_t d
, k
, kcount
;
1181 if (si
== NULL
) return NULL
;
1182 if (in
== NULL
) return NULL
;
1183 if (extra
== NULL
) return NULL
;
1188 if (d
>= in
->count
) return NULL
;
1190 kcount
= in
->dict
[d
].kcount
;
1193 for (k
= 0; k
< kcount
; k
++)
1195 if ((cmac
== NULL
) && (string_equal(in
->dict
[d
].key
[k
], "mac")))
1197 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1198 cmac
= si_canonical_mac_address(in
->dict
[d
].val
[k
][0]);
1199 if (cmac
== NULL
) return NULL
;
1203 if (cmac
== NULL
) return NULL
;
1205 out
= (si_item_t
*)LI_ils_create("L4488ss", (unsigned long)si
, CATEGORY_MAC
, 1, valid_global
, valid_cat
, extra
, cmac
);
1211 extract_mac_name(si_mod_t
*si
, kvarray_t
*in
, void *extra
, uint64_t valid_global
, uint64_t valid_cat
)
1213 uint32_t d
, k
, kcount
;
1217 if (si
== NULL
) return NULL
;
1218 if (in
== NULL
) return NULL
;
1219 if (extra
== NULL
) return NULL
;
1224 if (d
>= in
->count
) return NULL
;
1226 kcount
= in
->dict
[d
].kcount
;
1229 for (k
= 0; k
< kcount
; k
++)
1231 if ((name
== NULL
) && (string_equal(in
->dict
[d
].key
[k
], "name")))
1233 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1234 name
= in
->dict
[d
].val
[k
][0];
1238 if (name
== NULL
) return NULL
;
1240 out
= (si_item_t
*)LI_ils_create("L4488ss", (unsigned long)si
, CATEGORY_MAC
, 1, valid_global
, valid_cat
, name
, extra
);
1244 __private_extern__ si_item_t
*
1245 ds_user_byname(si_mod_t
*si
, const char *name
)
1247 static int proc
= -1;
1251 request
= kvbuf_query_key_val("login", name
);
1252 if (request
== NULL
) return NULL
;
1254 item
= ds_item(si
, CATEGORY_USER
, "getpwnam", &proc
, NULL
, extract_user
, request
);
1256 kvbuf_free(request
);
1260 __private_extern__ si_item_t
*
1261 ds_user_byuid(si_mod_t
*si
, uid_t uid
)
1263 static int proc
= -1;
1268 snprintf(val
, sizeof(val
), "%d", (int)uid
);
1269 request
= kvbuf_query_key_val("uid", val
);
1270 if (request
== NULL
) return NULL
;
1272 item
= ds_item(si
, CATEGORY_USER
, "getpwuid", &proc
, NULL
, extract_user
, request
);
1274 kvbuf_free(request
);
1278 __private_extern__ si_list_t
*
1279 ds_user_all(si_mod_t
*si
)
1281 static int proc
= -1;
1283 return ds_list(si
, CATEGORY_USER
, "getpwent", &proc
, NULL
, extract_user
, NULL
);
1286 __private_extern__ si_item_t
*
1287 ds_group_byname(si_mod_t
*si
, const char *name
)
1289 static int proc
= -1;
1293 request
= kvbuf_query_key_val("name", name
);
1294 if (request
== NULL
) return NULL
;
1296 item
= ds_item(si
, CATEGORY_GROUP
, "getgrnam", &proc
, NULL
, extract_group
, request
);
1298 kvbuf_free(request
);
1302 __private_extern__ si_item_t
*
1303 ds_group_bygid(si_mod_t
*si
, gid_t gid
)
1305 static int proc
= -1;
1310 snprintf(val
, sizeof(val
), "%d", (int)gid
);
1311 request
= kvbuf_query_key_val("gid", val
);
1312 if (request
== NULL
) return NULL
;
1314 item
= ds_item(si
, CATEGORY_GROUP
, "getgrgid", &proc
, NULL
, extract_group
, request
);
1316 kvbuf_free(request
);
1320 __private_extern__ si_list_t
*
1321 ds_group_all(si_mod_t
*si
)
1323 static int proc
= -1;
1325 return ds_list(si
, CATEGORY_GROUP
, "getgrent", &proc
, NULL
, extract_group
, NULL
);
1328 __private_extern__ si_item_t
*
1329 ds_grouplist(si_mod_t
*si
, const char *name
)
1332 kern_return_t kstatus
;
1333 uint32_t i
, j
, count
, uid
, basegid
, gidptrCnt
;
1336 audit_token_t token
;
1337 si_item_t
*user
, *item
;
1342 if (name
== NULL
) return NULL
;
1344 user
= ds_user_byname(si
, name
);
1345 if (user
== NULL
) return NULL
;
1347 pw
= (struct passwd
*)((uintptr_t)user
+ sizeof(si_item_t
));
1349 basegid
= pw
->pw_gid
;
1357 memset(&token
, 0, sizeof(audit_token_t
));
1359 kstatus
= memberdDSmig_GetAllGroups(_ds_port
, uid
, &count
, &gidptr
, &gidptrCnt
, &token
);
1360 if (kstatus
!= KERN_SUCCESS
) return NULL
;
1362 gidptrsz
= gidptrCnt
* sizeof(gid_t
);
1364 if ((audit_token_uid(token
) != 0) || (count
== 0))
1366 if (gidptr
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)gidptr
, gidptrsz
);
1370 gidlist
= (char **)calloc(count
+ 1, sizeof(char *));
1371 if (gidlist
== NULL
)
1373 if (gidptr
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)gidptr
, gidptrsz
);
1377 for (i
= 0; i
< count
; i
++)
1379 gidp
= (int32_t *)calloc(1, sizeof(int32_t));
1382 for (j
= 0; j
< i
; j
++) free(gidlist
[j
]);
1389 gidlist
[i
] = (char *)gidp
;
1394 if (gidptr
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)gidptr
, gidptrsz
);
1400 ds_get_validation(si
, &va
, &vb
, CATEGORY_GROUPLIST
);
1402 item
= (si_item_t
*)LI_ils_create("L4488s44a", (unsigned long)si
, CATEGORY_GROUPLIST
, 1, va
, vb
, name
, basegid
, count
, gidlist
);
1404 if (gidptr
!= NULL
) vm_deallocate(mach_task_self(), (vm_address_t
)gidptr
, gidptrsz
);
1406 for (i
= 0; i
<= count
; i
++) free(gidlist
[i
]);
1412 __private_extern__ si_list_t
*
1413 ds_netgroup_byname(si_mod_t
*si
, const char *name
)
1415 static int proc
= -1;
1419 request
= kvbuf_query_key_val("netgroup", name
);
1420 if (request
== NULL
) return NULL
;
1422 list
= ds_list(si
, CATEGORY_NETGROUP
, "getnetgrent", &proc
, NULL
, extract_netgroup
, request
);
1424 kvbuf_free(request
);
1430 check_innetgr(kvarray_t
*in
)
1432 uint32_t d
, k
, kcount
;
1434 if (in
== NULL
) return 0;
1437 if (d
>= in
->count
) return 0;
1439 kcount
= in
->dict
[d
].kcount
;
1441 for (k
= 0; k
< kcount
; k
++)
1443 if (string_equal(in
->dict
[d
].key
[k
], "result"))
1445 if (in
->dict
[d
].vcount
[k
] == 0) continue;
1446 return atoi(in
->dict
[d
].val
[k
][0]);
1453 __private_extern__
int
1454 ds_in_netgroup(si_mod_t
*si
, const char *group
, const char *host
, const char *user
, const char *domain
)
1459 kern_return_t status
;
1460 static int proc
= -1;
1464 status
= LI_DSLookupGetProcedureNumber("innetgr", &proc
);
1465 if (status
!= KERN_SUCCESS
) return 0;
1469 if (group
== NULL
) group
= "";
1470 if (host
== NULL
) host
= "";
1471 if (user
== NULL
) user
= "";
1472 if (domain
== NULL
) domain
= "";
1474 request
= kvbuf_query("ksksksks", "netgroup", group
, "host", host
, "user", user
, "domain", domain
);
1475 if (request
== NULL
) return 0;
1478 status
= LI_DSLookupQuery(proc
, request
, &reply
);
1479 kvbuf_free(request
);
1481 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
)) return 0;
1483 is_innetgr
= check_innetgr(reply
);
1485 kvarray_free(reply
);
1490 __private_extern__ si_item_t
*
1491 ds_alias_byname(si_mod_t
*si
, const char *name
)
1493 static int proc
= -1;
1497 request
= kvbuf_query_key_val("name", name
);
1498 if (request
== NULL
) return NULL
;
1500 item
= ds_item(si
, CATEGORY_ALIAS
, "alias_getbyname", &proc
, NULL
, extract_alias
, request
);
1502 kvbuf_free(request
);
1506 __private_extern__ si_list_t
*
1507 ds_alias_all(si_mod_t
*si
)
1509 static int proc
= -1;
1511 return ds_list(si
, CATEGORY_ALIAS
, "alias_getent", &proc
, NULL
, extract_alias
, NULL
);
1514 __private_extern__ si_item_t
*
1515 ds_host_byname(si_mod_t
*si
, const char *name
, int af
, const char *ignored
, uint32_t *err
)
1517 static int proc
= -1;
1520 uint32_t want4
, want6
;
1523 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
1527 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1534 cat
= CATEGORY_HOST_IPV4
;
1540 else if (af
== AF_INET6
)
1543 cat
= CATEGORY_HOST_IPV6
;
1547 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1551 request
= kvbuf_query("kskuku", "name", name
, "ipv4", want4
, "ipv6", want6
);
1552 if (request
== NULL
)
1554 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1558 item
= ds_item(si
, cat
, "gethostbyname", &proc
, NULL
, extract_host
, request
);
1560 if ((item
== NULL
) && (err
!= NULL
)) *err
= SI_STATUS_H_ERRNO_HOST_NOT_FOUND
;
1562 kvbuf_free(request
);
1566 __private_extern__ si_item_t
*
1567 ds_host_byaddr(si_mod_t
*si
, const void *addr
, int af
, const char *ignored
, uint32_t *err
)
1569 static int proc
= -1;
1572 struct in_addr addr4
;
1573 struct in6_addr addr6
;
1574 char val
[64 + 1 + IF_NAMESIZE
];
1578 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
1580 cat
= CATEGORY_HOST_IPV4
;
1582 memset(&addr4
, 0, sizeof(struct in_addr
));
1583 memset(&addr6
, 0, sizeof(struct in6_addr
));
1584 memset(val
, 0, sizeof(val
));
1586 want
= WANT_A4_ONLY
;
1590 memcpy(&addr4
.s_addr
, addr
, IPV4_ADDR_LEN
);
1591 if (inet_ntop(af
, &addr4
, val
, sizeof(val
)) == NULL
)
1593 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1597 else if (af
== AF_INET6
)
1599 want
= WANT_A6_ONLY
;
1600 cat
= CATEGORY_HOST_IPV6
;
1601 memcpy(&addr6
, addr
, IPV6_ADDR_LEN
);
1602 if (inet_ntop(af
, &addr6
, val
, sizeof(val
)) == NULL
)
1604 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1610 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1614 request
= kvbuf_query("ksku", "address", val
, "family", af
);
1615 if (request
== NULL
)
1617 *err
= SI_STATUS_H_ERRNO_NO_RECOVERY
;
1621 item
= ds_item(si
, cat
, "gethostbyaddr", &proc
, &want
, extract_host
, request
);
1623 if ((item
== NULL
) && (err
!= NULL
)) *err
= SI_STATUS_H_ERRNO_HOST_NOT_FOUND
;
1625 kvbuf_free(request
);
1629 __private_extern__ si_list_t
*
1630 ds_host_all(si_mod_t
*si
)
1632 static int proc
= -1;
1634 return ds_list(si
, CATEGORY_HOST_IPV4
, "gethostent", &proc
, NULL
, extract_host
, NULL
);
1637 __private_extern__ si_item_t
*
1638 ds_network_byname(si_mod_t
*si
, const char *name
)
1640 static int proc
= -1;
1644 request
= kvbuf_query_key_val("name", name
);
1645 if (request
== NULL
) return NULL
;
1647 item
= ds_item(si
, CATEGORY_NETWORK
, "getnetbyname", &proc
, NULL
, extract_network
, request
);
1649 kvbuf_free(request
);
1653 __private_extern__ si_item_t
*
1654 ds_network_byaddr(si_mod_t
*si
, uint32_t addr
)
1656 static int proc
= -1;
1657 unsigned char f1
, f2
, f3
;
1668 if (f3
!= 0) snprintf(val
, sizeof(val
), "%u.%u.%u", f3
, f2
, f1
);
1669 else if (f2
!= 0) snprintf(val
, sizeof(val
), "%u.%u", f2
, f1
);
1670 else snprintf(val
, sizeof(val
), "%u", f1
);
1672 request
= kvbuf_query_key_val("net", val
);
1673 if (request
== NULL
) return NULL
;
1675 item
= ds_item(si
, CATEGORY_NETWORK
, "getnetbyaddr", &proc
, NULL
, extract_network
, request
);
1677 kvbuf_free(request
);
1681 __private_extern__ si_list_t
*
1682 ds_network_all(si_mod_t
*si
)
1684 static int proc
= -1;
1686 return ds_list(si
, CATEGORY_NETWORK
, "getnetent", &proc
, NULL
, extract_network
, NULL
);
1689 __private_extern__ si_item_t
*
1690 ds_service_byname(si_mod_t
*si
, const char *name
, const char *proto
)
1692 static int proc
= -1;
1697 if (name
== NULL
) name
= "";
1698 if (proto
== NULL
) proto
= "";
1700 /* Check our local service cache (see ds_addrinfo). */
1701 item
= pthread_getspecific(_ds_serv_cache_key
);
1704 s
= (struct servent
*)((uintptr_t)item
+ sizeof(si_item_t
));
1705 if (string_equal(name
, s
->s_name
)) return si_item_retain(item
);
1708 request
= kvbuf_query("ksks", "name", name
, "proto", proto
);
1709 if (request
== NULL
) return NULL
;
1711 item
= ds_item(si
, CATEGORY_SERVICE
, "getservbyname", &proc
, NULL
, extract_service
, request
);
1713 kvbuf_free(request
);
1717 __private_extern__ si_item_t
*
1718 ds_service_byport(si_mod_t
*si
, int port
, const char *proto
)
1720 static int proc
= -1;
1726 if (proto
== NULL
) proto
= "";
1729 snprintf(val
, sizeof(val
), "%d", ntohs(sport
));
1731 request
= kvbuf_query("ksks", "port", val
, "proto", proto
);
1732 if (request
== NULL
) return NULL
;
1734 item
= ds_item(si
, CATEGORY_SERVICE
, "getservbyport", &proc
, NULL
, extract_service
, request
);
1736 kvbuf_free(request
);
1740 __private_extern__ si_list_t
*
1741 ds_service_all(si_mod_t
*si
)
1743 static int proc
= -1;
1745 return ds_list(si
, CATEGORY_SERVICE
, "getservent", &proc
, NULL
, extract_service
, NULL
);
1748 __private_extern__ si_item_t
*
1749 ds_protocol_byname(si_mod_t
*si
, const char *name
)
1751 static int proc
= -1;
1755 request
= kvbuf_query_key_val("name", name
);
1756 if (request
== NULL
) return NULL
;
1758 item
= ds_item(si
, CATEGORY_PROTOCOL
, "getprotobyname", &proc
, NULL
, extract_protocol
, request
);
1760 kvbuf_free(request
);
1764 __private_extern__ si_item_t
*
1765 ds_protocol_bynumber(si_mod_t
*si
, int number
)
1767 static int proc
= -1;
1772 snprintf(val
, sizeof(val
), "%d", number
);
1773 request
= kvbuf_query_key_val("number", val
);
1774 if (request
== NULL
) return NULL
;
1776 item
= ds_item(si
, CATEGORY_PROTOCOL
, "getprotobynumber", &proc
, NULL
, extract_protocol
, request
);
1778 kvbuf_free(request
);
1782 __private_extern__ si_list_t
*
1783 ds_protocol_all(si_mod_t
*si
)
1785 static int proc
= -1;
1787 return ds_list(si
, CATEGORY_PROTOCOL
, "getprotoent", &proc
, NULL
, extract_protocol
, NULL
);
1790 __private_extern__ si_item_t
*
1791 ds_rpc_byname(si_mod_t
*si
, const char *name
)
1793 static int proc
= -1;
1797 request
= kvbuf_query_key_val("name", name
);
1798 if (request
== NULL
) return NULL
;
1800 item
= ds_item(si
, CATEGORY_RPC
, "getrpcbyname", &proc
, NULL
, extract_rpc
, request
);
1802 kvbuf_free(request
);
1806 __private_extern__ si_item_t
*
1807 ds_rpc_bynumber(si_mod_t
*si
, int number
)
1809 static int proc
= -1;
1814 snprintf(val
, sizeof(val
), "%u", (uint32_t)number
);
1815 request
= kvbuf_query_key_val("number", val
);
1816 if (request
== NULL
) return NULL
;
1818 item
= ds_item(si
, CATEGORY_RPC
, "getrpcbynumber", &proc
, NULL
, extract_rpc
, request
);
1820 kvbuf_free(request
);
1824 __private_extern__ si_list_t
*
1825 ds_rpc_all(si_mod_t
*si
)
1827 static int proc
= -1;
1829 return ds_list(si
, CATEGORY_RPC
, "getrpcent", &proc
, NULL
, extract_rpc
, NULL
);
1832 __private_extern__ si_item_t
*
1833 ds_fs_byspec(si_mod_t
*si
, const char *name
)
1835 static int proc
= -1;
1839 request
= kvbuf_query_key_val("name", name
);
1840 if (request
== NULL
) return NULL
;
1842 item
= ds_item(si
, CATEGORY_FS
, "getfsbyname", &proc
, NULL
, extract_fstab
, request
);
1844 kvbuf_free(request
);
1848 __private_extern__ si_list_t
*
1849 ds_fs_all(si_mod_t
*si
)
1851 static int proc
= -1;
1853 return ds_list(si
, CATEGORY_FS
, "getfsent", &proc
, NULL
, extract_fstab
, NULL
);
1856 __private_extern__ si_item_t
*
1857 ds_fs_byfile(si_mod_t
*si
, const char *name
)
1864 if (name
== NULL
) return NULL
;
1866 list
= ds_fs_all(si
);
1867 if (list
== NULL
) return NULL
;
1870 for (i
= 0; (i
< list
->count
) && (item
== NULL
); i
++)
1872 f
= (struct fstab
*)((uintptr_t)(list
->entry
[i
]) + sizeof(si_item_t
));
1873 if (string_equal(name
, f
->fs_file
)) item
= si_item_retain(list
->entry
[i
]);
1876 si_list_release(list
);
1880 __private_extern__ si_item_t
*
1881 ds_mac_byname(si_mod_t
*si
, const char *name
)
1883 static int proc
= -1;
1887 request
= kvbuf_query_key_val("name", name
);
1888 if (request
== NULL
) return NULL
;
1890 item
= ds_item(si
, CATEGORY_MAC
, "getmacbyname", &proc
, (void *)name
, extract_mac_mac
, request
);
1892 kvbuf_free(request
);
1896 __private_extern__ si_item_t
*
1897 ds_mac_bymac(si_mod_t
*si
, const char *mac
)
1899 static int proc
= -1;
1904 cmac
= si_canonical_mac_address(mac
);
1905 if (cmac
== NULL
) return NULL
;
1907 request
= kvbuf_query_key_val("mac", cmac
);
1908 if (request
== NULL
) return NULL
;
1910 item
= ds_item(si
, CATEGORY_MAC
, "gethostbymac", &proc
, cmac
, extract_mac_name
, request
);
1913 kvbuf_free(request
);
1918 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
)
1920 static int proc
= -1;
1921 si_list_t
*list
, *out
;
1923 kvbuf_t
*request
= NULL
;
1925 kvarray_t
*reply
= NULL
;
1926 kern_return_t status
= 0;
1928 int i
, k
, kcount
, d
;
1932 char *h_name
= NULL
;
1933 int h_aliases_cnt
= 0;
1934 const char **h_aliases
= NULL
;
1935 struct in_addr
*a4
= NULL
;
1936 struct in6_addr
*a6
= NULL
;
1940 const char *s_name
= NULL
;
1941 int s_aliases_cnt
= 0;
1942 const char **s_aliases
= NULL
;
1943 uint16_t s_port
= 0;
1944 const char *s_proto
= NULL
;
1945 const char *protoname
;
1948 int numericserv
= ((flags
& AI_NUMERICSERV
) != 0);
1949 int numerichost
= ((flags
& AI_NUMERICHOST
) != 0);
1956 wantv4
= (family
!= AF_INET6
);
1957 wantv6
= (family
!= AF_INET
);
1960 if (err
!= NULL
) *err
= SI_STATUS_NO_ERROR
;
1964 status
= LI_DSLookupGetProcedureNumber("gethostbyname_service", &proc
);
1965 if (status
!= KERN_SUCCESS
)
1967 if (err
!= NULL
) *err
= SI_STATUS_EAI_SYSTEM
;
1972 /* look up canonical name of numeric host */
1973 if ((numerichost
== 1) && (flags
& AI_CANONNAME
) && (node
!= NULL
))
1975 item
= si_host_byaddr(si
, node
, family
, NULL
, NULL
);
1978 h
= (struct hostent
*)((uintptr_t)item
+ sizeof(si_item_t
));
1979 h_name
= strdup(h
->h_name
);
1980 si_item_release(item
);
1984 if (numericserv
== 1)
1986 s_port
= *(int16_t *)serv
;
1989 if ((numericserv
== 0) || (numerichost
== 0))
1991 request
= kvbuf_new();
1992 if (request
!= NULL
)
1994 kvbuf_add_dict(request
);
1996 if (numerichost
== 0)
1998 kvbuf_add_key(request
, "name");
1999 kvbuf_add_val(request
, node
);
2000 kvbuf_add_key(request
, "ipv4");
2001 kvbuf_add_val(request
, wantv4
? "1" : "0");
2002 kvbuf_add_key(request
, "ipv6");
2003 kvbuf_add_val(request
, wantv6
? "1" : "0");
2006 if (numericserv
== 0)
2009 if (proto
== IPPROTO_UDP
) protoname
= "udp";
2010 if (proto
== IPPROTO_TCP
) protoname
= "tcp";
2012 kvbuf_add_key(request
, "s_name");
2013 kvbuf_add_val(request
, serv
);
2014 if (protoname
!= NULL
)
2016 kvbuf_add_key(request
, "s_proto");
2017 kvbuf_add_val(request
, protoname
);
2021 status
= LI_DSLookupQuery(proc
, request
, &reply
);
2022 kvbuf_free(request
);
2026 if (err
!= NULL
) *err
= SI_STATUS_EAI_SYSTEM
;
2030 if ((status
!= KERN_SUCCESS
) || (reply
== NULL
))
2036 for (d
= 0; d
< reply
->count
; d
++)
2038 dict
= reply
->dict
+ d
;
2039 kcount
= dict
->kcount
;
2041 for (k
= 0; k
< kcount
; k
++)
2043 if (string_equal(dict
->key
[k
], "h_name"))
2045 if (dict
->vcount
[k
] == 0) continue;
2046 h_name
= strdup(dict
->val
[k
][0]);
2048 else if (string_equal(dict
->key
[k
], "h_aliases"))
2050 h_aliases_cnt
= dict
->vcount
[k
];
2051 h_aliases
= (const char **)calloc(h_aliases_cnt
, sizeof(char *));
2052 if (h_aliases
== NULL
) h_aliases_cnt
= 0;
2054 for (i
= 0; i
< h_aliases_cnt
; ++i
)
2056 h_aliases
[i
] = dict
->val
[k
][i
];
2059 else if (wantv4
&& (string_equal(dict
->key
[k
], "h_ipv4_addr_list")))
2061 a4_cnt
= dict
->vcount
[k
];
2062 a4
= calloc(a4_cnt
, sizeof(struct in_addr
));
2063 if (a4
== NULL
) a4_cnt
= 0;
2065 for (i
= 0; i
< a4_cnt
; ++i
)
2067 memset(&a4
[i
], 0, sizeof(struct in_addr
));
2068 inet_pton(AF_INET
, dict
->val
[k
][i
], &a4
[i
]);
2071 else if (wantv6
&& (string_equal(dict
->key
[k
], "h_ipv6_addr_list")))
2073 a6_cnt
= dict
->vcount
[k
];
2074 a6
= calloc(a6_cnt
, sizeof(struct in6_addr
));
2075 if (a6
== NULL
) a6_cnt
= 0;
2077 for (i
= 0; i
< a6_cnt
; ++i
)
2079 memset(&a6
[i
], 0, sizeof(struct in6_addr
));
2080 inet_pton(AF_INET6
, dict
->val
[k
][i
], &a6
[i
]);
2083 else if (string_equal(dict
->key
[k
], "s_name"))
2085 if (dict
->vcount
[k
] == 0) continue;
2086 s_name
= dict
->val
[k
][0];
2088 else if (string_equal(dict
->key
[k
], "s_port"))
2090 if (dict
->vcount
[k
] == 0) continue;
2091 s_port
= atoi(dict
->val
[k
][0]);
2093 else if (string_equal(dict
->key
[k
], "s_aliases"))
2095 s_aliases_cnt
= dict
->vcount
[k
];
2096 s_aliases
= (const char **)calloc(s_aliases_cnt
+1, sizeof(char *));
2097 if (s_aliases
== NULL
) s_aliases_cnt
= 0;
2099 for (i
= 0; i
< s_aliases_cnt
; ++i
)
2101 s_aliases
[i
] = dict
->val
[k
][i
];
2104 else if (string_equal(dict
->key
[k
], "s_proto"))
2106 if (dict
->vcount
[k
] == 0) continue;
2107 s_proto
= dict
->val
[k
][0];
2112 kvarray_free(reply
);
2114 /* check if we actually got back what we wanted */
2115 if (((wantv4
|| wantv6
) && (a4_cnt
== 0) && (a6_cnt
== 0)) || ((serv
!= NULL
) && (s_port
== 0)))
2117 if (err
!= NULL
) *err
= SI_STATUS_EAI_NONAME
;
2129 * Cache the service entry regardless of whether there is a host match.
2130 * This allows later modules to get the service entry quickly.
2131 * This should really be part of the general cache mechanism, but that's
2132 * not currently visible outside of the search module.
2134 if ((s_name
!= NULL
) && (s_port
!= 0))
2136 port
= htons(s_port
);
2138 item
= pthread_getspecific(_ds_serv_cache_key
);
2141 s
= (struct servent
*)((uintptr_t)item
+ sizeof(si_item_t
));
2142 if ((port
!= s
->s_port
) || string_not_equal(s_name
, s
->s_name
))
2144 si_item_release(item
);
2151 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
);
2152 pthread_setspecific(_ds_serv_cache_key
, item
);
2156 /* Construct the addrinfo list from the returned addresses (if found). */
2158 for (i
= 0; i
< a6_cnt
; i
++)
2160 list
= si_addrinfo_list(si
, socktype
, proto
, NULL
, &a6
[i
], s_port
, scope
, NULL
, h_name
);
2161 out
= si_list_concat(out
, list
);
2162 si_list_release(list
);
2165 for (i
= 0; i
< a4_cnt
; i
++)
2167 list
= si_addrinfo_list(si
, socktype
, proto
, &a4
[i
], NULL
, s_port
, 0, h_name
, NULL
);
2168 out
= si_list_concat(out
, list
);
2169 si_list_release(list
);
2181 __private_extern__
int
2182 ds_is_valid(si_mod_t
*si
, si_item_t
*item
)
2185 ds_si_private_t
*pp
;
2187 uint32_t oldval
, newval
;
2189 if (si
== NULL
) return 0;
2190 if (item
== NULL
) return 0;
2191 if (si
->name
== NULL
) return 0;
2192 if (item
->src
== NULL
) return 0;
2194 pp
= (ds_si_private_t
*)si
->private;
2195 if (pp
== NULL
) return 0;
2197 src
= (si_mod_t
*)item
->src
;
2199 if (src
->name
== NULL
) return 0;
2200 if (string_not_equal(si
->name
, src
->name
)) return 0;
2202 /* check global invalidation */
2203 oldval
= item
->validation_a
;
2205 status
= notify_peek(pp
->notify_token_global
, &newval
);
2206 if (status
!= NOTIFY_STATUS_OK
) return 0;
2208 newval
= ntohl(newval
);
2209 if (oldval
!= newval
) return 0;
2211 oldval
= item
->validation_b
;
2213 if (item
->type
== CATEGORY_USER
) status
= notify_peek(pp
->notify_token_user
, &newval
);
2214 else if (item
->type
== CATEGORY_GROUP
) status
= notify_peek(pp
->notify_token_group
, &newval
);
2215 else if (item
->type
== CATEGORY_HOST_IPV4
) status
= notify_peek(pp
->notify_token_host
, &newval
);
2216 else if (item
->type
== CATEGORY_HOST_IPV6
) status
= notify_peek(pp
->notify_token_host
, &newval
);
2217 else if (item
->type
== CATEGORY_SERVICE
) status
= notify_peek(pp
->notify_token_service
, &newval
);
2220 if (status
!= NOTIFY_STATUS_OK
) return 0;
2222 newval
= ntohl(newval
);
2223 if (oldval
!= newval
) return 0;
2228 __private_extern__ si_mod_t
*
2229 si_module_static_ds()
2233 ds_si_private_t
*pp
;
2236 out
= (si_mod_t
*)calloc(1, sizeof(si_mod_t
));
2237 outname
= strdup("ds");
2238 pp
= (ds_si_private_t
*)calloc(1, sizeof(ds_si_private_t
));
2240 if ((out
== NULL
) || (outname
== NULL
) || (pp
== NULL
))
2242 if (out
!= NULL
) free(out
);
2243 if (outname
!= NULL
) free(outname
);
2244 if (pp
!= NULL
) free(pp
);
2250 pthread_key_create(&_ds_serv_cache_key
, _ds_serv_cache_free
);
2252 pp
->notify_token_global
= -1;
2253 pp
->notify_token_user
= -1;
2254 pp
->notify_token_group
= -1;
2255 pp
->notify_token_host
= -1;
2256 pp
->notify_token_service
= -1;
2259 * Don't register for notifications if the cache is disabled.
2260 * notifyd (notably) disables the cache to prevent deadlocks.
2262 if (gL1CacheEnabled
!= 0)
2265 * Errors in registering for cache invalidation notifications are ignored.
2266 * If there are failures, the tokens remain set to -1 which just causes
2267 * cached items to be invalidated.
2269 status
= notify_register_check(DS_NOTIFICATION_KEY_GLOBAL
, &(pp
->notify_token_global
));
2270 status
= notify_register_check(DS_NOTIFICATION_KEY_GLOBAL
, &(pp
->notify_token_user
));
2271 status
= notify_register_check(DS_NOTIFICATION_KEY_GLOBAL
, &(pp
->notify_token_group
));
2272 status
= notify_register_check(DS_NOTIFICATION_KEY_GLOBAL
, &(pp
->notify_token_host
));
2273 status
= notify_register_check(DS_NOTIFICATION_KEY_GLOBAL
, &(pp
->notify_token_service
));
2276 out
->name
= outname
;
2281 out
->sim_is_valid
= ds_is_valid
;
2283 out
->sim_user_byname
= ds_user_byname
;
2284 out
->sim_user_byuid
= ds_user_byuid
;
2285 out
->sim_user_all
= ds_user_all
;
2287 out
->sim_group_byname
= ds_group_byname
;
2288 out
->sim_group_bygid
= ds_group_bygid
;
2289 out
->sim_group_all
= ds_group_all
;
2291 out
->sim_grouplist
= ds_grouplist
;
2293 out
->sim_netgroup_byname
= ds_netgroup_byname
;
2294 out
->sim_in_netgroup
= ds_in_netgroup
;
2296 out
->sim_alias_byname
= ds_alias_byname
;
2297 out
->sim_alias_all
= ds_alias_all
;
2299 out
->sim_host_byname
= ds_host_byname
;
2300 out
->sim_host_byaddr
= ds_host_byaddr
;
2301 out
->sim_host_all
= ds_host_all
;
2303 out
->sim_network_byname
= ds_network_byname
;
2304 out
->sim_network_byaddr
= ds_network_byaddr
;
2305 out
->sim_network_all
= ds_network_all
;
2307 out
->sim_service_byname
= ds_service_byname
;
2308 out
->sim_service_byport
= ds_service_byport
;
2309 out
->sim_service_all
= ds_service_all
;
2311 out
->sim_protocol_byname
= ds_protocol_byname
;
2312 out
->sim_protocol_bynumber
= ds_protocol_bynumber
;
2313 out
->sim_protocol_all
= ds_protocol_all
;
2315 out
->sim_rpc_byname
= ds_rpc_byname
;
2316 out
->sim_rpc_bynumber
= ds_rpc_bynumber
;
2317 out
->sim_rpc_all
= ds_rpc_all
;
2319 out
->sim_fs_byspec
= ds_fs_byspec
;
2320 out
->sim_fs_byfile
= ds_fs_byfile
;
2321 out
->sim_fs_all
= ds_fs_all
;
2323 out
->sim_mac_byname
= ds_mac_byname
;
2324 out
->sim_mac_bymac
= ds_mac_bymac
;
2326 /* si_mac_all not supported */
2327 out
->sim_mac_all
= NULL
;
2329 out
->sim_addrinfo
= ds_addrinfo
;