]> git.saurik.com Git - apple/libinfo.git/commitdiff
Libinfo-406.17.tar.gz mac-os-x-108 mac-os-x-1081 mac-os-x-1082 mac-os-x-1083 mac-os-x-1084 mac-os-x-1085 v406.17
authorApple <opensource@apple.com>
Fri, 30 Mar 2012 23:25:31 +0000 (23:25 +0000)
committerApple <opensource@apple.com>
Fri, 30 Mar 2012 23:25:31 +0000 (23:25 +0000)
24 files changed:
Libinfo.xcodeproj/project.pbxproj
gen.subproj/gethostbyname.3
gen.subproj/getnetent.3
lookup.subproj/cache_module.c
lookup.subproj/ds_module.c
lookup.subproj/file_module.c
lookup.subproj/getgrent.3
lookup.subproj/getpwent.3
lookup.subproj/grp.h [new file with mode: 0644]
lookup.subproj/libinfo.c
lookup.subproj/mdns_module.c
lookup.subproj/pwd.h [new file with mode: 0644]
lookup.subproj/search_module.c
lookup.subproj/si_getaddrinfo.c
lookup.subproj/si_module.c
lookup.subproj/si_module.h
membership.subproj/mbr_check_membership.3
membership.subproj/mbr_uid_to_uuid.3
membership.subproj/membership.c
membership.subproj/membership.h
membership.subproj/membershipPriv.h
rpc.subproj/clnt_raw.c
rpc.subproj/rpc_prot.c
xcodescripts/install_files.sh

index d633498c9513d6fb42ac2359f96197f683bd4286..112788ae1b3ef4ce456fb226497a62c2cf2d3e1f 100644 (file)
@@ -3,7 +3,7 @@
        archiveVersion = 1;
        classes = {
        };
        archiveVersion = 1;
        classes = {
        };
-       objectVersion = 45;
+       objectVersion = 46;
        objects = {
 
 /* Begin PBXBuildFile section */
        objects = {
 
 /* Begin PBXBuildFile section */
                FC52855D11478C200058CCB0 /* rcmd.c in Sources */ = {isa = PBXBuildFile; fileRef = FC5284BE11478C200058CCB0 /* rcmd.c */; };
                FC52855E11478C200058CCB0 /* rcmdsh.c in Sources */ = {isa = PBXBuildFile; fileRef = FC5284BF11478C200058CCB0 /* rcmdsh.c */; };
                FC5285D4114791B50058CCB0 /* DSlibinfoMIG.defs in Sources */ = {isa = PBXBuildFile; fileRef = FC5285D1114791B50058CCB0 /* DSlibinfoMIG.defs */; };
                FC52855D11478C200058CCB0 /* rcmd.c in Sources */ = {isa = PBXBuildFile; fileRef = FC5284BE11478C200058CCB0 /* rcmd.c */; };
                FC52855E11478C200058CCB0 /* rcmdsh.c in Sources */ = {isa = PBXBuildFile; fileRef = FC5284BF11478C200058CCB0 /* rcmdsh.c */; };
                FC5285D4114791B50058CCB0 /* DSlibinfoMIG.defs in Sources */ = {isa = PBXBuildFile; fileRef = FC5285D1114791B50058CCB0 /* DSlibinfoMIG.defs */; };
-               FC5285D5114791B50058CCB0 /* DSlibinfoMIGAsyncReply.defs in Sources */ = {isa = PBXBuildFile; fileRef = FC5285D2114791B50058CCB0 /* DSlibinfoMIGAsyncReply.defs */; settings = {ATTRIBUTES = (Server, ); }; };
-               FC5285D6114791B50058CCB0 /* DSmemberdMIG.defs in Sources */ = {isa = PBXBuildFile; fileRef = FC5285D3114791B50058CCB0 /* DSmemberdMIG.defs */; };
                FC5285F7114793400058CCB0 /* ether_addr.c in Sources */ = {isa = PBXBuildFile; fileRef = FC5285F6114793400058CCB0 /* ether_addr.c */; };
 /* End PBXBuildFile section */
 
                FC5285F7114793400058CCB0 /* ether_addr.c in Sources */ = {isa = PBXBuildFile; fileRef = FC5285F6114793400058CCB0 /* ether_addr.c */; };
 /* End PBXBuildFile section */
 
                FC5284BE11478C200058CCB0 /* rcmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rcmd.c; sourceTree = "<group>"; };
                FC5284BF11478C200058CCB0 /* rcmdsh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rcmdsh.c; sourceTree = "<group>"; };
                FC5285D1114791B50058CCB0 /* DSlibinfoMIG.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 4; name = DSlibinfoMIG.defs; path = usr/local/include/opendirectory/DSlibinfoMIG.defs; sourceTree = SDKROOT; };
                FC5284BE11478C200058CCB0 /* rcmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rcmd.c; sourceTree = "<group>"; };
                FC5284BF11478C200058CCB0 /* rcmdsh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rcmdsh.c; sourceTree = "<group>"; };
                FC5285D1114791B50058CCB0 /* DSlibinfoMIG.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 4; name = DSlibinfoMIG.defs; path = usr/local/include/opendirectory/DSlibinfoMIG.defs; sourceTree = SDKROOT; };
-               FC5285D2114791B50058CCB0 /* DSlibinfoMIGAsyncReply.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 4; name = DSlibinfoMIGAsyncReply.defs; path = usr/local/include/opendirectory/DSlibinfoMIGAsyncReply.defs; sourceTree = SDKROOT; };
-               FC5285D3114791B50058CCB0 /* DSmemberdMIG.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 4; name = DSmemberdMIG.defs; path = usr/local/include/opendirectory/DSmemberdMIG.defs; sourceTree = SDKROOT; };
                FC5285F6114793400058CCB0 /* ether_addr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ether_addr.c; sourceTree = "<group>"; };
                FC5285F6114793400058CCB0 /* ether_addr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ether_addr.c; sourceTree = "<group>"; };
+               FCFDBF0A145CC5C100A39A66 /* grp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = grp.h; sourceTree = "<group>"; };
+               FCFDBF0B145CC5C100A39A66 /* pwd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pwd.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                        children = (
                                2D4070B0129354A700FE81ED /* getnameinfo_link.c */,
                                FC5285D1114791B50058CCB0 /* DSlibinfoMIG.defs */,
                        children = (
                                2D4070B0129354A700FE81ED /* getnameinfo_link.c */,
                                FC5285D1114791B50058CCB0 /* DSlibinfoMIG.defs */,
-                               FC5285D2114791B50058CCB0 /* DSlibinfoMIGAsyncReply.defs */,
                                FC52841811478C200058CCB0 /* aliasdb.h */,
                                FC52841911478C200058CCB0 /* bootparams.5 */,
                                FC52841A11478C200058CCB0 /* bootparams.h */,
                                FC52841811478C200058CCB0 /* aliasdb.h */,
                                FC52841911478C200058CCB0 /* bootparams.5 */,
                                FC52841A11478C200058CCB0 /* bootparams.h */,
                                FC52842311478C200058CCB0 /* getnameinfo.3 */,
                                FC52842411478C200058CCB0 /* getnetgrent.3 */,
                                FC52842511478C200058CCB0 /* getpwent.3 */,
                                FC52842311478C200058CCB0 /* getnameinfo.3 */,
                                FC52842411478C200058CCB0 /* getnetgrent.3 */,
                                FC52842511478C200058CCB0 /* getpwent.3 */,
+                               FCFDBF0A145CC5C100A39A66 /* grp.h */,
                                FC52842611478C200058CCB0 /* ils.c */,
                                FC52842711478C200058CCB0 /* ils.h */,
                                FC52842811478C200058CCB0 /* initgroups.3 */,
                                FC52842611478C200058CCB0 /* ils.c */,
                                FC52842711478C200058CCB0 /* ils.h */,
                                FC52842811478C200058CCB0 /* initgroups.3 */,
                                FC52842F11478C200058CCB0 /* netdb.h */,
                                FC52843011478C200058CCB0 /* netdb_async.h */,
                                FC52843111478C200058CCB0 /* printerdb.h */,
                                FC52842F11478C200058CCB0 /* netdb.h */,
                                FC52843011478C200058CCB0 /* netdb_async.h */,
                                FC52843111478C200058CCB0 /* printerdb.h */,
+                               FCFDBF0B145CC5C100A39A66 /* pwd.h */,
                                FC52843211478C200058CCB0 /* search_module.c */,
                                FC52843311478C200058CCB0 /* si_data.c */,
                                FC52843411478C200058CCB0 /* si_data.h */,
                                FC52843211478C200058CCB0 /* search_module.c */,
                                FC52843311478C200058CCB0 /* si_data.c */,
                                FC52843411478C200058CCB0 /* si_data.h */,
                FC52843A11478C200058CCB0 /* membership.subproj */ = {
                        isa = PBXGroup;
                        children = (
                FC52843A11478C200058CCB0 /* membership.subproj */ = {
                        isa = PBXGroup;
                        children = (
-                               FC5285D3114791B50058CCB0 /* DSmemberdMIG.defs */,
                                FC52843C11478C200058CCB0 /* mbr_check_membership.3 */,
                                FC52843D11478C200058CCB0 /* mbr_uid_to_uuid.3 */,
                                FC52843E11478C200058CCB0 /* membership.c */,
                                FC52843C11478C200058CCB0 /* mbr_check_membership.3 */,
                                FC52843D11478C200058CCB0 /* mbr_uid_to_uuid.3 */,
                                FC52843E11478C200058CCB0 /* membership.c */,
 /* Begin PBXProject section */
                08FB7793FE84155DC02AAC07 /* Project object */ = {
                        isa = PBXProject;
 /* Begin PBXProject section */
                08FB7793FE84155DC02AAC07 /* Project object */ = {
                        isa = PBXProject;
+                       attributes = {
+                               LastUpgradeCheck = 0440;
+                       };
                        buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "Libinfo" */;
                        buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "Libinfo" */;
-                       compatibilityVersion = "Xcode 3.1";
+                       compatibilityVersion = "Xcode 3.2";
                        developmentRegion = English;
                        hasScannedForEncodings = 1;
                        knownRegions = (
                        developmentRegion = English;
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                FC52855D11478C200058CCB0 /* rcmd.c in Sources */,
                                FC52855E11478C200058CCB0 /* rcmdsh.c in Sources */,
                                FC5285D4114791B50058CCB0 /* DSlibinfoMIG.defs in Sources */,
                                FC52855D11478C200058CCB0 /* rcmd.c in Sources */,
                                FC52855E11478C200058CCB0 /* rcmdsh.c in Sources */,
                                FC5285D4114791B50058CCB0 /* DSlibinfoMIG.defs in Sources */,
-                               FC5285D5114791B50058CCB0 /* DSlibinfoMIGAsyncReply.defs in Sources */,
-                               FC5285D6114791B50058CCB0 /* DSmemberdMIG.defs in Sources */,
                                FC5285F7114793400058CCB0 /* ether_addr.c in Sources */,
                                2D31A0FC128074E700D5A84C /* getifmaddrs.c in Sources */,
                                2D4070B1129354A700FE81ED /* getnameinfo_link.c in Sources */,
                                FC5285F7114793400058CCB0 /* ether_addr.c in Sources */,
                                2D31A0FC128074E700D5A84C /* getifmaddrs.c in Sources */,
                                2D4070B1129354A700FE81ED /* getnameinfo_link.c in Sources */,
                                );
                                INSTALLHDRS_SCRIPT_PHASE = YES;
                                INSTALL_PATH = /usr/lib/system;
                                );
                                INSTALLHDRS_SCRIPT_PHASE = YES;
                                INSTALL_PATH = /usr/lib/system;
+                               ORDER_FILE = "$(SDKROOT)/$(APPLE_INTERNAL_DIR)/OrderFiles/libsystem_info.order";
                                PRODUCT_NAME = info;
                                VERSION_INFO_EXPORT_DECL = static;
                                VERSION_INFO_PREFIX = __;
                                PRODUCT_NAME = info;
                                VERSION_INFO_EXPORT_DECL = static;
                                VERSION_INFO_PREFIX = __;
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                GCC_TREAT_WARNINGS_AS_ERRORS = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               PREBINDING = NO;
                                VERSIONING_SYSTEM = "apple-generic";
                                WARNING_LDFLAGS = "-Wall";
                        };
                                VERSIONING_SYSTEM = "apple-generic";
                                WARNING_LDFLAGS = "-Wall";
                        };
index 8737a10ae12d29ea6bb8cff85c5305ff1dcde948..7c85286ff887fcc18de18bc632055dbd9e51ec6b 100644 (file)
@@ -114,7 +114,7 @@ argument specifies the address family
 etc.) of this address.
 .Pp
 The structure returned contains information obtained from
 etc.) of this address.
 .Pp
 The structure returned contains information obtained from
-.Xr DirectoryService 8 ,
+.Xr mDNSResponder 8 ,
 including records in
 .Pa /etc/hosts .
 .\"The structure returned contains either the information obtained from the name
 including records in
 .Pa /etc/hosts .
 .\"The structure returned contains either the information obtained from the name
@@ -305,7 +305,7 @@ for example, a mail-forwarder may be registered for this domain.
 .Xr resolver 3 ,
 .Xr hosts 5 ,
 .Xr hostname 7 ,
 .Xr resolver 3 ,
 .Xr hosts 5 ,
 .Xr hostname 7 ,
-.Xr DirectoryService 8
+.Xr mDNSResponder 8
 .\".Xr named 8
 .Sh CAVEAT
 The
 .\".Xr named 8
 .Sh CAVEAT
 The
index 5e344999b59591486738725ec9778af4acf132ca..55723c3230383a20b9b9a8cb8242d6f30f68b507 100644 (file)
@@ -73,7 +73,7 @@ following structure describing an internet network.
 .\"`networks' entry in
 .\".Xr nsswitch.conf 5 .
 This structure contains information obtained from
 .\"`networks' entry in
 .\".Xr nsswitch.conf 5 .
 This structure contains information obtained from
-.Xr DirectoryService 8 ,
+.Xr opendirectoryd 8 ,
 including records in
 .Pa /etc/networks .
 .Pp
 including records in
 .Pa /etc/networks .
 .Pp
index 6a55ee1eb34360234447270dc2f88a404165e162..5a39a1b78a89612f4d7db5aff5e82ce7932e87c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2008-2010 Apple Inc.  All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc.  All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -191,7 +191,7 @@ cache_group_all(si_mod_t *si)
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-cache_grouplist(si_mod_t *si, const char *name)
+cache_grouplist(si_mod_t *si, const char *name, uint32_t count)
 {
        return cache_fetch_item(si, CATEGORY_GROUPLIST, name, 0, SEL_NAME);
 }
 {
        return cache_fetch_item(si, CATEGORY_GROUPLIST, name, 0, SEL_NAME);
 }
@@ -409,10 +409,12 @@ si_module_static_cache(void)
 
                .sim_user_byname = &cache_user_byname,
                .sim_user_byuid = &cache_user_byuid,
 
                .sim_user_byname = &cache_user_byname,
                .sim_user_byuid = &cache_user_byuid,
+               .sim_user_byuuid = NULL,
                .sim_user_all = &cache_user_all,
 
                .sim_group_byname = &cache_group_byname,
                .sim_group_bygid = &cache_group_bygid,
                .sim_user_all = &cache_user_all,
 
                .sim_group_byname = &cache_group_byname,
                .sim_group_bygid = &cache_group_bygid,
+               .sim_group_byuuid = NULL,
                .sim_group_all = &cache_group_all,
 
                .sim_grouplist = &cache_grouplist,
                .sim_group_all = &cache_group_all,
 
                .sim_grouplist = &cache_grouplist,
index 3c4e3e4940b4ff2b106b3192554fe9e59c614391..65ff3a8c21bdee4717bd785ef15df82e462f466f 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2008-2010 Apple Inc.  All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc.  All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 
  * @APPLE_LICENSE_HEADER_END@
  */
 
-#include <mach/mach.h>
-
-kern_return_t
-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)
-{
-       return KERN_SUCCESS;
-}
-
 #ifdef DS_AVAILABLE
 
 #include <stdio.h>
 #ifdef DS_AVAILABLE
 
 #include <stdio.h>
@@ -39,8 +31,8 @@ libinfoDSmig_do_Response_async(mach_port_t server, char *reply, mach_msg_type_nu
 #include <errno.h>
 #include <arpa/inet.h>
 #include <sys/stat.h>
 #include <errno.h>
 #include <arpa/inet.h>
 #include <sys/stat.h>
+#include <pthread.h>
 #include <ils.h>
 #include <ils.h>
-#include "kvbuf.h"
 #include <pwd.h>
 #include <grp.h>
 #include <fstab.h>
 #include <pwd.h>
 #include <grp.h>
 #include <fstab.h>
@@ -51,90 +43,82 @@ libinfoDSmig_do_Response_async(mach_port_t server, char *reply, mach_msg_type_nu
 #include <si_module.h>
 #include <netdb_async.h>
 #include <net/if.h>
 #include <si_module.h>
 #include <netdb_async.h>
 #include <net/if.h>
+#include <xpc/xpc.h>
+#include <xpc/private.h>
+#include <opendirectory/odipc.h>
 #include <servers/bootstrap.h>
 #include <bootstrap_priv.h>
 #include <servers/bootstrap.h>
 #include <bootstrap_priv.h>
-#include "DSlibinfoMIG.h"
-#include "DSmemberdMIG.h"
+#include <opendirectory/DSlibinfoMIG_types.h>
 #ifdef DEBUG
 #include <asl.h>
 #endif
 
 #ifdef DEBUG
 #include <asl.h>
 #endif
 
-#define SOCK_UNSPEC 0
-#define IPPROTO_UNSPEC 0
+#ifdef __i386__
+/* <rdar://problem/10675978> */
+__attribute__((weak_import))
+void xpc_dictionary_get_audit_token(xpc_object_t xdict, audit_token_t *token);
 
 
-#define IPV6_ADDR_LEN 16
-#define IPV4_ADDR_LEN 4
+__attribute__((weak_import))
+xpc_pipe_t xpc_pipe_create(const char *name, uint64_t flags);
 
 
-#define WANT_NOTHING 0
-#define WANT_A4_ONLY 1
-#define WANT_A6_ONLY 2
-#define WANT_A6_PLUS_MAPPED_A4 3
-#define WANT_MAPPED_A4_ONLY 4
+__attribute__((weak_import))
+void xpc_pipe_invalidate(xpc_pipe_t pipe);
+
+__attribute__((weak_import))
+int xpc_pipe_routine(xpc_pipe_t pipe, xpc_object_t message, xpc_object_t *reply);
+#endif
 
 
-/* ONLY TO BE USED BY getipv6nodebyaddr */
-#define WANT_A6_OR_MAPPED_A4_IF_NO_A6 5
+#define IPV6_ADDR_LEN 16
+#define IPV4_ADDR_LEN 4
 
 
-#define MAX_LOOKUP_ATTEMPTS 10
+typedef si_item_t *(*od_extract_t)(si_mod_t *si, xpc_object_t reply, const void *extra, uint64_t valid_global, uint64_t valid_cat);
 
 
-#define INET_NTOP_AF_INET_OFFSET 4
-#define INET_NTOP_AF_INET6_OFFSET 8
+/* notify SPI */
+uint32_t notify_peek(int token, uint32_t *val);
 
 
-mach_port_t _ds_port;
-mach_port_t _mbr_port;
+typedef struct
+{
+       int notify_token_global;
+       int notify_token_user;
+       int notify_token_group;
+       int notify_token_service;
+} ds_si_private_t;
 
 extern uint32_t gL1CacheEnabled;
 
 extern uint32_t gL1CacheEnabled;
+extern int _si_opendirectory_disabled;
 
 static pthread_key_t _ds_serv_cache_key = 0;
 
 static pthread_key_t _ds_serv_cache_key = 0;
+static xpc_pipe_t __od_pipe;   /* use accessor only */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+mach_port_t _ds_port;
 
 static void
 
 static void
-_ds_child(void)
+_od_fork_child(void)
 {
 {
+       // re-enable opendirectory interaction since we forked
+       _si_opendirectory_disabled = 0;
+       
+       if (__od_pipe != NULL) {
+               xpc_pipe_invalidate(__od_pipe);
+               /* disable release due to 10649340, it will cause a minor leak for each fork without exec */
+               // xpc_release(__od_pipe);
+               __od_pipe = NULL;
+       }
        _ds_port = MACH_PORT_NULL;
        _ds_port = MACH_PORT_NULL;
-       _mbr_port = MACH_PORT_NULL;
+       pthread_mutex_unlock(&mutex);
 }
 
 }
 
-static int _si_opendirectory_disabled;
-
-void
-_si_disable_opendirectory(void)
+static void
+_od_fork_prepare(void)
 {
 {
-       _si_opendirectory_disabled = 1;
-       _ds_port = MACH_PORT_NULL;
-       _mbr_port = MACH_PORT_NULL;
+       pthread_mutex_lock(&mutex);
 }
 
 }
 
-int
-_ds_running(void)
+static void
+_od_fork_parent(void)
 {
 {
-       kern_return_t status;
-       char *od_debug_mode = NULL;
-       
-       if (_ds_port != MACH_PORT_NULL) return 1;
-       
-       if (_si_opendirectory_disabled) return 0;
-       pthread_atfork(NULL, NULL, _ds_child);
-       
-       if (!issetugid()) {
-               od_debug_mode = getenv("OD_DEBUG_MODE");
-       }
-       
-       if (od_debug_mode) {
-               status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName "_debug", &_ds_port);
-       } else {
-               status = bootstrap_look_up2(bootstrap_port, kDSStdMachDSLookupPortName, 
-                                                                       &_ds_port, 0, BOOTSTRAP_PRIVILEGED_SERVER);
-       }
-       if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL;
-       
-       if (od_debug_mode) {
-               status = bootstrap_look_up(bootstrap_port, kDSStdMachDSMembershipPortName "_debug", &_mbr_port);
-       } else {
-               status = bootstrap_look_up2(bootstrap_port, kDSStdMachDSMembershipPortName, 
-                                                                       &_mbr_port, 0, BOOTSTRAP_PRIVILEGED_SERVER);
-       }
-       if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _mbr_port = MACH_PORT_NULL;
-       
-       return (_ds_port != MACH_PORT_NULL);
+       pthread_mutex_unlock(&mutex);
 }
 
 static void
 }
 
 static void
@@ -143,197 +127,128 @@ _ds_serv_cache_free(void *x)
        if (x != NULL) si_item_release(x);
 }
 
        if (x != NULL) si_item_release(x);
 }
 
-static kern_return_t
-LI_DSLookupGetProcedureNumber(const char *name, int32_t *procno)
+void
+_si_disable_opendirectory(void)
 {
 {
-       kern_return_t status;
-       security_token_t token;
-       uint32_t n, len;
-
-       if (name == NULL) return KERN_FAILURE;
-
-       len = strlen(name) + 1;
-       if (len == 1) return KERN_FAILURE;
-
-       token.val[0] = -1;
-       token.val[1] = -1;
+       _si_opendirectory_disabled = 1;
+       _ds_port = MACH_PORT_NULL;
+}
 
 
-       if (_ds_running() == 0) return KERN_FAILURE;
-       if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE;
+XPC_RETURNS_RETAINED
+static xpc_pipe_t
+_od_xpc_pipe(bool resetPipe)
+{
+       static dispatch_once_t once;
+       xpc_pipe_t result = NULL;
 
 
-       status = MIG_SERVER_DIED;
-       for (n = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
-       {
-               status = libinfoDSmig_GetProcedureNumber(_ds_port, (char *)name, procno, &token);
+#ifdef __i386__
+       if (xpc_pipe_create == NULL) {
+               _si_disable_opendirectory();
+               return NULL;
+       }
+#endif
 
 
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1);
-                       status = bootstrap_look_up2(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port, 0, BOOTSTRAP_PRIVILEGED_SERVER);
-                       if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL;
-                       status = MIG_SERVER_DIED;
+       dispatch_once(&once, ^(void) {
+               char *rc_xbs;
+               
+               /* if this is a build environment we ignore opendirectoryd */
+               rc_xbs = getenv("RC_XBS");
+               if ((issetugid() == 0) && (rc_xbs != NULL) && (strcmp(rc_xbs, "YES") == 0)) {
+                       _si_opendirectory_disabled = 1;
+                       return;
                }
                }
-       }
 
 
-       if (status != KERN_SUCCESS)
-       {
-#ifdef DEBUG
-               asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s status %u", name, status);
-#endif
-               return status;
+               pthread_atfork(_od_fork_prepare, _od_fork_parent, _od_fork_child);
+       });
+       
+       if (_si_opendirectory_disabled == 1) {
+               return NULL;
        }
        }
-
-       if (token.val[0] != 0)
-       {
-#ifdef DEBUG
-               asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s auth failure uid=%d", name, token.val[0]);
-#endif
-               return KERN_FAILURE;
+       
+       pthread_mutex_lock(&mutex);
+       if (resetPipe) {
+               xpc_release(__od_pipe);
+               __od_pipe = NULL;
        }
        }
-
-#ifdef DEBUG
-       asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s = %d", name, *procno);
-#endif
-       return status;
+       
+       if (__od_pipe == NULL) {
+               if (!issetugid() && getenv("OD_DEBUG_MODE") != NULL) {
+                       __od_pipe = xpc_pipe_create(kODMachLibinfoPortNameDebug, 0);
+               } else {
+                       __od_pipe = xpc_pipe_create(kODMachLibinfoPortName, XPC_PIPE_FLAG_PRIVILEGED);
+               }
+       }
+       
+       if (__od_pipe != NULL) result = xpc_retain(__od_pipe);
+       pthread_mutex_unlock(&mutex);
+       
+       return result;
 }
 
 }
 
-static kern_return_t
-LI_DSLookupQuery(int32_t procno, kvbuf_t *request, kvarray_t **reply)
+static bool
+_od_running(void)
 {
 {
-       kern_return_t status;
-       security_token_t token;
-       uint32_t n;
-       mach_msg_type_number_t illen, oolen;
-       char ilbuf[MAX_MIG_INLINE_DATA];
-       vm_offset_t oobuf;
-       kvbuf_t *out;
-
-       if (reply == NULL) return KERN_FAILURE;
-       if ((request != NULL) && ((request->databuf == NULL) || (request->datalen == 0))) return KERN_FAILURE;
-
-       token.val[0] = -1;
-       token.val[1] = -1;
-       *reply = NULL;
+       xpc_pipe_t pipe;
 
 
-       if (_ds_running() == 0) return KERN_FAILURE;
-       if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE;
-
-       status = MIG_SERVER_DIED;
-       for (n = 0; (_ds_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
-       {
-               illen = 0;
-               oolen = 0;
-               oobuf = 0;
-
-               if (request != NULL)
-               {
-                       status = libinfoDSmig_Query(_ds_port, procno, request->databuf, request->datalen, ilbuf, &illen, &oobuf, &oolen, &token);
-               }
-               else
-               {
-                       status = libinfoDSmig_Query(_ds_port, procno, "", 0, ilbuf, &illen, &oobuf, &oolen, &token);
-               }
-
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1);
-                       status = bootstrap_look_up2(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port, 0, BOOTSTRAP_PRIVILEGED_SERVER);
-                       if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL;
-                       status = MIG_SERVER_DIED;
-               }
+       pipe = _od_xpc_pipe(false);
+       if (pipe != NULL) {
+               xpc_release(pipe);
        }
 
        }
 
-       if (status != KERN_SUCCESS)
-       {
-#ifdef DEBUG
-               asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status %u", procno, status);
-#endif
-               return status;
+       if (_si_opendirectory_disabled) {
+               return 0;
        }
 
        }
 
-       if (token.val[0] != 0)
-       {
-#ifdef DEBUG
-               asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d auth failure uid=%d", procno, token.val[0]);
-#endif
-               if ((oolen > 0) && (oobuf != 0)) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen);
-               return KERN_FAILURE;
-       }
+       return (pipe != NULL);
+}
 
 
-       out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t));
-       if (out == NULL)
-       {
-               if ((oolen > 0) && (oobuf != 0)) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen);
-               return KERN_FAILURE;
-       }
+static void
+_ds_child(void)
+{
+       _ds_port = MACH_PORT_NULL;
+}
 
 
-       if ((oolen > 0) && (oobuf != 0))
-       {
-               out->datalen = oolen;
-               out->databuf = malloc(oolen);
-               if (out->databuf == NULL)
-               {
-                       free(out);
-                       *reply = NULL;
-                       vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen);
-                       return KERN_FAILURE;
-               }
+int
+_ds_running(void)
+{
+       kern_return_t status;
+       char *od_debug_mode = NULL;
 
 
-               memcpy(out->databuf, (char *)oobuf, oolen);
-               vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen);
-       }
-       else if (illen > 0)
-       {
-               out->datalen = illen;
-               out->databuf = malloc(illen);
-               if (out->databuf == NULL)
-               {
-                       free(out);
-                       *reply = NULL;
-                       return KERN_FAILURE;
-               }
+       if (_ds_port != MACH_PORT_NULL) return 1;
+
+       if (_si_opendirectory_disabled) return 0;
+       pthread_atfork(NULL, NULL, _ds_child);
 
 
-               memcpy(out->databuf, ilbuf, illen);
+       if (!issetugid()) {
+               od_debug_mode = getenv("OD_DEBUG_MODE");
        }
 
        }
 
-       *reply = kvbuf_decode(out);
-       if (*reply == NULL)
-       {
-               /* DS returned no data */
-               free(out->databuf);
-               free(out);
+       if (od_debug_mode) {
+               status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName "_debug", &_ds_port);
+       } else {
+               status = bootstrap_look_up2(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port, 0, BOOTSTRAP_PRIVILEGED_SERVER);
        }
        }
+       if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL;
 
 
-#ifdef DEBUG
-       asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status OK", procno);
-#endif
-       return status;
+       return (_ds_port != MACH_PORT_NULL);
 }
 
 }
 
-/* notify SPI */
-uint32_t notify_peek(int token, uint32_t *val);
-
-typedef struct
-{
-       int notify_token_global;
-       int notify_token_user;
-       int notify_token_group;
-       int notify_token_host;
-       int notify_token_service;
-} ds_si_private_t;
-
-static uid_t
-audit_token_uid(audit_token_t a)
+static bool
+_valid_token(xpc_object_t reply)
 {
 {
+       audit_token_t token;
+       
        /*
         * This should really call audit_token_to_au32,
         * but that's in libbsm, not in a Libsystem library.
         */
        /*
         * This should really call audit_token_to_au32,
         * but that's in libbsm, not in a Libsystem library.
         */
-       return (uid_t)a.val[1];
+       xpc_dictionary_get_audit_token(reply, &token);
+       
+       return ((uid_t) token.val[1] == 0);
 }
 
 static void
 }
 
 static void
-ds_get_validation(si_mod_t *si, uint64_t *a, uint64_t *b, int cat)
+_ds_get_validation(si_mod_t *si, uint64_t *a, uint64_t *b, int cat)
 {
        ds_si_private_t *pp;
        uint32_t peek;
 {
        ds_si_private_t *pp;
        uint32_t peek;
@@ -360,242 +275,172 @@ ds_get_validation(si_mod_t *si, uint64_t *a, uint64_t *b, int cat)
                if (cat == CATEGORY_USER) status = notify_peek(pp->notify_token_user, &peek);
                else if (cat == CATEGORY_GROUP) status = notify_peek(pp->notify_token_group, &peek);
                else if (cat == CATEGORY_GROUPLIST) status = notify_peek(pp->notify_token_group, &peek);
                if (cat == CATEGORY_USER) status = notify_peek(pp->notify_token_user, &peek);
                else if (cat == CATEGORY_GROUP) status = notify_peek(pp->notify_token_group, &peek);
                else if (cat == CATEGORY_GROUPLIST) status = notify_peek(pp->notify_token_group, &peek);
-               else if (cat == CATEGORY_HOST_IPV4) status = notify_peek(pp->notify_token_host, &peek);
-               else if (cat == CATEGORY_HOST_IPV6) status = notify_peek(pp->notify_token_host, &peek);
                else if (cat == CATEGORY_SERVICE) status = notify_peek(pp->notify_token_service, &peek);
 
                if (status == NOTIFY_STATUS_OK) *b = ntohl(peek);
        }
 }
 
                else if (cat == CATEGORY_SERVICE) status = notify_peek(pp->notify_token_service, &peek);
 
                if (status == NOTIFY_STATUS_OK) *b = ntohl(peek);
        }
 }
 
-static si_list_t *
-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)
+XPC_RETURNS_RETAINED
+__private_extern__ xpc_object_t 
+_od_rpc_call(const char *procname, xpc_object_t payload, xpc_pipe_t (*get_pipe)(bool))
 {
 {
-       si_item_t *item;
-       si_list_t *list;
-       kvarray_t *reply;
-       kern_return_t status;
-       uint64_t va, vb;
-
-       if (*procnum < 0)
-       {
-               status = LI_DSLookupGetProcedureNumber(procname, procnum);
-               if (status != KERN_SUCCESS) return NULL;
+       xpc_object_t result = NULL;
+       xpc_object_t reply;
+       xpc_pipe_t od_pipe;
+       int retries, rc;
+       
+       od_pipe = get_pipe(false);
+       if (od_pipe == NULL) return NULL;
+       
+       if (payload == NULL) {
+               payload = xpc_dictionary_create(NULL, NULL, 0);
+       }
+       
+       // we nest it for backward compatibility so we can do independent submissions
+       xpc_dictionary_set_string(payload, OD_RPC_NAME, procname);
+       xpc_dictionary_set_int64(payload, OD_RPC_VERSION, 2);
+       
+       for (retries = 0; od_pipe != NULL && retries < 2; retries++) {
+               rc = xpc_pipe_routine(od_pipe, payload, &reply);
+               switch (rc) {
+                       case EPIPE:
+                               xpc_release(od_pipe);
+                               od_pipe = get_pipe(true);
+                               break;
+                               
+                       case EAGAIN:
+                               /* just loop and try to send again */
+                               break;
+                               
+                       case 0:
+                               if (_valid_token(reply) == true) {
+                                       result = reply;
+                               }
+                               /* fall through since we got a valid response */
+                               
+                       default:
+                               /* release and NULL the pipe it'll break the loop */
+                               xpc_release(od_pipe);
+                               od_pipe = NULL;
+                               break;
+               }
+       }
+       
+       if (od_pipe != NULL) {
+               xpc_release(od_pipe);
        }
 
        }
 
-       reply = NULL;
-       ds_get_validation(si, &va, &vb, cat);
-       status = LI_DSLookupQuery(*procnum, request, &reply);
+       return result;
+}
+
+static si_list_t *
+_ds_list(si_mod_t *si, int cat, const char *procname, const void *extra, od_extract_t extract)
+{
+       __block si_list_t *list;
+       uint64_t va, vb;
+       xpc_object_t reply, result;
 
 
-       if ((status != KERN_SUCCESS) || (reply == NULL)) return NULL;
+       if (procname == NULL) return NULL;
 
 
+       _ds_get_validation(si, &va, &vb, cat);
+       
        list = NULL;
        list = NULL;
-       while (reply->curr < reply->count)
-       {
-               item = extract(si, reply, extra, va, vb);
-               list = si_list_add(list, item);
-               si_item_release(item);
+       reply = _od_rpc_call(procname, NULL, _od_xpc_pipe);
+       if (reply != NULL) {
+               result = xpc_dictionary_get_value(reply, OD_RPC_RESULT);
+               if (result != NULL && xpc_get_type(result) == XPC_TYPE_ARRAY) {
+                       xpc_array_apply(result, ^bool(size_t index, xpc_object_t value) {
+                               si_item_t *item = extract(si, value, extra, va, vb);
+                               list = si_list_add(list, item);
+                               si_item_release(item);
+                               
+                               return true;
+                       });
+               }
+               
+               xpc_release(reply);
        }
 
        }
 
-       kvarray_free(reply);
-
        return list;
 }
 
 static si_item_t *
        return list;
 }
 
 static si_item_t *
-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)
+_ds_item(si_mod_t *si, int cat, const char *procname, const void *extra, od_extract_t extract, xpc_object_t payload)
 {
 {
-       si_item_t *item;
-       kvarray_t *reply;
-       kern_return_t status;
+       xpc_object_t result;
        uint64_t va, vb;
        uint64_t va, vb;
+       si_item_t *item = NULL;
+       
+       if (procname == NULL) return NULL;
 
 
-       if (*procnum < 0)
-       {
-               status = LI_DSLookupGetProcedureNumber(procname, procnum);
-               if (status != KERN_SUCCESS) return NULL;
+       result = _od_rpc_call(procname, payload, _od_xpc_pipe);
+       if (result != NULL) {
+               _ds_get_validation(si, &va, &vb, cat);
+               if (xpc_dictionary_get_int64(result, OD_RPC_ERROR) == 0) {
+                       item = extract(si, result, extra, va, vb);
+               }
+               
+               xpc_release(result);
        }
        }
-
-       reply = NULL;
-       ds_get_validation(si, &va, &vb, cat);
-       status = LI_DSLookupQuery(*procnum, request, &reply);
-
-       if ((status != KERN_SUCCESS) || (reply == NULL)) return NULL;
-
-       item = extract(si, reply, extra, va, vb);
-       kvarray_free(reply);
-
+       
        return item;
 }
 
        return item;
 }
 
-/*
- * Extract the next user entry from a kvarray.
- */
-static si_item_t *
-extract_user(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat)
+static int
+_ds_is_valid(si_mod_t *si, si_item_t *item)
 {
 {
-       struct passwd tmp;
-       uint32_t d, k, kcount;
-
-       if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
+       si_mod_t *src;
+       ds_si_private_t *pp;
+       int status;
+       uint32_t oldval, newval;
+       
+       if (si == NULL) return 0;
+       if (item == NULL) return 0;
+       if (si->name == NULL) return 0;
+       if (item->src == NULL) return 0;
+       
+       pp = (ds_si_private_t *)si->private;
+       if (pp == NULL) return 0;
+       
+       src = (si_mod_t *)item->src;
+       
+       if (src->name == NULL) return 0;
+       if (string_not_equal(si->name, src->name)) return 0;
+       
+       /* check global invalidation */
+       oldval = item->validation_a;
+       newval = -1;
+       status = notify_peek(pp->notify_token_global, &newval);
+       if (status != NOTIFY_STATUS_OK) return 0;
+       
+       newval = ntohl(newval);
+       if (oldval != newval) return 0;
+       
+       oldval = item->validation_b;
+       newval = -1;
+       if (item->type == CATEGORY_USER) status = notify_peek(pp->notify_token_user, &newval);
+       else if (item->type == CATEGORY_GROUP) status = notify_peek(pp->notify_token_group, &newval);
+       else if (item->type == CATEGORY_SERVICE) status = notify_peek(pp->notify_token_service, &newval);
+       else return 0;
+       
+       if (status != NOTIFY_STATUS_OK) return 0;
+       
+       newval = ntohl(newval);
+       if (oldval != newval) return 0;
+       
+       return 1;
+}
 
 
-       if (d >= in->count) return NULL;
+static void
+_free_addr_list(char **l)
+{
+       int i;
 
 
-       memset(&tmp, 0, sizeof(struct passwd));
-
-       tmp.pw_uid = -2;
-       tmp.pw_gid = -2;
-
-       kcount = in->dict[d].kcount;
-
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "pw_name"))
-               {
-                       if (tmp.pw_name != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.pw_name = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_passwd"))
-               {
-                       if (tmp.pw_passwd != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.pw_passwd = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_uid"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.pw_uid = atoi(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_gid"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.pw_gid = atoi(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_change"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.pw_change = atol(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_expire"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.pw_expire = atol(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_class"))
-               {
-                       if (tmp.pw_class != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.pw_class = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_gecos"))
-               {
-                       if (tmp.pw_gecos != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.pw_gecos = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_dir"))
-               {
-                       if (tmp.pw_dir != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.pw_dir = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "pw_shell"))
-               {
-                       if (tmp.pw_shell != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.pw_shell = (char *)in->dict[d].val[k][0];
-               }
-       }
-
-       if (tmp.pw_name == NULL) tmp.pw_name = "";
-       if (tmp.pw_passwd == NULL) tmp.pw_passwd = "";
-       if (tmp.pw_class == NULL) tmp.pw_class = "";
-       if (tmp.pw_gecos == NULL) tmp.pw_gecos = "";
-       if (tmp.pw_dir == NULL) tmp.pw_dir = "";
-       if (tmp.pw_shell == NULL) tmp.pw_shell = "";
-
-       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);
-}
-
-static si_item_t *
-extract_group(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat)
-{
-       struct group tmp;
-       char *empty[1];
-       uint32_t d, k, kcount;
-
-       if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       empty[0] = NULL;
-       memset(&tmp, 0, sizeof(struct group));
-
-       tmp.gr_gid = -2;
-
-       kcount = in->dict[d].kcount;
-
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "gr_name"))
-               {
-                       if (tmp.gr_name != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.gr_name = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "gr_passwd"))
-               {
-                       if (tmp.gr_passwd != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.gr_passwd = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "gr_gid"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.gr_gid = atoi(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "gr_mem"))
-               {
-                       if (tmp.gr_mem != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.gr_mem = (char **)in->dict[d].val[k];
-               }
-       }
-
-       if (tmp.gr_name == NULL) tmp.gr_name = "";
-       if (tmp.gr_passwd == NULL) tmp.gr_passwd = "";
-       if (tmp.gr_mem == NULL) tmp.gr_mem = empty;
-
-       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);
-}
-
-static void
-_free_addr_list(char **l)
-{
-       int i;
-
-       if (l == NULL) return;
-       for (i = 0; l[i] != NULL; i++) free(l[i]);
-       free(l);
-}
+       if (l == NULL) return;
+       for (i = 0; l[i] != NULL; i++) free(l[i]);
+       free(l);
+}
 
 /* map ipv4 addresses and append to v6 list */
 static int 
 
 /* map ipv4 addresses and append to v6 list */
 static int 
@@ -633,1107 +478,636 @@ _map_v4(char ***v6, uint32_t n6, char **v4, uint32_t n4)
        return 0;
 }
 
        return 0;
 }
 
-static si_item_t *
-extract_netgroup(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat)
+static xpc_object_t
+_xpc_query_key_string(const char *key, const char *value)
 {
 {
-       const char *host, *user, *domain;
-       uint32_t d, k, kcount;
-
-       if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       kcount = in->dict[d].kcount;
+       xpc_object_t payload;
+       
+       if (value == NULL) return NULL;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return NULL;
+       
+       xpc_dictionary_set_string(payload, key, value);
+       
+       return payload;
+}
 
 
-       host = NULL;
-       user = NULL;
-       domain = NULL;
+static xpc_object_t
+_xpc_query_key_id(const char *key, id_t idValue)
+{
+       xpc_object_t payload;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return NULL;
+       
+       xpc_dictionary_set_int64(payload, key, idValue);
+       
+       return payload;
+}
 
 
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "host"))
-               {
-                       if (host != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
+static xpc_object_t
+_xpc_query_key_uuid(const char *key, uuid_t uu)
+{
+       xpc_object_t payload;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return NULL;
+       
+       xpc_dictionary_set_uuid(payload, key, uu);
+       
+       return payload;
+}
 
 
-                       host = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "user"))
-               {
-                       if (user != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
+static xpc_object_t
+_xpc_query_key_int(const char *key, int64_t intValue)
+{
+       xpc_object_t payload;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return NULL;
+       
+       xpc_dictionary_set_int64(payload, key, intValue);
+       
+       return payload;
+}
 
 
-                       user = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "domain"))
-               {
-                       if (domain != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
+#pragma mark -
 
 
-                       domain = (char *)in->dict[d].val[k][0];
-               }
+static char **
+_extract_array(xpc_object_t reply, const char *key, unsigned int *len)
+{
+       xpc_object_t xpc_array;
+       char **result;
+       
+       xpc_array = xpc_dictionary_get_value(reply, key);
+       if (xpc_array == NULL || xpc_get_type(xpc_array) != XPC_TYPE_ARRAY) {
+               return calloc(1, sizeof(*result));
        }
        }
+       
+       result = calloc(xpc_array_get_count(xpc_array) + 1, sizeof(*result));
+       if (result == NULL) {
+               return NULL;
+       }
+       
+       if (len != NULL) {
+               /* include trailing NULL */
+               (*len) = xpc_array_get_count(xpc_array) + 1;
+       }
+       
+       xpc_array_apply(xpc_array, ^_Bool(size_t idx, xpc_object_t value) {
+               result[idx] = (char *) xpc_string_get_string_ptr(value);
+               return true;
+       });
+       
+       return result;
+}
 
 
-       if (host == NULL) host = "";
-       if (user == NULL) user = "";
-       if (domain == NULL) domain = "";
+static const char *
+_extract_string(xpc_object_t reply, const char *key)
+{
+       xpc_object_t value = xpc_dictionary_get_value(reply, key);
+       xpc_type_t type;
+       const char *result = NULL;
+       
+       if (value == NULL) {
+               return "";
+       }
+       
+       type = xpc_get_type(value);
+       if (type == XPC_TYPE_STRING) {
+               result = xpc_string_get_string_ptr(value);
+       } else if (type == XPC_TYPE_ARRAY && xpc_array_get_count(value) != 0) {
+               result = xpc_array_get_string(value, 0);
+       }
+       
+       if (result == NULL) {
+               result = "";
+       }
+       
+       return result;
+}
 
 
-       return (si_item_t *)LI_ils_create("L4488sss", (unsigned long)si, CATEGORY_ALIAS, 1, valid_global, valid_cat, host, user, domain);
+static uint32_t
+_extract_uint32(xpc_object_t reply, const char *key)
+{
+       xpc_object_t value = xpc_dictionary_get_value(reply, key);
+       xpc_type_t type;
+       uint32_t result;
+       
+       if (value == NULL) {
+               return 0;
+       }
+       
+       type = xpc_get_type(value);
+       if (type == XPC_TYPE_ARRAY && xpc_array_get_count(value) != 0) {
+               value = xpc_array_get_value(value, 0);
+               type = xpc_get_type(value);
+       }
+       
+       if (type == XPC_TYPE_STRING) {
+               result = (int) strtol(xpc_string_get_string_ptr(value), NULL, 10);
+       } else if (type == XPC_TYPE_INT64) {
+               result = (uint32_t) xpc_int64_get_value(value);
+       } else if (type == XPC_TYPE_BOOL) {
+               result = xpc_bool_get_value(value);
+       } else {
+               result = 0;
+       }
+       
+       return result;
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-extract_alias(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat)
+_extract_user(si_mod_t *si, xpc_object_t reply, __unused const void *ignored, uint64_t valid_global, uint64_t valid_cat)
 {
 {
-       struct aliasent tmp;
-       char *empty[1];
-       uint32_t d, k, kcount;
-
+       struct passwd tmp;
+       
        if (si == NULL) return NULL;
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       empty[0] = NULL;
-       memset(&tmp, 0, sizeof(struct group));
-
-       kcount = in->dict[d].kcount;
-
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "alias_name"))
-               {
-                       if (tmp.alias_name != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.alias_name = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "alias_members"))
-               {
-                       if (tmp.alias_members != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.alias_members_len = in->dict[d].vcount[k];
-                       tmp.alias_members = (char **)in->dict[d].val[k];
-               }
-               else if (string_equal(in->dict[d].key[k], "alias_local"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.alias_local = atoi(in->dict[d].val[k][0]);
-               }
-       }
-
-       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);
+       if (reply == NULL) return NULL;
+       
+       tmp.pw_name = (char *) _extract_string(reply, "pw_name");
+       tmp.pw_passwd = (char *) _extract_string(reply, "pw_passwd");
+       tmp.pw_uid = (uid_t) _extract_uint32(reply, "pw_uid");
+       tmp.pw_gid = (gid_t) _extract_uint32(reply, "pw_gid");
+       tmp.pw_change = (time_t) _extract_uint32(reply, "pw_change");
+       tmp.pw_expire = (time_t) _extract_uint32(reply, "pw_expire");
+       tmp.pw_class = (char *) _extract_string(reply, "pw_class");
+       tmp.pw_gecos = (char *) _extract_string(reply, "pw_gecos");
+       tmp.pw_dir = (char *) _extract_string(reply, "pw_dir");
+       tmp.pw_shell = (char *) _extract_string(reply, "pw_shell");
+       
+       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);
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-extract_host(si_mod_t *si, kvarray_t *in, void *extra, uint64_t valid_global, uint64_t valid_cat)
+_extract_group(si_mod_t *si, xpc_object_t reply, __unused const void *ignored, uint64_t valid_global, uint64_t valid_cat)
 {
 {
-       struct hostent tmp;
-       si_item_t *out;
-       uint32_t i, d, k, kcount, vcount, v4count, v6count, want;
-       int status, addr_len;
-       int family, addr_count;
-       struct in_addr a4;
-       struct in6_addr a6;
-       char **v4addrs, **v6addrs;
-       char *empty[1];
-
-       v4addrs = NULL;
-       v6addrs = NULL;
-       v4count = 0;
-       v6count = 0;
-       addr_count = 0;
-       addr_len = sizeof(void *);
-
+       si_item_t *item;
+       struct group tmp;
+       
        if (si == NULL) return NULL;
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       empty[0] = NULL;
-       memset(&tmp, 0, sizeof(struct hostent));
-
-       family = AF_INET;
-       tmp.h_length = IPV4_ADDR_LEN;
-
-       want = WANT_A4_ONLY;
-       if (extra != NULL) want = *(uint32_t *)extra;
-
-       if (want != WANT_A4_ONLY)
-       {
-               family = AF_INET6;
-               tmp.h_length = IPV6_ADDR_LEN;
-       }
-
-       tmp.h_addrtype = family;
-
-       kcount = in->dict[d].kcount;
-
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "h_name"))
-               {
-                       if (tmp.h_name != NULL) continue;
-
-                       vcount = in->dict[d].vcount[k];
-                       if (vcount == 0) continue;
-
-                       tmp.h_name = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "h_aliases"))
-               {
-                       if (tmp.h_aliases != NULL) continue;
-
-                       vcount = in->dict[d].vcount[k];
-                       if (vcount == 0) continue;
-
-                       tmp.h_aliases = (char **)in->dict[d].val[k];
-               }
-               else if (string_equal(in->dict[d].key[k], "h_ipv4_addr_list"))
-               {
-                       if (v4addrs != NULL) continue;
-
-                       v4count = in->dict[d].vcount[k];
-                       if (v4count == 0) continue;
-
-                       v4addrs = (char **)calloc(v4count + 1, sizeof(char *));
-                       if (v4addrs == NULL)
-                       {
-                               _free_addr_list(v6addrs);
-                               return NULL;
-                       }
-
-                       for (i = 0; i < v4count; i++)
-                       {
-                               v4addrs[i] = calloc(1, IPV4_ADDR_LEN);
-                               if (v4addrs[i] == NULL)
-                               {
-                                       _free_addr_list(v4addrs);
-                                       _free_addr_list(v6addrs);
-                                       return NULL;
-                               }
-
-                               memset(&a4, 0, sizeof(struct in_addr));
-                               status = inet_pton(AF_INET, in->dict[d].val[k][i], &a4);
-                               if (status != 1)
-                               {
-                                       _free_addr_list(v4addrs);
-                                       _free_addr_list(v6addrs);
-                                       return NULL;
-                               }
-
-                               memcpy(v4addrs[i], &a4, IPV4_ADDR_LEN);
-                       }
-               }
-               else if (string_equal(in->dict[d].key[k], "h_ipv6_addr_list"))
-               {
-                       if (v6addrs != NULL) continue;
-
-                       v6count = in->dict[d].vcount[k];
-                       if (v6count == 0) continue;
-
-                       v6addrs = (char **)calloc(v6count + 1, sizeof(char *));
-                       if (v6addrs == NULL)
-                       {
-                               _free_addr_list(v4addrs);
-                               return NULL;
-                       }
-
-                       for (i = 0; i < v6count; i++)
-                       {
-                               v6addrs[i] = calloc(1, IPV6_ADDR_LEN);
-                               if (v6addrs[i] == NULL)
-                               {
-                                       _free_addr_list(v4addrs);
-                                       _free_addr_list(v6addrs);
-                                       return NULL;
-                               }
-
-                               memset(&a6, 0, sizeof(struct in6_addr));
-                               status = inet_pton(AF_INET6, in->dict[d].val[k][i], &a6);
-                               if (status != 1)
-                               {
-                                       _free_addr_list(v4addrs);
-                                       _free_addr_list(v6addrs);
-                                       return NULL;
-                               }
+       if (reply == NULL) return NULL;
+       
+       tmp.gr_name = (char *) _extract_string(reply, "gr_name");
+       tmp.gr_passwd = (char *) _extract_string(reply, "gr_passwd");
+       tmp.gr_gid = (gid_t) _extract_uint32(reply, "gr_gid");
+       tmp.gr_mem = _extract_array(reply, "gr_mem", NULL);
 
 
-                               memcpy(v6addrs[i], &(a6.__u6_addr.__u6_addr32[0]), IPV6_ADDR_LEN);
-                       }
-               }
+       item = (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);
+       
+       if (tmp.gr_mem != NULL) {
+               free(tmp.gr_mem); /* have to free because it's allocated */
        }
        }
+       
+       return item;
+}
 
 
-       if (tmp.h_name == NULL) tmp.h_name = "";
-       if (tmp.h_aliases == NULL) tmp.h_aliases = empty;
+static si_item_t *
+_extract_netgroup(si_mod_t *si, xpc_object_t reply, const void *ignored, uint64_t valid_global, uint64_t valid_cat)
+{
+       const char *host, *user, *domain;
 
 
-       if (want == WANT_A4_ONLY)
-       {
-               _free_addr_list(v6addrs);
-               if (v4addrs == NULL) return NULL;
+       if (si == NULL) return NULL;
+       if (reply == NULL) return NULL;
 
 
-               tmp.h_addr_list = v4addrs;
-               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);
-               _free_addr_list(v4addrs);
-               return out;
-       }
-       else if ((want == WANT_A6_ONLY) || ((want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) && (v6count > 0)))
-       {
-               _free_addr_list(v4addrs);
-               if (v6addrs == NULL) return NULL;
+       host = _extract_string(reply, "host");
+       user = _extract_string(reply, "user");
+       domain = _extract_string(reply, "domain");
 
 
-               tmp.h_addr_list = v6addrs;
-               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);
-               _free_addr_list(v6addrs);
-               return out;
-       }
+       return (si_item_t *)LI_ils_create("L4488sss", (unsigned long)si, CATEGORY_NETGROUP, 1, valid_global, valid_cat, host, user, domain);
+}
 
 
-       /*
-        * At this point, want is WANT_A6_PLUS_MAPPED_A4, WANT_MAPPED_A4_ONLY,
-        * or WANT_A6_OR_MAPPED_A4_IF_NO_A6.  In the last case, there are no ipv6
-        * addresses, so that case degenerates into WANT_MAPPED_A4_ONLY.
-        */
-       if (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) want = WANT_MAPPED_A4_ONLY;
+static si_item_t *
+_extract_alias(si_mod_t *si, xpc_object_t reply, __unused const void *ignored, uint64_t valid_global, uint64_t valid_cat)
+{
+       struct aliasent tmp;
+       si_item_t *item;
 
 
-       if (want == WANT_MAPPED_A4_ONLY)
-       {
-               _free_addr_list(v6addrs);
-               v6addrs = NULL;
-               v6count = 0;
-       }
+       if (si == NULL) return NULL;
+       if (reply == NULL) return NULL;
+       
+       tmp.alias_name = (char *) _extract_string(reply, "alias_name");
+       tmp.alias_local = _extract_uint32(reply, "alias_local");
+       tmp.alias_members = _extract_array(reply, "alias_members", &tmp.alias_members_len);
 
 
-       status = _map_v4(&v6addrs, v6count, v4addrs, v4count);
-       _free_addr_list(v4addrs);
-       if (status != 0)
-       {
-               _free_addr_list(v6addrs);
-               return NULL;
+       item = (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);
+       
+       if (tmp.alias_members != NULL) {
+               free(tmp.alias_members);
        }
        }
-
-       if (v6addrs == NULL) return NULL;
-
-       tmp.h_addr_list = v6addrs;
-       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);
-       _free_addr_list(v6addrs);
-       return out;
+       
+       return item;
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-extract_network(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat)
+_extract_network(si_mod_t *si, xpc_object_t reply, __unused const void *ignored, uint64_t valid_global, uint64_t valid_cat)
 {
        struct netent tmp;
 {
        struct netent tmp;
-       uint32_t d, k, kcount;
-       char *empty[1];
+       si_item_t *item;
 
        if (si == NULL) return NULL;
 
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
+       if (reply == NULL) return NULL;
 
 
-       empty[0] = NULL;
-       memset(&tmp, 0, sizeof(struct netent));
-
-       tmp.n_addrtype = AF_INET;
-
-       kcount = in->dict[d].kcount;
-
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "n_name"))
-               {
-                       if (tmp.n_name != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.n_name = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "n_net"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.n_net = inet_network(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "n_addrtype"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.n_addrtype = atoi(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "n_aliases"))
-               {
-                       if (tmp.n_aliases != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
+       tmp.n_name = (char *) _extract_string(reply, "n_name");
+       tmp.n_aliases = _extract_array(reply, "n_aliases", NULL);
+       tmp.n_net = _extract_uint32(reply, "n_net");
+       tmp.n_addrtype = AF_INET; /* opendirectoryd doesn't return this value, only AF_INET is supported */
 
 
-                       tmp.n_aliases = (char **)in->dict[d].val[k];
-               }
+       item = (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);
+       
+       if (tmp.n_aliases != NULL) {
+               free(tmp.n_aliases);
        }
        }
-
-       if (tmp.n_name == NULL) tmp.n_name = "";
-       if (tmp.n_aliases == NULL) tmp.n_aliases = empty;
-
-       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);
+       
+       return item;
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-extract_service(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat)
+_extract_service(si_mod_t *si, xpc_object_t reply, __unused const void *ignored, uint64_t valid_global, uint64_t valid_cat)
 {
        struct servent tmp;
 {
        struct servent tmp;
-       char *empty[1];
-       uint32_t d, k, kcount;
+       si_item_t *item;
 
        if (si == NULL) return NULL;
 
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       empty[0] = NULL;
-       memset(&tmp, 0, sizeof(struct servent));
-
-       kcount = in->dict[d].kcount;
-
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "s_name"))
-               {
-                       if (tmp.s_name != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.s_name = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "s_aliases"))
-               {
-                       if (tmp.s_aliases != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.s_aliases = (char **)in->dict[d].val[k];
-               }
-               else if (string_equal(in->dict[d].key[k], "s_port"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.s_port = atoi(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "s_proto"))
-               {
-                       if (tmp.s_proto != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
+       if (reply == NULL) return NULL;
+       
+       tmp.s_name = (char *) _extract_string(reply, "s_name");
+       tmp.s_aliases = _extract_array(reply, "s_aliases", NULL);
+       tmp.s_port = (unsigned int) htons(_extract_uint32(reply, "s_port"));
+       tmp.s_proto = (char *) _extract_string(reply, "s_proto");
 
 
-                       tmp.s_proto = (char *)in->dict[d].val[k][0];
-               }
+       item = (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);
+       
+       if (tmp.s_aliases != NULL) {
+               free(tmp.s_aliases);
        }
        }
-
-       if (tmp.s_name == NULL) tmp.s_name = "";
-       if (tmp.s_proto == NULL) tmp.s_proto = "";
-       if (tmp.s_aliases == NULL) tmp.s_aliases = empty;
-
-       /* strange but correct */
-       tmp.s_port = htons(tmp.s_port);
-
-       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);
+       
+       return item;
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-extract_protocol(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat)
+_extract_protocol(si_mod_t *si, xpc_object_t reply, __unused const void *ignored, uint64_t valid_global, uint64_t valid_cat)
 {
        struct protoent tmp;
 {
        struct protoent tmp;
-       uint32_t d, k, kcount;
-       char *empty[1];
+       si_item_t *item;
 
        if (si == NULL) return NULL;
 
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       empty[0] = NULL;
-       memset(&tmp, 0, sizeof(struct protoent));
-
-       kcount = in->dict[d].kcount;
-
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "p_name"))
-               {
-                       if (tmp.p_name != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
+       if (reply == NULL) return NULL;
 
 
-                       tmp.p_name = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "p_proto"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.p_proto = atoi(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "p_aliases"))
-               {
-                       if (tmp.p_aliases != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
+       tmp.p_name = (char *) _extract_string(reply, "p_name");
+       tmp.p_proto = (int) _extract_uint32(reply, "p_proto");
+       tmp.p_aliases = _extract_array(reply, "p_aliases", NULL);
 
 
-                       tmp.p_aliases = (char **)in->dict[d].val[k];
-               }
+       item = (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);
+       if (tmp.p_aliases != NULL) {
+               free(tmp.p_aliases);
        }
        }
-
-       if (tmp.p_name == NULL) tmp.p_name = "";
-       if (tmp.p_aliases == NULL) tmp.p_aliases = empty;
-
-       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);
+       
+       return item;
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-extract_rpc(si_mod_t *si, kvarray_t *in, void *ignored, uint64_t valid_global, uint64_t valid_cat)
+_extract_rpc(si_mod_t *si, xpc_object_t reply, __unused const void *ignored, uint64_t valid_global, uint64_t valid_cat)
 {
        struct rpcent tmp;
 {
        struct rpcent tmp;
-       uint32_t d, k, kcount;
-       char *empty[1];
+       si_item_t *item;
 
        if (si == NULL) return NULL;
 
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       empty[0] = NULL;
-       memset(&tmp, 0, sizeof(struct rpcent));
+       if (reply == NULL) return NULL;
 
 
-       kcount = in->dict[d].kcount;
+       tmp.r_name = (char *) _extract_string(reply, "r_name");
+       tmp.r_number = (int) _extract_uint32(reply, "r_number");
+       tmp.r_aliases = _extract_array(reply, "r_aliases", NULL);
 
 
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "r_name"))
-               {
-                       if (tmp.r_name != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.r_name = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "r_number"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.r_number = atoi(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "r_aliases"))
-               {
-                       if (tmp.r_aliases != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.r_aliases = (char **)in->dict[d].val[k];
-               }
+       item = (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);
+       if (tmp.r_aliases != NULL) {
+               free(tmp.r_aliases);
        }
        }
-
-       if (tmp.r_name == NULL) tmp.r_name = "";
-       if (tmp.r_aliases == NULL) tmp.r_aliases = empty;
-
-       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);
+       
+       return item;
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-extract_fstab(si_mod_t *si, kvarray_t *in, void *extra, uint64_t valid_global, uint64_t valid_cat)
+_extract_fstab(si_mod_t *si, xpc_object_t reply, __unused const void *ignored, uint64_t valid_global, uint64_t valid_cat)
 {
        struct fstab tmp;
 {
        struct fstab tmp;
-       uint32_t d, k, kcount;
-       char *file;
 
        if (si == NULL) return NULL;
 
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
-
-       file = NULL;
-       if (extra != NULL) file = (char *)extra;
+       if (reply == NULL) return NULL;
 
 
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       memset(&tmp, 0, sizeof(struct fstab));
-
-       kcount = in->dict[d].kcount;
-
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "fs_spec"))
-               {
-                       if (tmp.fs_spec != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.fs_spec = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "fs_file"))
-               {
-                       if (tmp.fs_file != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.fs_file = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "fs_vfstype"))
-               {
-                       if (tmp.fs_vfstype != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.fs_vfstype = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "fs_mntops"))
-               {
-                       if (tmp.fs_mntops != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.fs_mntops = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "fs_type"))
-               {
-                       if (tmp.fs_type != NULL) continue;
-                       if (in->dict[d].vcount[k] == 0) continue;
-
-                       tmp.fs_type = (char *)in->dict[d].val[k][0];
-               }
-               else if (string_equal(in->dict[d].key[k], "fs_freq"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.fs_freq = atoi(in->dict[d].val[k][0]);
-               }
-               else if (string_equal(in->dict[d].key[k], "fs_passno"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       tmp.fs_passno = atoi(in->dict[d].val[k][0]);
-               }
-       }
-
-       if (tmp.fs_spec == NULL) tmp.fs_spec = "";
-       if (tmp.fs_file == NULL) tmp.fs_file = "";
-       if (tmp.fs_vfstype == NULL) tmp.fs_vfstype = "";
-       if (tmp.fs_mntops == NULL) tmp.fs_mntops = "";
-       if (tmp.fs_type == NULL) tmp.fs_type = "";
-
-       if ((file != NULL) && string_not_equal(file, tmp.fs_file)) return NULL;
+       tmp.fs_file = (char *) _extract_string(reply, "fs_file");
+       if (tmp.fs_file == NULL) return NULL;
+       
+       tmp.fs_spec = (char *) _extract_string(reply, "fs_spec");
+       tmp.fs_freq = _extract_uint32(reply, "fs_freq");
+       tmp.fs_passno = _extract_uint32(reply, "fs_passno");
+       tmp.fs_mntops = (char *) _extract_string(reply, "fs_mntops");
+       tmp.fs_type = (char *) _extract_string(reply, "fs_type");
+       tmp.fs_vfstype = (char *) _extract_string(reply, "fs_vfstype");
 
        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);
 }
 
 static si_item_t *
 
        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);
 }
 
 static si_item_t *
-extract_mac_mac(si_mod_t *si, kvarray_t *in, void *extra, uint64_t valid_global, uint64_t valid_cat)
+_extract_mac_mac(si_mod_t *si, xpc_object_t reply, const void *extra, uint64_t valid_global, uint64_t valid_cat)
 {
 {
-       uint32_t d, k, kcount;
+       const char *value;
        char *cmac;
        si_item_t *out;
 
        if (si == NULL) return NULL;
        char *cmac;
        si_item_t *out;
 
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
+       if (reply == NULL) return NULL;
        if (extra == NULL) return NULL;
 
        if (extra == NULL) return NULL;
 
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       kcount = in->dict[d].kcount;
-
-       cmac = NULL;
-       for (k = 0; k < kcount; k++)
-       {
-               if ((cmac == NULL) && (string_equal(in->dict[d].key[k], "mac")))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       cmac = si_standardize_mac_address(in->dict[d].val[k][0]);
-                       if (cmac == NULL) return NULL;
-               }
-       }
-
+       value = _extract_string(reply, "mac");
+       if (value == NULL || value[0] == '\0') return NULL;
+       
+       cmac = si_standardize_mac_address(value);
        if (cmac == NULL) return NULL;
 
        out = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, valid_global, valid_cat, extra, cmac);
        if (cmac == NULL) return NULL;
 
        out = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, valid_global, valid_cat, extra, cmac);
+       
        free(cmac);
        free(cmac);
+       
        return out;
 }
 
 static si_item_t *
        return out;
 }
 
 static si_item_t *
-extract_mac_name(si_mod_t *si, kvarray_t *in, void *extra, uint64_t valid_global, uint64_t valid_cat)
+_extract_mac_name(si_mod_t *si, xpc_object_t reply, const void *extra, uint64_t valid_global, uint64_t valid_cat)
 {
 {
-       uint32_t d, k, kcount;
        const char *name;
        si_item_t *out;
 
        if (si == NULL) return NULL;
        const char *name;
        si_item_t *out;
 
        if (si == NULL) return NULL;
-       if (in == NULL) return NULL;
+       if (reply == NULL) return NULL;
        if (extra == NULL) return NULL;
 
        if (extra == NULL) return NULL;
 
-       d = in->curr;
-       in->curr++;
-
-       if (d >= in->count) return NULL;
-
-       kcount = in->dict[d].kcount;
-
-       name = NULL;
-       for (k = 0; k < kcount; k++)
-       {
-               if ((name == NULL) && (string_equal(in->dict[d].key[k], "name")))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       name = in->dict[d].val[k][0];
-               }
-       }
-
-       if (name == NULL) return NULL;
+       name = _extract_string(reply, "name");
 
        out = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, valid_global, valid_cat, name, extra);
        return out;
 }
 
 
        out = (si_item_t *)LI_ils_create("L4488ss", (unsigned long)si, CATEGORY_MAC, 1, valid_global, valid_cat, name, extra);
        return out;
 }
 
-static si_item_t *
-ds_user_byname(si_mod_t *si, const char *name)
-{
-       static int proc = -1;
-       kvbuf_t *request;
-       si_item_t *item;
-
-       request = kvbuf_query_key_val("login", name);
-       if (request == NULL) return NULL;
-
-       item = ds_item(si, CATEGORY_USER, "getpwnam", &proc, NULL, extract_user, request);
-
-       kvbuf_free(request);
-       return item;
-}
-
-static si_item_t *
-ds_user_byuid(si_mod_t *si, uid_t uid)
-{
-       static int proc = -1;
-       char val[16];
-       kvbuf_t *request;
-       si_item_t *item;
-
-       snprintf(val, sizeof(val), "%d", (int)uid);
-       request = kvbuf_query_key_val("uid", val);
-       if (request == NULL) return NULL;
-
-       item = ds_item(si, CATEGORY_USER, "getpwuid", &proc, NULL, extract_user, request);
-
-       kvbuf_free(request);
-       return item;
-}
-
-static si_list_t *
-ds_user_all(si_mod_t *si)
-{
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_USER, "getpwent", &proc, NULL, extract_user, NULL);
-}
-
-static si_item_t *
-ds_group_byname(si_mod_t *si, const char *name)
-{
-       static int proc = -1;
-       kvbuf_t *request;
-       si_item_t *item;
-
-       request = kvbuf_query_key_val("name", name);
-       if (request == NULL) return NULL;
-
-       item = ds_item(si, CATEGORY_GROUP, "getgrnam", &proc, NULL, extract_group, request);
-
-       kvbuf_free(request);
-       return item;
-}
-
-static si_item_t *
-ds_group_bygid(si_mod_t *si, gid_t gid)
-{
-       static int proc = -1;
-       char val[16];
-       kvbuf_t *request;
-       si_item_t *item;
-
-       snprintf(val, sizeof(val), "%d", (int)gid);
-       request = kvbuf_query_key_val("gid", val);
-       if (request == NULL) return NULL;
-
-       item = ds_item(si, CATEGORY_GROUP, "getgrgid", &proc, NULL, extract_group, request);
-
-       kvbuf_free(request);
-       return item;
-}
-
-static si_list_t *
-ds_group_all(si_mod_t *si)
-{
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_GROUP, "getgrent", &proc, NULL, extract_group, NULL);
-}
-
-static si_item_t *
-ds_grouplist(si_mod_t *si, const char *name)
-{
-       struct passwd *pw;
-       kern_return_t kstatus, ks2;
-       uint32_t i, j, count, uid, basegid, gidptrCnt;
-       int32_t *gidp;
-       gid_t *gidptr;
-       audit_token_t token;
-       si_item_t *user, *item;
-       char **gidlist;
-       uint64_t va, vb;
-       size_t gidptrsz;
-       int n;
-
-       if (name == NULL) return NULL;
-
-       user = ds_user_byname(si, name);
-       if (user == NULL) return NULL;
-
-       pw = (struct passwd *)((uintptr_t)user + sizeof(si_item_t));
-       uid = pw->pw_uid;
-       basegid = pw->pw_gid;
-
-       free(user);
-
-       count = 0;
-       gidptr = NULL;
-       gidptrCnt = 0;
-       gidptrsz = 0;
-       memset(&token, 0, sizeof(audit_token_t));
-
-       if (_mbr_port == MACH_PORT_NULL)
-       {
-               kstatus = bootstrap_look_up2(bootstrap_port, kDSStdMachDSMembershipPortName, &_mbr_port, 0, BOOTSTRAP_PRIVILEGED_SERVER);
-       }
-
-       for (n = 0; n < MAX_LOOKUP_ATTEMPTS; n++)
-       {
-               kstatus = memberdDSmig_GetAllGroups(_mbr_port, uid, &count, &gidptr, &gidptrCnt, &token);
-               if (kstatus != MACH_SEND_INVALID_DEST) break;
-
-               mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1);
-
-               ks2 = bootstrap_look_up2(bootstrap_port, kDSStdMachDSMembershipPortName, &_mbr_port, 0, BOOTSTRAP_PRIVILEGED_SERVER);
-               if ((ks2 != BOOTSTRAP_SUCCESS) && (ks2 != BOOTSTRAP_UNKNOWN_SERVICE))
-               {
-                       _mbr_port = MACH_PORT_NULL;
-                       break;
-               }
-       }
-
-       if (kstatus != KERN_SUCCESS) return NULL;
-       if (gidptr == NULL) return NULL;
-
-       /* gidptrCnt is the size, but it was set to number of groups (by DS) in 10.6 and earlier */
-       gidptrsz = gidptrCnt;
-       if (count == gidptrCnt) gidptrsz = gidptrCnt * sizeof(gid_t);
-
-       if ((audit_token_uid(token) != 0) || (count == 0))
-       {
-               if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz);
-               return NULL;
-       }
-
-       gidlist = (char **)calloc(count + 1, sizeof(char *));
-       if (gidlist == NULL)
-       {
-               if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz);
-               return NULL;
-       }
-
-       for (i = 0; i < count; i++) 
-       {
-               gidp = (int32_t *)calloc(1, sizeof(int32_t));
-               if (gidp == NULL)
-               {
-                       for (j = 0; j < i; j++) free(gidlist[j]);
-                       free(gidlist);
-                       count = 0;
-                       break;
-               }
-
-               *gidp = gidptr[i];
-               gidlist[i] = (char *)gidp;
-       }
-
-       if (count == 0)
-       {
-               if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz);
-               return NULL;
-       }
+#pragma mark -
 
 
-       va = 0;
-       vb = 0;
-       ds_get_validation(si, &va, &vb, CATEGORY_GROUPLIST);
+static si_item_t *
+ds_user_byname(si_mod_t *si, const char *name)
+{
+       xpc_object_t payload;
+       si_item_t *item;
 
 
-       item = (si_item_t *)LI_ils_create("L4488s44a", (unsigned long)si, CATEGORY_GROUPLIST, 1, va, vb, name, basegid, count, gidlist);
+       if (!_od_running()) return NULL;
 
 
-       if (gidptr != NULL) vm_deallocate(mach_task_self(), (vm_address_t)gidptr, gidptrsz);
+       payload = _xpc_query_key_string("name", name);
+       if (payload == NULL) return NULL;
 
 
-       for (i = 0; i <= count; i++) free(gidlist[i]);
-       free(gidlist);
+       item = _ds_item(si, CATEGORY_USER, "getpwnam", NULL, _extract_user, payload);
 
 
+       xpc_release(payload);
        return item;
 }
 
        return item;
 }
 
-static si_list_t *
-ds_netgroup_byname(si_mod_t *si, const char *name)
+static si_item_t *
+ds_user_byuid(si_mod_t *si, uid_t uid)
 {
 {
-       static int proc = -1;
-       kvbuf_t *request;
-       si_list_t *list;
+       xpc_object_t payload;
+       si_item_t *item;
 
 
-       request = kvbuf_query_key_val("netgroup", name);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
 
 
-       list = ds_list(si, CATEGORY_NETGROUP, "getnetgrent", &proc, NULL, extract_netgroup, request);
+       payload = _xpc_query_key_id("uid", uid);
+       if (payload == NULL) return NULL;
 
 
-       kvbuf_free(request);
+       item = _ds_item(si, CATEGORY_USER, "getpwuid", NULL, _extract_user, payload);
 
 
-       return list;
+       xpc_release(payload);
+       return item;
 }
 
 }
 
-static int
-check_innetgr(kvarray_t *in)
+static si_item_t *
+ds_user_byuuid(si_mod_t *si, uuid_t uuid)
 {
 {
-       uint32_t d, k, kcount;
+       xpc_object_t payload;
+       si_item_t *item;
 
 
-       if (in == NULL) return 0;
+       if (!_od_running()) return NULL;
 
 
-       d = in->curr;
-       if (d >= in->count) return 0;
+       payload = _xpc_query_key_uuid("uuid", uuid);
+       if (payload == NULL) return NULL;
 
 
-       kcount = in->dict[d].kcount;
+       item = _ds_item(si, CATEGORY_USER, "getpwuuid", NULL, _extract_user, payload);
 
 
-       for (k = 0; k < kcount; k++)
-       {
-               if (string_equal(in->dict[d].key[k], "result"))
-               {
-                       if (in->dict[d].vcount[k] == 0) continue;
-                       return atoi(in->dict[d].val[k][0]);
-               }
-       }
+       xpc_release(payload);
+       return item;
+}
 
 
-       return 0;
+static si_list_t *
+ds_user_all(si_mod_t *si)
+{
+       return _ds_list(si, CATEGORY_USER, "getpwent", NULL, _extract_user);
 }
 
 }
 
-static int
-ds_in_netgroup(si_mod_t *si, const char *group, const char *host, const char *user, const char *domain)
+static si_item_t *
+ds_group_byname(si_mod_t *si, const char *name)
 {
 {
-       int is_innetgr;
-       kvbuf_t *request;
-       kvarray_t *reply;
-       kern_return_t status;
-       static int proc = -1;
+       xpc_object_t payload;
+       si_item_t *item;
 
 
-       if (proc < 0)
-       {
-               status = LI_DSLookupGetProcedureNumber("innetgr", &proc);
-               if (status != KERN_SUCCESS) return 0;
-       }
+       if (!_od_running()) return NULL;
 
 
-       /* Encode NULL */
-       if (group == NULL) group = "";
-       if (host == NULL) host = "";
-       if (user == NULL) user = "";
-       if (domain == NULL) domain = "";
+       payload = _xpc_query_key_string("name", name);
+       if (payload == NULL) return NULL;
 
 
-       request = kvbuf_query("ksksksks", "netgroup", group, "host", host, "user", user, "domain", domain);
-       if (request == NULL) return 0;
+       item = _ds_item(si, CATEGORY_GROUP, "getgrnam", NULL, _extract_group, payload);
 
 
-       reply = NULL;
-       status = LI_DSLookupQuery(proc, request, &reply);
-       kvbuf_free(request);
+       xpc_release(payload);
+       return item;
+}
 
 
-       if ((status != KERN_SUCCESS) || (reply == NULL)) return 0;
+static si_item_t *
+ds_group_bygid(si_mod_t *si, gid_t gid)
+{
+       xpc_object_t payload;
+       si_item_t *item;
 
 
-       is_innetgr = check_innetgr(reply);
+       if (!_od_running()) return NULL;
+       
+       payload = _xpc_query_key_id("gid", gid);
+       if (payload == NULL) return NULL;
 
 
-       kvarray_free(reply);
+       item = _ds_item(si, CATEGORY_GROUP, "getgrgid", NULL, _extract_group, payload);
 
 
-       return is_innetgr;
+       xpc_release(payload);
+       return item;
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-ds_alias_byname(si_mod_t *si, const char *name)
+ds_group_byuuid(si_mod_t *si, uuid_t uuid)
 {
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       request = kvbuf_query_key_val("name", name);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
+       
+       payload = _xpc_query_key_uuid("uuid", uuid);
+       if (payload == NULL) return NULL;
 
 
-       item = ds_item(si, CATEGORY_ALIAS, "alias_getbyname", &proc, NULL, extract_alias, request);
+       item = _ds_item(si, CATEGORY_GROUP, "getgruuid", NULL, _extract_group, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
        return item;
 }
 
 static si_list_t *
        return item;
 }
 
 static si_list_t *
-ds_alias_all(si_mod_t *si)
+ds_group_all(si_mod_t *si)
 {
 {
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_ALIAS, "alias_getent", &proc, NULL, extract_alias, NULL);
+       if (!_od_running()) return NULL;
+       return _ds_list(si, CATEGORY_GROUP, "getgrent", NULL, _extract_group);
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-ds_host_byname(si_mod_t *si, const char *name, int af, const char *ignored, uint32_t *err)
+ds_grouplist(si_mod_t *si, const char *name, uint32_t ngroups)
 {
 {
-       static int proc = -1;
-       kvbuf_t *request;
-       si_item_t *item;
-       uint32_t want4, want6;
-       int cat;
+       xpc_object_t payload, reply;
+       si_item_t *item = NULL;
 
 
-       if (err != NULL) *err = SI_STATUS_NO_ERROR;
+       if (!_od_running()) return NULL;
+       if (name == NULL) return NULL;
 
 
-       if (name == NULL)
-       {
-               *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
-               return NULL;
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return NULL;
+       
+       xpc_dictionary_set_string(payload, "name", name);
+       xpc_dictionary_set_int64(payload, "ngroups", ngroups);
+       
+       reply = _od_rpc_call("getgrouplist", payload, _od_xpc_pipe);
+       if (reply != NULL) {
+               size_t gidptrsz;
+               const gid_t *gidptr = xpc_dictionary_get_data(reply, "groups", &gidptrsz);
+               int32_t count;
+               uint64_t va, vb;
+               
+               _ds_get_validation(si, &va, &vb, CATEGORY_GROUPLIST);
+
+               /* see what we were sent */
+               count = _extract_uint32(reply, "count");
+               if (count != 0) {
+                       item = (si_item_t *)LI_ils_create("L4488s4@", (unsigned long)si, CATEGORY_GROUPLIST, 1, va, vb, name, count, 
+                                                                                         gidptrsz, gidptr);
+               }
+               
+               xpc_release(reply);
        }
        }
+       
+       xpc_release(payload);
+       
+       return item;
+}
 
 
-       want4 = 0;
-       want6 = 0;
+static si_list_t *
+ds_netgroup_byname(si_mod_t *si, const char *name)
+{
+       xpc_object_t payload;
+       si_list_t *list = NULL;
+       si_item_t *item;
 
 
-       cat = CATEGORY_HOST_IPV4;
+       if (!_od_running()) return NULL;
 
 
-       if (af == AF_INET)
-       {
-               want4 = 1;
-       }
-       else if (af == AF_INET6)
-       {
-               want6 = 1;
-               cat = CATEGORY_HOST_IPV6;
-       }
-       else
-       {
-               *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
-               return NULL;
-       }
+       payload = _xpc_query_key_string("netgroup", name);
+       if (payload == NULL) return NULL;
 
 
-       request = kvbuf_query("kskuku", "name", name, "ipv4", want4, "ipv6", want6);
-       if (request == NULL)
-       {
-               *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
-               return NULL;
+       item = _ds_item(si, CATEGORY_NETGROUP, "getnetgrent", NULL, _extract_netgroup, payload);
+       if (item != NULL) {
+               list = si_list_add(list, item);
+               si_item_release(item);
        }
 
        }
 
-       item = ds_item(si, cat, "gethostbyname", &proc, NULL, extract_host, request);
+       xpc_release(payload);
 
 
-       if ((item == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
-
-       kvbuf_free(request);
-       return item;
+       return list;
 }
 
 }
 
-static si_item_t *
-ds_host_byaddr(si_mod_t *si, const void *addr, int af, const char *ignored, uint32_t *err)
+static int
+ds_in_netgroup(si_mod_t *si, const char *group, const char *host, const char *user, const char *domain)
 {
 {
-       static int proc = -1;
-       kvbuf_t *request;
-       si_item_t *item;
-       struct in_addr addr4;
-       struct in6_addr addr6;
-       char val[64 + 1 + IF_NAMESIZE];
-       int cat;
-       uint32_t want;
-
-       if (err != NULL) *err = SI_STATUS_NO_ERROR;
-
-       cat = CATEGORY_HOST_IPV4;
+       xpc_object_t payload, reply;
+       int is_innetgr;
 
 
-       memset(&addr4, 0, sizeof(struct in_addr));
-       memset(&addr6, 0, sizeof(struct in6_addr));
-       memset(val, 0, sizeof(val));
+       if (!_od_running()) return 0;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return 0;
+       
+       xpc_dictionary_set_string(payload, "netgroup", (group ? group : ""));
+       xpc_dictionary_set_string(payload, "host", (host ? host : ""));
+       xpc_dictionary_set_string(payload, "user", (user ? user : ""));
+       xpc_dictionary_set_string(payload, "domain", (domain ? domain : ""));
+
+       reply = _od_rpc_call("innetgr", payload, _od_xpc_pipe);
+       if (reply != NULL) {
+               is_innetgr = xpc_dictionary_get_bool(reply, OD_RPC_RESULT);
+               xpc_release(reply);
+       } else {
+               is_innetgr = 0;
+       }
 
 
-       want = WANT_A4_ONLY;
+       xpc_release(payload);
 
 
-       if (af == AF_INET)
-       {
-               memcpy(&addr4.s_addr, addr, IPV4_ADDR_LEN);
-               if (inet_ntop(af, &addr4, val, sizeof(val)) == NULL)
-               {
-                       *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
-                       return NULL;
-               }
-       }
-       else if (af == AF_INET6)
-       {
-               want = WANT_A6_ONLY;
-               cat = CATEGORY_HOST_IPV6;
-               memcpy(&addr6, addr, IPV6_ADDR_LEN);
-               if (inet_ntop(af, &addr6, val, sizeof(val)) == NULL)
-               {
-                       *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
-                       return NULL;
-               }
-       }
-       else
-       {
-               *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
-               return NULL;
-       }
+       return is_innetgr;
+}
 
 
-       request = kvbuf_query("ksku", "address", val, "family", af);
-       if (request == NULL)
-       {
-               *err = SI_STATUS_H_ERRNO_NO_RECOVERY;
-               return NULL;
-       }
+static si_item_t *
+ds_alias_byname(si_mod_t *si, const char *name)
+{
+       xpc_object_t payload;
+       si_item_t *item;
 
 
-       item = ds_item(si, cat, "gethostbyaddr", &proc, &want, extract_host, request);
+       if (!_od_running()) return NULL;
+       
+       payload = _xpc_query_key_string("name", name);
+       if (payload == NULL) return NULL;
 
 
-       if ((item == NULL) && (err != NULL)) *err = SI_STATUS_H_ERRNO_HOST_NOT_FOUND;
+       item = _ds_item(si, CATEGORY_ALIAS, "alias_getbyname", NULL, _extract_alias, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
        return item;
 }
 
 static si_list_t *
        return item;
 }
 
 static si_list_t *
-ds_host_all(si_mod_t *si)
+ds_alias_all(si_mod_t *si)
 {
 {
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_HOST_IPV4, "gethostent", &proc, NULL, extract_host, NULL);
+       if (!_od_running()) return NULL;
+       return _ds_list(si, CATEGORY_ALIAS, "alias_getent", NULL, _extract_alias);
 }
 
 static si_item_t *
 ds_network_byname(si_mod_t *si, const char *name)
 {
 }
 
 static si_item_t *
 ds_network_byname(si_mod_t *si, const char *name)
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       request = kvbuf_query_key_val("name", name);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
+       
+       payload = _xpc_query_key_string("name", name);
+       if (payload == NULL) return NULL;
 
 
-       item = ds_item(si, CATEGORY_NETWORK, "getnetbyname", &proc, NULL, extract_network, request);
+       item = _ds_item(si, CATEGORY_NETWORK, "getnetbyname", NULL, _extract_network, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
        return item;
 }
 
 static si_item_t *
 ds_network_byaddr(si_mod_t *si, uint32_t addr)
 {
        return item;
 }
 
 static si_item_t *
 ds_network_byaddr(si_mod_t *si, uint32_t addr)
 {
-       static int proc = -1;
        unsigned char f1, f2, f3;
        char val[64];
        unsigned char f1, f2, f3;
        char val[64];
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
+       if (!_od_running()) return NULL;
+       
        f1 = addr & 0xff;
        addr >>= 8;
        f2 = addr & 0xff;
        f1 = addr & 0xff;
        addr >>= 8;
        f2 = addr & 0xff;
@@ -1744,31 +1118,30 @@ ds_network_byaddr(si_mod_t *si, uint32_t addr)
        else if (f2 != 0) snprintf(val, sizeof(val), "%u.%u", f2, f1);
        else snprintf(val, sizeof(val), "%u", f1);
 
        else if (f2 != 0) snprintf(val, sizeof(val), "%u.%u", f2, f1);
        else snprintf(val, sizeof(val), "%u", f1);
 
-       request = kvbuf_query_key_val("net", val);
-       if (request == NULL) return NULL;
+       payload = _xpc_query_key_string("net", val);
+       if (payload == NULL) return NULL;
 
 
-       item = ds_item(si, CATEGORY_NETWORK, "getnetbyaddr", &proc, NULL, extract_network, request);
+       item = _ds_item(si, CATEGORY_NETWORK, "getnetbyaddr", NULL, _extract_network, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
        return item;
 }
 
 static si_list_t *
 ds_network_all(si_mod_t *si)
 {
        return item;
 }
 
 static si_list_t *
 ds_network_all(si_mod_t *si)
 {
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_NETWORK, "getnetent", &proc, NULL, extract_network, NULL);
+       if (!_od_running()) return NULL;
+       return _ds_list(si, CATEGORY_NETWORK, "getnetent", NULL, _extract_network);
 }
 
 static si_item_t *
 ds_service_byname(si_mod_t *si, const char *name, const char *proto)
 {
 }
 
 static si_item_t *
 ds_service_byname(si_mod_t *si, const char *name, const char *proto)
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
        struct servent *s;
 
        si_item_t *item;
        struct servent *s;
 
+       if (!_od_running()) return NULL;
        if (name == NULL) name = "";
        if (proto == NULL) proto = "";
 
        if (name == NULL) name = "";
        if (proto == NULL) proto = "";
 
@@ -1780,152 +1153,149 @@ ds_service_byname(si_mod_t *si, const char *name, const char *proto)
                if (string_equal(name, s->s_name)) return si_item_retain(item);
        }
 
                if (string_equal(name, s->s_name)) return si_item_retain(item);
        }
 
-       request = kvbuf_query("ksks", "name", name, "proto", proto);
-       if (request == NULL) return NULL;
-
-       item = ds_item(si, CATEGORY_SERVICE, "getservbyname", &proc, NULL, extract_service, request);
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return NULL;
+       
+       xpc_dictionary_set_string(payload, "name", name);
+       xpc_dictionary_set_string(payload, "proto", proto);
+       
+       item = _ds_item(si, CATEGORY_SERVICE, "getservbyname", NULL, _extract_service, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
+       
        return item;
 }
 
 static si_item_t *
 ds_service_byport(si_mod_t *si, int port, const char *proto)
 {
        return item;
 }
 
 static si_item_t *
 ds_service_byport(si_mod_t *si, int port, const char *proto)
 {
-       static int proc = -1;
-       uint16_t sport;
-       char val[16];
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       if (proto == NULL) proto = "";
-
-       sport = port;
-       snprintf(val, sizeof(val), "%d", ntohs(sport));
+       if (!_od_running()) return NULL;
 
 
-       request = kvbuf_query("ksks", "port", val, "proto", proto);
-       if (request == NULL) return NULL;
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return NULL;
+       
+       /* swap to native order, API passes network order */
+       xpc_dictionary_set_int64(payload, "port", ntohs(port));
+       xpc_dictionary_set_string(payload, "proto", (proto ? proto : ""));
 
 
-       item = ds_item(si, CATEGORY_SERVICE, "getservbyport", &proc, NULL, extract_service, request);
+       item = _ds_item(si, CATEGORY_SERVICE, "getservbyport", NULL, _extract_service, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
+       
        return item;
 }
 
 static si_list_t *
 ds_service_all(si_mod_t *si)
 {
        return item;
 }
 
 static si_list_t *
 ds_service_all(si_mod_t *si)
 {
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_SERVICE, "getservent", &proc, NULL, extract_service, NULL);
+       if (!_od_running()) return NULL;
+       return _ds_list(si, CATEGORY_SERVICE, "getservent", NULL, _extract_service);
 }
 
 static si_item_t *
 ds_protocol_byname(si_mod_t *si, const char *name)
 {
 }
 
 static si_item_t *
 ds_protocol_byname(si_mod_t *si, const char *name)
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       request = kvbuf_query_key_val("name", name);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
 
 
-       item = ds_item(si, CATEGORY_PROTOCOL, "getprotobyname", &proc, NULL, extract_protocol, request);
+       payload = _xpc_query_key_string("name", name);
+       if (payload == NULL) return NULL;
 
 
-       kvbuf_free(request);
+       item = _ds_item(si, CATEGORY_PROTOCOL, "getprotobyname", NULL, _extract_protocol, payload);
+
+       xpc_release(payload);
        return item;
 }
 
 static si_item_t *
 ds_protocol_bynumber(si_mod_t *si, int number)
 {
        return item;
 }
 
 static si_item_t *
 ds_protocol_bynumber(si_mod_t *si, int number)
 {
-       static int proc = -1;
-       char val[16];
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       snprintf(val, sizeof(val), "%d", number);
-       request = kvbuf_query_key_val("number", val);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
+
+       payload = _xpc_query_key_int("number", number);
+       if (payload == NULL) return NULL;
 
 
-       item = ds_item(si, CATEGORY_PROTOCOL, "getprotobynumber", &proc, NULL, extract_protocol, request);
+       item = _ds_item(si, CATEGORY_PROTOCOL, "getprotobynumber", NULL, _extract_protocol, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
        return item;
 }
 
 static si_list_t *
 ds_protocol_all(si_mod_t *si)
 {
        return item;
 }
 
 static si_list_t *
 ds_protocol_all(si_mod_t *si)
 {
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_PROTOCOL, "getprotoent", &proc, NULL, extract_protocol, NULL);
+       return _ds_list(si, CATEGORY_PROTOCOL, "getprotoent", NULL, _extract_protocol);
 }
 
 static si_item_t *
 ds_rpc_byname(si_mod_t *si, const char *name)
 {
 }
 
 static si_item_t *
 ds_rpc_byname(si_mod_t *si, const char *name)
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       request = kvbuf_query_key_val("name", name);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
+
+       payload = _xpc_query_key_string("name", name);
+       if (payload == NULL) return NULL;
 
 
-       item = ds_item(si, CATEGORY_RPC, "getrpcbyname", &proc, NULL, extract_rpc, request);
+       item = _ds_item(si, CATEGORY_RPC, "getrpcbyname", NULL, _extract_rpc, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
        return item;
 }
 
 static si_item_t *
 ds_rpc_bynumber(si_mod_t *si, int number)
 {
        return item;
 }
 
 static si_item_t *
 ds_rpc_bynumber(si_mod_t *si, int number)
 {
-       static int proc = -1;
-       char val[16];
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       snprintf(val, sizeof(val), "%u", (uint32_t)number);
-       request = kvbuf_query_key_val("number", val);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
 
 
-       item = ds_item(si, CATEGORY_RPC, "getrpcbynumber", &proc, NULL, extract_rpc, request);
+       payload = _xpc_query_key_int("number", number);
+       if (payload == NULL) return NULL;
 
 
-       kvbuf_free(request);
+       item = _ds_item(si, CATEGORY_RPC, "getrpcbynumber", NULL, _extract_rpc, payload);
+
+       xpc_release(payload);
        return item;
 }
 
 static si_list_t *
 ds_rpc_all(si_mod_t *si)
 {
        return item;
 }
 
 static si_list_t *
 ds_rpc_all(si_mod_t *si)
 {
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_RPC, "getrpcent", &proc, NULL, extract_rpc, NULL);
+       return _ds_list(si, CATEGORY_RPC, "getrpcent", NULL, _extract_rpc);
 }
 
 static si_item_t *
 ds_fs_byspec(si_mod_t *si, const char *name)
 {
 }
 
 static si_item_t *
 ds_fs_byspec(si_mod_t *si, const char *name)
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       request = kvbuf_query_key_val("name", name);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
+       
+       payload = _xpc_query_key_string("name", name);
+       if (payload == NULL) return NULL;
 
 
-       item = ds_item(si, CATEGORY_FS, "getfsbyname", &proc, NULL, extract_fstab, request);
+       item = _ds_item(si, CATEGORY_FS, "getfsbyname", NULL, _extract_fstab, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
        return item;
 }
 
 static si_list_t *
 ds_fs_all(si_mod_t *si)
 {
        return item;
 }
 
 static si_list_t *
 ds_fs_all(si_mod_t *si)
 {
-       static int proc = -1;
-
-       return ds_list(si, CATEGORY_FS, "getfsent", &proc, NULL, extract_fstab, NULL);
+       return _ds_list(si, CATEGORY_FS, "getfsent", NULL, _extract_fstab);
 }
 
 static si_item_t *
 }
 
 static si_item_t *
@@ -1936,6 +1306,7 @@ ds_fs_byfile(si_mod_t *si, const char *name)
        uint32_t i;
        struct fstab *f;
 
        uint32_t i;
        struct fstab *f;
 
+       if (!_od_running()) return NULL;
        if (name == NULL) return NULL;
 
        list = ds_fs_all(si);
        if (name == NULL) return NULL;
 
        list = ds_fs_all(si);
@@ -1955,364 +1326,61 @@ ds_fs_byfile(si_mod_t *si, const char *name)
 static si_item_t *
 ds_mac_byname(si_mod_t *si, const char *name)
 {
 static si_item_t *
 ds_mac_byname(si_mod_t *si, const char *name)
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
        si_item_t *item;
 
-       request = kvbuf_query_key_val("name", name);
-       if (request == NULL) return NULL;
+       if (!_od_running()) return NULL;
+       
+       payload = _xpc_query_key_string("name", name);
+       if (payload == NULL) return NULL;
 
 
-       item = ds_item(si, CATEGORY_MAC, "getmacbyname", &proc, (void *)name, extract_mac_mac, request);
+       item = _ds_item(si, CATEGORY_MAC, "getmacbyname", name, _extract_mac_mac, payload);
 
 
-       kvbuf_free(request);
+       xpc_release(payload);
        return item;
 }
 
 static si_item_t *
 ds_mac_bymac(si_mod_t *si, const char *mac)
 {
        return item;
 }
 
 static si_item_t *
 ds_mac_bymac(si_mod_t *si, const char *mac)
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
        char *cmac;
        si_item_t *item;
        char *cmac;
+       
+       if (!_od_running()) return NULL;
 
        cmac = si_standardize_mac_address(mac);
        if (cmac == NULL) return NULL;
 
 
        cmac = si_standardize_mac_address(mac);
        if (cmac == NULL) return NULL;
 
-       request = kvbuf_query_key_val("mac", cmac);
-       if (request == NULL) return NULL;
-
-       item = ds_item(si, CATEGORY_MAC, "gethostbymac", &proc, cmac, extract_mac_name, request);
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return NULL;
+       
+       payload = _xpc_query_key_string("mac", cmac);
+       item = _ds_item(si, CATEGORY_MAC, "gethostbymac", cmac, _extract_mac_name, payload);
 
        free(cmac);
 
        free(cmac);
-       kvbuf_free(request);
+       xpc_release(payload);
+       
        return item;
 }
 
        return item;
 }
 
-static si_list_t *
-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)
-{
-       static int proc = -1;
-       si_list_t *list, *out;
-       si_item_t *item;
-       kvbuf_t *request = NULL;
-       kvdict_t *dict;
-       kvarray_t *reply = NULL;
-       kern_return_t status = 0;
-       uint16_t scope = 0;
-       int i, k, kcount, d;
-       uint32_t port;
-
-       struct hostent *h;
-       char *h_name = NULL;
-       int h_aliases_cnt = 0;
-       const char **h_aliases = NULL;
-       struct in_addr *a4 = NULL;
-       struct in6_addr *a6 = NULL;
-       int a4_cnt = 0;
-       int a6_cnt = 0;
-       struct servent *s;
-       const char *s_name = NULL;
-       int s_aliases_cnt = 0;
-       const char **s_aliases = NULL;
-       uint16_t s_port = 0;
-       const char *s_proto = NULL;
-       const char *protoname;
-       int wantv4, wantv6;
-
-       int numericserv = ((flags & AI_NUMERICSERV) != 0);
-       int numerichost = ((flags & AI_NUMERICHOST) != 0);
-
-       wantv4 = 0;
-       wantv6 = 0;
-
-       if (node != NULL)
-       {
-               wantv4 = ((family != AF_INET6) || (flags & AI_V4MAPPED));
-               wantv6 = (family != AF_INET);
-       }
-
-       if (err != NULL) *err = SI_STATUS_NO_ERROR;
-
-       if (proc < 0)
-       {
-               status = LI_DSLookupGetProcedureNumber("gethostbyname_service", &proc);
-               if (status != KERN_SUCCESS)
-               {
-                       if (err != NULL) *err = SI_STATUS_EAI_SYSTEM;
-                       return NULL;
-               }
-       }
-
-       /* look up canonical name of numeric host */
-       if ((numerichost == 1) && (flags & AI_CANONNAME) && (node != NULL))
-       {
-               item = si_host_byaddr(si, node, family, NULL, NULL);
-               if (item != NULL)
-               {
-                       h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t));
-                       h_name = strdup(h->h_name);
-                       si_item_release(item);
-               }
-       }
-
-       if (numericserv == 1)
-       {
-               s_port = *(int16_t *)serv;
-       }
-
-       if ((numericserv == 0) || (numerichost == 0))
-       {
-               request = kvbuf_new();
-               if (request != NULL)
-               {
-                       kvbuf_add_dict(request);
-
-                       if (numerichost == 0)
-                       {
-                               kvbuf_add_key(request, "name");
-                               kvbuf_add_val(request, node);
-                               kvbuf_add_key(request, "ipv4");
-                               kvbuf_add_val(request, wantv4 ? "1" : "0");
-                               kvbuf_add_key(request, "ipv6");
-                               kvbuf_add_val(request, wantv6 ? "1" : "0");
-                       }
-
-                       if (numericserv == 0)
-                       {
-                               protoname = NULL;   
-                               if (proto == IPPROTO_UDP) protoname = "udp";
-                               if (proto == IPPROTO_TCP) protoname = "tcp";
-
-                               kvbuf_add_key(request, "s_name");
-                               kvbuf_add_val(request, serv);
-                               if (protoname != NULL)
-                               {
-                                       kvbuf_add_key(request, "s_proto");
-                                       kvbuf_add_val(request, protoname);
-                               }
-                       }
-
-                       status = LI_DSLookupQuery(proc, request, &reply);
-                       kvbuf_free(request);
-               }
-               else
-               {
-                       if (err != NULL) *err = SI_STATUS_EAI_SYSTEM;
-               }
-       }
-
-       if ((status != KERN_SUCCESS) || (reply == NULL))
-       {
-               free(h_name);
-               return NULL;
-       }
-
-       for (d = 0; d < reply->count; d++)
-       {
-               dict = reply->dict + d;
-               kcount = dict->kcount;
-
-               for (k = 0; k < kcount; k++)
-               {
-                       if (string_equal(dict->key[k], "h_name"))
-                       {
-                               if (dict->vcount[k] == 0) continue;
-                               h_name = strdup(dict->val[k][0]);
-                       }
-                       else if (string_equal(dict->key[k], "h_aliases"))
-                       {
-                               h_aliases_cnt = dict->vcount[k];
-                               h_aliases = (const char **)calloc(h_aliases_cnt, sizeof(char *));
-                               if (h_aliases == NULL) h_aliases_cnt = 0;
-
-                               for (i = 0; i < h_aliases_cnt; ++i)
-                               {
-                                       h_aliases[i] = dict->val[k][i];
-                               }
-                       }
-                       else if (wantv4 && (string_equal(dict->key[k], "h_ipv4_addr_list")))
-                       {
-                               a4_cnt = dict->vcount[k];
-                               a4 = calloc(a4_cnt, sizeof(struct in_addr));
-                               if (a4 == NULL) a4_cnt = 0;
-
-                               for (i = 0; i < a4_cnt; ++i)
-                               {
-                                       memset(&a4[i], 0, sizeof(struct in_addr));
-                                       inet_pton(AF_INET, dict->val[k][i], &a4[i]);
-                               }
-                       }
-                       else if (wantv6 && (string_equal(dict->key[k], "h_ipv6_addr_list")))
-                       {
-                               a6_cnt = dict->vcount[k];
-                               a6 = calloc(a6_cnt, sizeof(struct in6_addr));
-                               if (a6 == NULL) a6_cnt = 0;
-
-                               for (i = 0; i < a6_cnt; ++i)
-                               {
-                                       memset(&a6[i], 0, sizeof(struct in6_addr));
-                                       inet_pton(AF_INET6, dict->val[k][i], &a6[i]);
-                               }
-                       }
-                       else if (string_equal(dict->key[k], "s_name"))
-                       {
-                               if (dict->vcount[k] == 0) continue;
-                               s_name = dict->val[k][0];
-                       }
-                       else if (string_equal(dict->key[k], "s_port"))
-                       {
-                               if (dict->vcount[k] == 0) continue;
-                               s_port = atoi(dict->val[k][0]);
-                       }
-                       else if (string_equal(dict->key[k], "s_aliases"))
-                       {
-                               s_aliases_cnt = dict->vcount[k];
-                               s_aliases = (const char **)calloc(s_aliases_cnt+1, sizeof(char *));
-                               if (s_aliases == NULL) s_aliases_cnt = 0;
-
-                               for (i = 0; i < s_aliases_cnt; ++i)
-                               {
-                                       s_aliases[i] = dict->val[k][i];
-                               }
-                       }
-                       else if (string_equal(dict->key[k], "s_proto"))
-                       {
-                               if (dict->vcount[k] == 0) continue;
-                               s_proto = dict->val[k][0];
-                       }
-               }
-       }
-
-       kvarray_free(reply);
-
-       /* check if we actually got back what we wanted */
-       if (((wantv4 || wantv6) && (a4_cnt == 0) && (a6_cnt == 0)) || ((serv != NULL) && (s_port == 0)))
-       {
-               if (err != NULL) *err = SI_STATUS_EAI_NONAME;
-
-               free(h_name);
-               free(h_aliases);
-               free(s_aliases);
-               free(a4);
-               free(a6);
-
-               return NULL;
-       }
-
-       /*
-        * Cache the service entry regardless of whether there is a host match.
-        * This allows later modules to get the service entry quickly.
-        * This should really be part of the general cache mechanism, but that's
-        * not currently visible outside of the search module.
-        */
-       if ((s_name != NULL) && (s_port != 0))
-       {
-               port = htons(s_port);
-
-               item = pthread_getspecific(_ds_serv_cache_key);
-               if (item != NULL)
-               {
-                       s = (struct servent *)((uintptr_t)item + sizeof(si_item_t));
-                       if ((port != s->s_port) || string_not_equal(s_name, s->s_name))
-                       {
-                               si_item_release(item);
-                               item = NULL;
-                       }
-               }
-
-               if (item == NULL)
-               {
-                       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);
-                       pthread_setspecific(_ds_serv_cache_key, item);
-               }
-       }
-
-       /* Construct the addrinfo list from the returned addresses (if found). */
-       out = NULL;
-       for (i = 0; i < a6_cnt; i++)
-       {
-               list = si_addrinfo_list(si, flags, socktype, proto, NULL, &a6[i], s_port, scope, NULL, h_name);
-               out = si_list_concat(out, list);
-               si_list_release(list);
-       }
-
-       for (i = 0; i < a4_cnt; i++)
-       {
-               list = si_addrinfo_list(si, flags, socktype, proto, &a4[i], NULL, s_port, 0, h_name, NULL);
-               out = si_list_concat(out, list);
-               si_list_release(list);
-       }
-
-       free(h_name);
-       free(h_aliases);
-       free(s_aliases);
-       free(a4);
-       free(a6);
-
-       return out;
-}
-
-static int
-ds_is_valid(si_mod_t *si, si_item_t *item)
-{
-       si_mod_t *src;
-       ds_si_private_t *pp;
-       int status;
-       uint32_t oldval, newval;
-
-       if (si == NULL) return 0;
-       if (item == NULL) return 0;
-       if (si->name == NULL) return 0;
-       if (item->src == NULL) return 0;
-
-       pp = (ds_si_private_t *)si->private;
-       if (pp == NULL) return 0;
-
-       src = (si_mod_t *)item->src;
-
-       if (src->name == NULL) return 0;
-       if (string_not_equal(si->name, src->name)) return 0;
-
-       /* check global invalidation */
-       oldval = item->validation_a;
-       newval = -1;
-       status = notify_peek(pp->notify_token_global, &newval);
-       if (status != NOTIFY_STATUS_OK) return 0;
-
-       newval = ntohl(newval);
-       if (oldval != newval) return 0;
-
-       oldval = item->validation_b;
-       newval = -1;
-       if (item->type == CATEGORY_USER) status = notify_peek(pp->notify_token_user, &newval);
-       else if (item->type == CATEGORY_GROUP) status = notify_peek(pp->notify_token_group, &newval);
-       else if (item->type == CATEGORY_HOST_IPV4) status = notify_peek(pp->notify_token_host, &newval);
-       else if (item->type == CATEGORY_HOST_IPV6) status = notify_peek(pp->notify_token_host, &newval);
-       else if (item->type == CATEGORY_SERVICE) status = notify_peek(pp->notify_token_service, &newval);
-       else return 0;
-
-       if (status != NOTIFY_STATUS_OK) return 0;
-
-       newval = ntohl(newval);
-       if (oldval != newval) return 0;
-
-       return 1;
-}
+#pragma mark -
 
 si_mod_t *
 si_module_static_ds(void)
 {
        static const struct si_mod_vtable_s ds_vtable =
        {
 
 si_mod_t *
 si_module_static_ds(void)
 {
        static const struct si_mod_vtable_s ds_vtable =
        {
-               .sim_is_valid = &ds_is_valid,
+               .sim_is_valid = &_ds_is_valid,
 
                .sim_user_byname = &ds_user_byname,
                .sim_user_byuid = &ds_user_byuid,
 
                .sim_user_byname = &ds_user_byname,
                .sim_user_byuid = &ds_user_byuid,
+               .sim_user_byuuid = &ds_user_byuuid,
                .sim_user_all = &ds_user_all,
 
                .sim_group_byname = &ds_group_byname,
                .sim_group_bygid = &ds_group_bygid,
                .sim_user_all = &ds_user_all,
 
                .sim_group_byname = &ds_group_byname,
                .sim_group_bygid = &ds_group_bygid,
+               .sim_group_byuuid = &ds_group_byuuid,
                .sim_group_all = &ds_group_all,
 
                .sim_grouplist = &ds_grouplist,
                .sim_group_all = &ds_group_all,
 
                .sim_grouplist = &ds_grouplist,
@@ -2323,9 +1391,10 @@ si_module_static_ds(void)
                .sim_alias_byname = &ds_alias_byname,
                .sim_alias_all = &ds_alias_all,
 
                .sim_alias_byname = &ds_alias_byname,
                .sim_alias_all = &ds_alias_all,
 
-               .sim_host_byname = &ds_host_byname,
-               .sim_host_byaddr = &ds_host_byaddr,
-               .sim_host_all = &ds_host_all,
+               /* host lookups not supported */
+               .sim_host_byname = NULL,
+               .sim_host_byaddr = NULL,
+               .sim_host_all = NULL,
 
                .sim_network_byname = &ds_network_byname,
                .sim_network_byaddr = &ds_network_byaddr,
 
                .sim_network_byname = &ds_network_byname,
                .sim_network_byaddr = &ds_network_byaddr,
@@ -2380,7 +1449,6 @@ si_module_static_ds(void)
                        pp->notify_token_global = -1;
                        pp->notify_token_user = -1;
                        pp->notify_token_group = -1;
                        pp->notify_token_global = -1;
                        pp->notify_token_user = -1;
                        pp->notify_token_group = -1;
-                       pp->notify_token_host = -1;
                        pp->notify_token_service = -1;
                }
 
                        pp->notify_token_service = -1;
                }
 
@@ -2398,7 +1466,6 @@ si_module_static_ds(void)
                        notify_register_check(kNotifyDSCacheInvalidation, &(pp->notify_token_global));
                        notify_register_check(kNotifyDSCacheInvalidationUser, &(pp->notify_token_user));
                        notify_register_check(kNotifyDSCacheInvalidationGroup, &(pp->notify_token_group));
                        notify_register_check(kNotifyDSCacheInvalidation, &(pp->notify_token_global));
                        notify_register_check(kNotifyDSCacheInvalidationUser, &(pp->notify_token_user));
                        notify_register_check(kNotifyDSCacheInvalidationGroup, &(pp->notify_token_group));
-                       notify_register_check(kNotifyDSCacheInvalidationHost, &(pp->notify_token_host));
                        notify_register_check(kNotifyDSCacheInvalidationService, &(pp->notify_token_service));
                }
 
                        notify_register_check(kNotifyDSCacheInvalidationService, &(pp->notify_token_service));
                }
 
index 7db0b896bac9ebbb03a6bc0ce933e16dee9c1b24..bf332f85406cbeae407ab8b0eed25e7ca311e6e9 100644 (file)
@@ -30,6 +30,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <notify.h>
 #include <dirent.h>
 #include <errno.h>
 #include <notify.h>
+#include <pthread.h>
 #include <arpa/inet.h>
 #include <sys/param.h>
 #include <sys/mount.h>
 #include <arpa/inet.h>
 #include <sys/param.h>
 #include <sys/mount.h>
@@ -132,21 +133,18 @@ _fsi_append_string(char *s, char **l)
        int i, len;
 
        if (s == NULL) return l;
        int i, len;
 
        if (s == NULL) return l;
-       if (l == NULL) 
-       {
-               l = (char **)malloc(2 * sizeof(char *));
-               l[0] = s;
-               l[1] = NULL;
-               return l;
+       if (l != NULL) {
+               for (i = 0; l[i] != NULL; i++);
+               len = i;
+       } else {
+               len = 0;
        }
 
        }
 
-       for (i = 0; l[i] != NULL; i++);
-       len = i + 1; /* count the NULL on the end of the list too! */
-
-       l = (char **)reallocf(l, (len + 1) * sizeof(char *));
+       l = (char **) reallocf(l, (len + 2) * sizeof(char *));
+       if (l == NULL) return NULL;
 
 
-       l[len - 1] = s;
-       l[len] = NULL;
+       l[len] = s;
+       l[len + 1] = NULL;
        return l;
 }
 
        return l;
 }
 
@@ -276,7 +274,7 @@ _fsi_get_validation(si_mod_t *si, int vtype, const char *path, FILE *f, uint64_t
        int status;
 
        if (a != NULL) *a = 0;
        int status;
 
        if (a != NULL) *a = 0;
-       if (b != NULL) *a = 0;
+       if (b != NULL) *b = 0;
 
        if (si == NULL) return;
        if (path == NULL) return;
 
        if (si == NULL) return;
        if (path == NULL) return;
@@ -984,8 +982,8 @@ _fsi_get_grouplist(si_mod_t *si, const char *user)
        si_item_t *item;
        FILE *f;
        uint64_t va, vb;
        si_item_t *item;
        FILE *f;
        uint64_t va, vb;
-       int32_t gid, basegid, *gidp;
-       char **gidlist;
+       gid_t gid, basegid;
+       gid_t *gidlist;
        struct passwd *pw;
 
        if (user == NULL) return NULL;
        struct passwd *pw;
 
        if (user == NULL) return NULL;
@@ -1000,7 +998,8 @@ _fsi_get_grouplist(si_mod_t *si, const char *user)
        {
                pw = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
                basegid = pw->pw_gid;
        {
                pw = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
                basegid = pw->pw_gid;
-               free(item);
+               si_item_release(item);
+               item = NULL;
        }
 
        f = fopen(_PATH_GROUP, "r");
        }
 
        f = fopen(_PATH_GROUP, "r");
@@ -1034,12 +1033,13 @@ _fsi_get_grouplist(si_mod_t *si, const char *user)
                match = 0;
                gid = -2;
 
                match = 0;
                gid = -2;
 
-               for (i = 0; (i < ntokens) && (match == 0); i++)
+               for (i = 0; i < ntokens; i++)
                {
                        if (string_equal(user, members[i]))
                        {
                                gid = atoi(tokens[2]);
                                match = 1;
                {
                        if (string_equal(user, members[i]))
                        {
                                gid = atoi(tokens[2]);
                                match = 1;
+                               break;
                        }
                }
 
                        }
                }
 
@@ -1050,40 +1050,24 @@ _fsi_get_grouplist(si_mod_t *si, const char *user)
 
                if (match == 1)
                {
 
                if (match == 1)
                {
-                       if (gidcount == 0) gidlist = (char **)calloc(1, sizeof(char *));
-                       else gidlist = (char **)reallocf(gidlist, (gidcount + 1) * sizeof(char *));
-                       gidp = (int32_t *)calloc(1, sizeof(int32_t));
-
+                       gidlist = (gid_t *) reallocf(gidlist, (gidcount + 1) * sizeof(gid_t));
                        if (gidlist == NULL)
                        {
                                gidcount = 0;
                                break;
                        }
 
                        if (gidlist == NULL)
                        {
                                gidcount = 0;
                                break;
                        }
 
-                       if (gidp == NULL)
-                       {
-                               for (i = 0; i < gidcount; i++) free(gidlist[i]);
-                               free(gidlist);
-                               gidcount = 0;
-                               break;
-                       }
-
-                       *gidp = gid;
-                       gidlist[gidcount++] = (char *)gidp;
+                       gidlist[gidcount++] = gid;
                }
        }
 
        fclose(f);
 
                }
        }
 
        fclose(f);
 
-       if (gidcount == 0) return NULL;
-
-       gidlist = (char **)reallocf(gidlist, (gidcount + 1) * sizeof(int32_t *));
-       if (gidlist == NULL) return NULL;
-       gidlist[gidcount] = NULL;
-
-       item = (si_item_t *)LI_ils_create("L4488s44a", (unsigned long)si, CATEGORY_GROUPLIST, 1, va, vb, user, basegid, gidcount, gidlist);
+       if (gidcount != 0) {
+               item = (si_item_t *)LI_ils_create("L4488s4@", (unsigned long)si, CATEGORY_GROUPLIST, 1, va, vb, user, gidcount, 
+                                                                                 gidcount * sizeof(gid_t), gidlist);
+       }
 
 
-       for (i = 0; i <= gidcount; i++) free(gidlist[i]);
        free(gidlist);
 
        return item;
        free(gidlist);
 
        return item;
@@ -2030,7 +2014,7 @@ file_group_all(si_mod_t *si)
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-file_grouplist(si_mod_t *si, const char *name)
+file_grouplist(si_mod_t *si, const char *name, __unused uint32_t ignored)
 {
        return _fsi_get_grouplist(si, name);
 }
 {
        return _fsi_get_grouplist(si, name);
 }
@@ -2040,7 +2024,7 @@ file_netgroup_byname(si_mod_t *si, const char *name)
 {
        si_list_t *list = NULL;
        si_item_t *item;
 {
        si_list_t *list = NULL;
        si_item_t *item;
-       uint64_t va, vb;
+       uint64_t va=0, vb=0;
        file_netgroup_t *n;
        file_si_private_t *pp;
 
        file_netgroup_t *n;
        file_si_private_t *pp;
 
@@ -2296,10 +2280,12 @@ si_module_static_file(void)
 
                .sim_user_byname = &file_user_byname,
                .sim_user_byuid = &file_user_byuid,
 
                .sim_user_byname = &file_user_byname,
                .sim_user_byuid = &file_user_byuid,
+               .sim_user_byuuid = NULL,
                .sim_user_all = &file_user_all,
 
                .sim_group_byname = &file_group_byname,
                .sim_group_bygid = &file_group_bygid,
                .sim_user_all = &file_user_all,
 
                .sim_group_byname = &file_group_byname,
                .sim_group_bygid = &file_group_bygid,
+               .sim_group_byuuid = NULL,
                .sim_group_all = &file_group_all,
 
                .sim_grouplist = &file_grouplist,
                .sim_group_all = &file_group_all,
 
                .sim_grouplist = &file_grouplist,
index 2a2920c7f90b6963fb656324ccd9fe5ea78733c1..adad337cd965522b023e60a77a0ae8a143b4d3aa 100644 (file)
@@ -28,7 +28,7 @@
 .\"     From: @(#)getgrent.3   8.2 (Berkeley) 4/19/94
 .\" $FreeBSD: src/lib/libc/gen/getgrent.3,v 1.28 2007/01/09 00:27:53 imp Exp $
 .\"
 .\"     From: @(#)getgrent.3   8.2 (Berkeley) 4/19/94
 .\" $FreeBSD: src/lib/libc/gen/getgrent.3,v 1.28 2007/01/09 00:27:53 imp Exp $
 .\"
-.Dd April 16, 2003
+.Dd October 26, 2011
 .Dt GETGRENT 3
 .Os
 .Sh NAME
 .Dt GETGRENT 3
 .Os
 .Sh NAME
@@ -38,6 +38,8 @@
 .Nm getgrnam_r ,
 .Nm getgrgid ,
 .Nm getgrgid_r ,
 .Nm getgrnam_r ,
 .Nm getgrgid ,
 .Nm getgrgid_r ,
+.Nm getgruuid ,
+.Nm getgruuid_r ,
 .Nm setgroupent ,
 .Nm setgrent ,
 .Nm endgrent
 .Nm setgroupent ,
 .Nm setgrent ,
 .Nm endgrent
@@ -46,6 +48,7 @@
 .Lb libc
 .Sh SYNOPSIS
 .In grp.h
 .Lb libc
 .Sh SYNOPSIS
 .In grp.h
+.In uuid/uuid.h
 .Ft struct group *
 .Fn getgrent void
 .\".Ft int
 .Ft struct group *
 .Fn getgrent void
 .\".Ft int
 .Ft int
 .Fn getgrgid_r "gid_t gid" "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result"
 .Ft int
 .Ft int
 .Fn getgrgid_r "gid_t gid" "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result"
 .Ft int
+.Fn getgruuid "uuid_t uuid"
+.Ft int
+.Fn getgruuid_r "uuid_t uuid" "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result"
+.Ft int
 .Fn setgroupent "int stayopen"
 .Ft void
 .Fn setgrent void
 .Fn setgroupent "int stayopen"
 .Ft void
 .Fn setgrent void
@@ -67,7 +74,7 @@
 .Sh DESCRIPTION
 .\"These functions operate on the group database file
 These functions obtain information from
 .Sh DESCRIPTION
 .\"These functions operate on the group database file
 These functions obtain information from
-.Xr DirectoryService 8 ,
+.Xr opendirectoryd 8 ,
 including records in
 .Pa /etc/group
 which is described
 including records in
 .Pa /etc/group
 which is described
@@ -88,21 +95,35 @@ struct group {
 .Ed
 .Pp
 The functions
 .Ed
 .Pp
 The functions
-.Fn getgrnam
+.Fn getgrnam ,
+.Fn getgrgid ,
 and
 and
-.Fn getgrgid
+.Fn getgruuid
 search the group database for the given group name pointed to by
 search the group database for the given group name pointed to by
-.Fa name
-or the group id pointed to by
+.Fa name ,
+the group id given by
 .Fa gid ,
 .Fa gid ,
+or the UUID given by
+.Fa uuid 
 respectively, returning the first one encountered.
 Identical group
 respectively, returning the first one encountered.
 Identical group
-names or group gids may result in undefined behavior.
+names, group gids, or uuids may result in undefined behavior.
+.Pp
+Note that the groups file
+.Pa /etc/group
+does not contain group UUIDs.
+The UUID for a group may be found using
+.Fn mbr_gid_to_uuid .
 .Pp
 On Mac OS X, these routines are thread-safe and return a pointer to a
 thread-specific data structure.  The contents of this data
 structure are automatically released by subsequent calls to
 any of these routines on the same thread, or when the thread exits.
 .Pp
 On Mac OS X, these routines are thread-safe and return a pointer to a
 thread-specific data structure.  The contents of this data
 structure are automatically released by subsequent calls to
 any of these routines on the same thread, or when the thread exits.
+These routines are therefore unsuitable for use in libraries or frameworks,
+from where they may overwrite the per-thread data that the calling
+application expects to find as a result of its own calls to these
+routines. Library and framework code should use the alternative reentrant 
+variants detailed below.
 .Pp
 The
 .Fn getgrent
 .Pp
 The
 .Fn getgrent
@@ -111,17 +132,15 @@ sequentially reads the group database and is intended for programs
 that wish to step through the complete list of groups.
 .Pp
 The functions
 that wish to step through the complete list of groups.
 .Pp
 The functions
-.\".Fn getgrent_r ,
-.\".Fn getgrnam_r ,
-.Fn getgrnam_r
-and
-.Fn getgrgid_r
-are thread-safe versions of
-.\".Fn getgrent ,
-.\".Fn getgrnam ,
-.Fn getgrnam
+.Fn getgrnam_r , 
+.Fn getgrgid_r ,
 and
 and
+.Fn getgruuid_r
+are alternative versions of
+.Fn getgrnam ,
 .Fn getgrgid ,
 .Fn getgrgid ,
+and
+.Fn getgruuid
 respectively.
 The caller must provide storage for the results of the search in
 the
 respectively.
 The caller must provide storage for the results of the search in
 the
@@ -186,11 +205,10 @@ Note that programs must explicitly set
 to zero before calling any of these functions if they need to
 distinguish between a non-existent entry and an error.
 The functions
 to zero before calling any of these functions if they need to
 distinguish between a non-existent entry and an error.
 The functions
-.\".Fn getgrent_r ,
-.\".Fn getgrnam_r ,
-.Fn getgrnam_r
+.Fn getgrnam_r ,
+.Fn getgrgid_r ,
 and
 and
-.Fn getgrgid_r
+.Fn getgruuid_r
 return 0 if no error occurred, or an error number to indicate failure.
 It is not an error if a matching entry is not found.
 (Thus, if
 return 0 if no error occurred, or an error number to indicate failure.
 It is not an error if a matching entry is not found.
 (Thus, if
@@ -216,13 +234,13 @@ group database file
 .Sh COMPATIBILITY
 The historic function
 .Fn setgrfile ,
 .Sh COMPATIBILITY
 The historic function
 .Fn setgrfile ,
-which allowed the specification of alternate password databases, has
+which allowed the specification of alternate group databases, has
 been deprecated and is no longer available.
 .Sh SEE ALSO
 .Xr getpwent 3 ,
 .Xr group 5 ,
 been deprecated and is no longer available.
 .Sh SEE ALSO
 .Xr getpwent 3 ,
 .Xr group 5 ,
-.\".Xr nsswitch.conf 5 ,
-.Xr DirectoryService 8 ,
+.Xr mbr_gid_to_uuid 3, 
+.Xr opendirectory 8 ,
 .Xr yp 8
 .Sh STANDARDS
 The
 .Xr yp 8
 .Sh STANDARDS
 The
@@ -265,11 +283,17 @@ and
 .Fn getgrgid_r
 appeared in
 .Fx 5.1 .
 .Fn getgrgid_r
 appeared in
 .Fx 5.1 .
+The functions
+.Fn getgruuid
+and
+.Fn getgruuid_r
+appeared in Mac OS X 10.8.
 .Sh BUGS
 The functions
 .Fn getgrent ,
 .Fn getgrnam ,
 .Fn getgrgid ,
 .Sh BUGS
 The functions
 .Fn getgrent ,
 .Fn getgrnam ,
 .Fn getgrgid ,
+.Fn getgruuid ,
 .Fn setgroupent
 and
 .Fn setgrent
 .Fn setgroupent
 and
 .Fn setgrent
@@ -278,21 +302,3 @@ a pointer to that object.
 Subsequent calls to
 the same function
 will modify the same object.
 Subsequent calls to
 the same function
 will modify the same object.
-.\".Pp
-.\"The functions
-.\".Fn getgrent ,
-.\".Fn getgrent_r ,
-.\".Fn endgrent ,
-.\".Fn setgroupent ,
-.\"and
-.\".Fn setgrent
-.\"are fairly useless in a networked environment and should be
-.\"avoided, if possible.
-.\"The
-.\".Fn getgrent
-.\"and
-.\".Fn getgrent_r
-.\"functions
-.\"make no attempt to suppress duplicate information if multiple
-.\"sources are specified in
-.\".Xr nsswitch.conf 5 .
index 75c99c352388c643ff8a2c7b23c05f8f282c052f..14bf4c10c115559ba51f5f92e9a5eac695504c48 100644 (file)
@@ -28,7 +28,7 @@
 .\"     From: @(#)getpwent.3   8.2 (Berkeley) 12/11/93
 .\" $FreeBSD: src/lib/libc/gen/getpwent.3,v 1.30 2007/01/09 00:27:54 imp Exp $
 .\"
 .\"     From: @(#)getpwent.3   8.2 (Berkeley) 12/11/93
 .\" $FreeBSD: src/lib/libc/gen/getpwent.3,v 1.30 2007/01/09 00:27:54 imp Exp $
 .\"
-.Dd April 16, 2003
+.Dd October 26, 2011
 .Dt GETPWENT 3
 .Os
 .Sh NAME
 .Dt GETPWENT 3
 .Os
 .Sh NAME
@@ -38,6 +38,8 @@
 .Nm getpwnam_r ,
 .Nm getpwuid ,
 .Nm getpwuid_r ,
 .Nm getpwnam_r ,
 .Nm getpwuid ,
 .Nm getpwuid_r ,
+.Nm getpwuuid ,
+.Nm getpwuuid_r ,
 .Nm setpassent ,
 .Nm setpwent ,
 .Nm endpwent
 .Nm setpassent ,
 .Nm setpwent ,
 .Nm endpwent
@@ -47,6 +49,7 @@
 .Sh SYNOPSIS
 .In sys/types.h
 .In pwd.h
 .Sh SYNOPSIS
 .In sys/types.h
 .In pwd.h
+.In uuid/uuid.h
 .Ft struct passwd *
 .Fn getpwent void
 .\".Ft int
 .Ft struct passwd *
 .Fn getpwent void
 .\".Ft int
 .Ft int
 .Fn getpwuid_r "uid_t uid" "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result"
 .Ft int
 .Ft int
 .Fn getpwuid_r "uid_t uid" "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result"
 .Ft int
+.Fn getpwuuid "uuid_t uuid"
+.Ft int
+.Fn getpwuuid_r "uuid_t uuid" "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result"
+.Ft int
 .Fn setpassent "int stayopen"
 .Ft void
 .Fn setpwent void
 .Fn setpassent "int stayopen"
 .Ft void
 .Fn setpwent void
 These functions
 .\"operate on the password database file
 obtain information from
 These functions
 .\"operate on the password database file
 obtain information from
-.Xr DirectoryService 8 ,
+.Xr opendirectoryd 8 ,
 including records in
 including records in
-.Pa /etc/passwd
+.Pa /etc/master.passwd
 which is described
 in
 which is described
 in
-.Xr passwd 5 .
+.Xr master.passwd 5 .
 Each entry in the database is defined by the structure
 .Vt passwd
 found in the include
 Each entry in the database is defined by the structure
 .Vt passwd
 found in the include
@@ -97,16 +104,28 @@ struct passwd {
 .Ed
 .Pp
 The functions
 .Ed
 .Pp
 The functions
-.Fn getpwnam
+.Fn getpwnam ,
+.Fn getpwuid ,
 and
 and
-.Fn getpwuid
-search the password database for the given login name or user uid,
+.Fn getpwuuid
+search the password database for the given login name, user uid, or user uuid
 respectively, always returning the first one encountered.
 .Pp
 respectively, always returning the first one encountered.
 .Pp
+Note that the password file
+.Pa /etc/master.passwd
+does not contain user UUIDs.
+The UUID for a user may be found using
+.Fn mbr_uid_to_uuid .
+.Pp
 On Mac OS X, these routines are thread-safe and return a pointer to a
 thread-specific data structure.  The contents of this data
 structure are automatically released by subsequent calls to
 any of these routines on the same thread, or when the thread exits.
 On Mac OS X, these routines are thread-safe and return a pointer to a
 thread-specific data structure.  The contents of this data
 structure are automatically released by subsequent calls to
 any of these routines on the same thread, or when the thread exits.
+These routines are therefore unsuitable for use in libraries or frameworks,
+from where they may overwrite the per-thread data that the calling
+application expects to find as a result of its own calls to these
+routines. Library and framework code should use the alternative reentrant 
+variants detailed below.
 .Pp
 The
 .Fn getpwent
 .Pp
 The
 .Fn getpwent
@@ -115,30 +134,31 @@ sequentially reads the password database and is intended for programs
 that wish to process the complete list of users.
 .Pp
 The functions
 that wish to process the complete list of users.
 .Pp
 The functions
-.\".Fn getpwent_r ,
-.\".Fn getpwnam_r ,
-.Fn getpwnam_r
-and
-.Fn getpwuid_r
-are thread-safe versions of
-.\".Fn getpwent ,
-.\".Fn getpwnam ,
-.Fn getpwnam
+.Fn getpwnam_r ,
+.Fn getpwuid_r ,
 and
 and
+.Fn getpwuuid_r
+are alternative versions of
+.Fn getpwnam ,
 .Fn getpwuid ,
 .Fn getpwuid ,
-respectively.
-The caller must provide storage for the results of the search in
-the
-.Fa pwd ,
-.Fa buffer ,
-.Fa bufsize ,
 and
 and
-.Fa result
-arguments.
-When these functions are successful, the
+.Fn getpwuuid
+respectively.
+They store the results of their search in the caller-provided
+.Fa pwd 
+structure, which additionally contains pointers to strings that are 
+stored in the caller-provided 
+.Fa buffer
+of size
+.Fa bufsize .
+(The maximum required
+.Fa bufsize
+can be obtained by passing the _SC_GETPW_R_SIZE_MAX constant to the
+.Xr sysconf 3
+call. See example code below.) When these functions are successful, the
 .Fa pwd
 .Fa pwd
-argument will be filled-in, and a pointer to that argument will be
-stored in
+argument will be filled in, and a pointer to that argument will be
+stored in the caller-provided
 .Fa result .
 If an entry is not found or an error occurs,
 .Fa result
 .Fa result .
 If an entry is not found or an error occurs,
 .Fa result
@@ -188,7 +208,7 @@ by returning a structure whose password field points to the string
 .Ql ******** .
 Legacy crypt passwords are still returned for user records created on
 earlier versions of Mac OS X whose
 .Ql ******** .
 Legacy crypt passwords are still returned for user records created on
 earlier versions of Mac OS X whose
-.Xr DirectoryService 8
+.Xr opendirectoryd 8
 .Dt AuthenticationAuthority
 attribute contains the value
 .Ql ;basic; .
 .Dt AuthenticationAuthority
 attribute contains the value
 .Ql ;basic; .
@@ -196,8 +216,9 @@ attribute contains the value
 The functions
 .Fn getpwent ,
 .Fn getpwnam ,
 The functions
 .Fn getpwent ,
 .Fn getpwnam ,
+.Fn getpwuid ,
 and
 and
-.Fn getpwuid
+.Fn getpwuuid
 return a valid pointer to a passwd structure on success
 or
 .Dv NULL
 return a valid pointer to a passwd structure on success
 or
 .Dv NULL
@@ -210,11 +231,10 @@ Note that programs must explicitly set
 to zero before calling any of these functions if they need to
 distinguish between a non-existent entry and an error.
 The functions
 to zero before calling any of these functions if they need to
 distinguish between a non-existent entry and an error.
 The functions
-.\".Fn getpwent_r ,
-.\".Fn getpwnam_r ,
-.Fn getpwnam_r
+.Fn getpwnam_r ,
+.Fn getpwuid_r ,
 and
 and
-.Fn getpwuid_r
+.Fn getpwuuid_r
 return 0 if no error occurred, or an error number to indicate failure.
 It is not an error if a matching entry is not found.
 (Thus, if
 return 0 if no error occurred, or an error number to indicate failure.
 It is not an error if a matching entry is not found.
 (Thus, if
@@ -232,6 +252,27 @@ and
 .Fn setpwent
 functions
 have no return value.
 .Fn setpwent
 functions
 have no return value.
+.Sh EXAMPLES
+To print the current user's home directory without depending on per-thread storage:
+.Bd -literal -offset indent
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pwd.h>
+
+int bufsize;
+
+if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1)
+    abort();
+
+char buffer[bufsize];
+struct passwd pwd, *result = NULL;
+if (getpwuid_r(getuid(), &pwd, buffer, bufsize, &result) != 0 || !result)
+    abort();
+
+printf("%s\\n", pwd.pw_dir);
+.Ed
 .Sh FILES
 .Bl -tag -width /etc/master.passwd -compact
 .\".It Pa /etc/pwd.db
 .Sh FILES
 .Bl -tag -width /etc/master.passwd -compact
 .\".It Pa /etc/pwd.db
@@ -272,7 +313,8 @@ The caller should retry with a larger buffer.
 .Xr passwd 5 ,
 .\".Xr pwd_mkdb 8 ,
 .\".Xr vipw 8 ,
 .Xr passwd 5 ,
 .\".Xr pwd_mkdb 8 ,
 .\".Xr vipw 8 ,
-.Xr DirectoryService 8 ,
+.Xr mbr_uid_to_uuid 3, 
+.Xr opendirectoryd 8 ,
 .Xr yp 8
 .Sh STANDARDS
 The
 .Xr yp 8
 .Sh STANDARDS
 The
@@ -308,12 +350,18 @@ and
 .Fn getpwuid_r
 functions appeared in
 .Fx 5.1 .
 .Fn getpwuid_r
 functions appeared in
 .Fx 5.1 .
+The functions
+.Fn getpwuuid
+and
+.Fn getpwuuid_r
+appeared in Mac OS X 10.8.
 .Sh BUGS
 The functions
 .Fn getpwent ,
 .Fn getpwnam ,
 .Sh BUGS
 The functions
 .Fn getpwent ,
 .Fn getpwnam ,
-and
 .Fn getpwuid ,
 .Fn getpwuid ,
+and
+.Fn getpwuuid ,
 .\"leave their results in an internal static object and return
 leave their results in an internal thread-specific memory and return
 a pointer to that object.
 .\"leave their results in an internal static object and return
 leave their results in an internal thread-specific memory and return
 a pointer to that object.
diff --git a/lookup.subproj/grp.h b/lookup.subproj/grp.h
new file mode 100644 (file)
index 0000000..76a8efc
--- /dev/null
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)grp.h       8.2 (Berkeley) 1/21/94
+ */
+/* Portions copyright (c) 2000-2011 Apple Inc. All rights reserved. */ 
+
+#ifndef _GRP_H_
+#define        _GRP_H_
+
+#include <_types.h>
+
+#ifndef _GID_T
+typedef __darwin_gid_t gid_t;          /* [XBD] */
+#define _GID_T
+#endif
+
+/*
+ * Although the definition of size_t is not mandated by [TSF], the function
+ * prototypes defined by [TSF] for the thread reentrant functions include
+ * it as a type for their 4th arguments, so we define it here.
+ */
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef __darwin_size_t        size_t;         /* [???] */
+#endif
+
+#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
+#define        _PATH_GROUP             "/etc/group"
+#endif
+
+struct group {
+       char    *gr_name;               /* [XBD] group name */
+       char    *gr_passwd;             /* [???] group password */
+       gid_t   gr_gid;                 /* [XBD] group id */
+       char    **gr_mem;               /* [XBD] group members */
+};
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+/* [XBD] */
+struct group *getgrgid(gid_t);
+struct group *getgrnam(const char *);
+/* [TSF] */
+int getgrgid_r(gid_t, struct group *, char *, size_t, struct group **);
+int getgrnam_r(const char *, struct group *, char *, size_t, struct group **);
+/* [XSI] */
+struct group *getgrent(void);
+void setgrent(void);
+void endgrent(void);
+__END_DECLS
+
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
+#include <uuid/uuid.h>
+__BEGIN_DECLS
+char *group_from_gid(gid_t, int);
+struct group *getgruuid(uuid_t);
+int getgruuid_r(uuid_t, struct group *, char *, size_t, struct group **);
+__END_DECLS
+#endif
+
+#if !defined(_XOPEN_SOURCE) || defined(_DARWIN_C_SOURCE)
+__BEGIN_DECLS
+void setgrfile(const char *);
+int setgroupent(int);
+__END_DECLS
+#endif
+
+#endif /* !_GRP_H_ */
index 0f5f2e2a7e9f14a9c5d0b9936e48b5cbbe7e3e25..7a9628ebbc198edac63cc0953f2ce13f1f3962ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2008 Apple Inc.  All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc.  All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <errno.h>
 #include <netdb.h>
 #include <string.h>
 #include <errno.h>
 #include <netdb.h>
+#include <asl.h>
 #include <printerdb.h>
 #include <sys/param.h>
 #include <sys/syscall.h>
 #include <printerdb.h>
 #include <sys/param.h>
 #include <sys/syscall.h>
@@ -38,6 +39,7 @@
 #include <thread_data.h>
 #include <sys/kauth.h>
 #include "netdb_async.h"
 #include <thread_data.h>
 #include <sys/kauth.h>
 #include "netdb_async.h"
+#include <dispatch/dispatch.h>
 
 #define SOCK_UNSPEC 0
 #define IPPROTO_UNSPEC 0
 
 #define SOCK_UNSPEC 0
 #define IPPROTO_UNSPEC 0
@@ -272,6 +274,24 @@ getpwuid_async_handle_reply(mach_msg_header_t *msg)
        si_async_handle_reply(msg);
 }
 
        si_async_handle_reply(msg);
 }
 
+struct passwd *
+getpwuuid(uuid_t uuid)
+{
+       si_item_t *item;
+
+#ifdef CALL_TRACE
+       uuid_string_t uuidstr;
+       uuid_unparse_upper(uuid, uuidstr);
+       fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
+#endif
+
+       item = si_user_byuuid(si_search(), uuid);
+       LI_set_thread_item(CATEGORY_USER + 300, item);
+
+       if (item == NULL) return NULL;
+       return (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
+}
+
 void
 setpwent(void)
 {
 void
 setpwent(void)
 {
@@ -425,6 +445,24 @@ getgruid_async_handle_reply(mach_msg_header_t *msg)
        si_async_handle_reply(msg);
 }
 
        si_async_handle_reply(msg);
 }
 
+struct group *
+getgruuid(uuid_t uuid)
+{
+       si_item_t *item;
+
+#ifdef CALL_TRACE
+       uuid_string_t uuidstr;
+       uuid_unparse_upper(uuid, uuidstr);
+       fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
+#endif
+
+       item = si_group_byuuid(si_search(), uuid);
+       LI_set_thread_item(CATEGORY_GROUP + 300, item);
+
+       if (item == NULL) return NULL;
+       return (struct group *)((uintptr_t)item + sizeof(si_item_t));
+}
+
 void
 setgrent(void)
 {
 void
 setgrent(void)
 {
@@ -557,10 +595,42 @@ endnetgrent(void)
        LI_set_thread_list(CATEGORY_NETGROUP, NULL);
 }
 
        LI_set_thread_list(CATEGORY_NETGROUP, NULL);
 }
 
+#if DS_AVAILABLE
+static void
+_check_groups(const char *function, int32_t ngroups)
+{
+       static dispatch_once_t once;
+       
+       if (ngroups > 0 && ngroups < NGROUPS_MAX) {
+               return;
+       }
+       
+       /* only log once per process */
+       dispatch_once(&once, ^(void) {
+               const char *proc_name = getprogname();
+               if (strcmp(proc_name, "id") != 0 && strcmp(proc_name, "smbd") != 0 && strcmp(proc_name, "rpcsvchost") != 0) {
+                       aslmsg msg = asl_new(ASL_TYPE_MSG);
+                       char buffer[256];
+                       
+                       snprintf(buffer, sizeof(buffer), "%d", (ngroups == 0 ? INT_MAX : ngroups));
+                       asl_set(msg, "com.apple.message.value", buffer);
+                       
+                       asl_set(msg, "com.apple.message.domain", "com.apple.system.libinfo");
+                       asl_set(msg, "com.apple.message.result", "noop");
+                       asl_set(msg, "com.apple.message.signature", function);
+                       
+                       asl_log(NULL, msg, ASL_LEVEL_NOTICE, "%s called triggering group enumeration", function);
+                       
+                       asl_free(msg);
+               }
+       });
+}
+#endif
+
 /* GROUPLIST */
 
 static int
 /* GROUPLIST */
 
 static int
-getgrouplist_internal(const char *name, int basegid, gid_t *groups, uint32_t *ngroups, int set_thread_data)
+getgrouplist_internal(const char *name, int basegid, gid_t *groups, uint32_t *ngroups)
 {
        int i, j, x, g, add, max;
        si_item_t *item;
 {
        int i, j, x, g, add, max;
        si_item_t *item;
@@ -580,34 +650,31 @@ getgrouplist_internal(const char *name, int basegid, gid_t *groups, uint32_t *ng
        if (groups == NULL) return 0;
        if (ngroups == NULL) return 0;
 
        if (groups == NULL) return 0;
        if (ngroups == NULL) return 0;
 
-       max = *ngroups;
+       max = (*ngroups);
        *ngroups = 0;
        if (max <= 0) return 0;
 
        groups[0] = basegid;
        *ngroups = 1;
        *ngroups = 0;
        if (max <= 0) return 0;
 
        groups[0] = basegid;
        *ngroups = 1;
-
-       item = si_grouplist(si_search(), name);
-       if (set_thread_data != 0) LI_set_thread_item(CATEGORY_GROUPLIST, item);
+       
+       item = si_grouplist(si_search(), name, max);
+       LI_set_thread_item(CATEGORY_GROUPLIST, item);
        if (item == NULL) return 0;
 
        gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t));
 
        x = 1;
 
        if (item == NULL) return 0;
 
        gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t));
 
        x = 1;
 
-       if (gl->gl_basegid != basegid)
-       {
-               if (x >= max) return -1;
-               groups[x] = gl->gl_basegid;
-               x++;
-               *ngroups = x;
-       }
-
        for (i = 0; i < gl->gl_count; i++)
        {
        for (i = 0; i < gl->gl_count; i++)
        {
-               g = (int)*(gl->gl_gid[i]);
+               g = gl->gl_gid[i];
                add = 1;
                add = 1;
-               for (j = 0; (j < x) && (add == 1); j++) if (groups[j] == g) add = 0;
+               for (j = 0; j < x; j++) {
+                       if (groups[j] == g) {
+                               add = 0;
+                               break;
+                       }
+               }
                if (add == 0) continue;
 
                if (x >= max) return -1;
                if (add == 0) continue;
 
                if (x >= max) return -1;
@@ -622,121 +689,100 @@ getgrouplist_internal(const char *name, int basegid, gid_t *groups, uint32_t *ng
 int
 getgrouplist(const char *name, int basegid, int *groups, int *ngroups)
 {
 int
 getgrouplist(const char *name, int basegid, int *groups, int *ngroups)
 {
-       return getgrouplist_internal(name, basegid, (gid_t *)groups, (uint32_t *)ngroups, 1);
-}
+#if DS_AVAILABLE
+       _check_groups("getgrouplist", *ngroups);
+#endif
 
 
-/* XXX to do: async getgrouplist */
+       return getgrouplist_internal(name, basegid, (gid_t *)groups, (uint32_t *)ngroups);
+}
 
 
-static int
-merge_gid(gid_t **list, gid_t g, int32_t *count)
+static void
+merge_gid(gid_t *list, gid_t g, int32_t *count)
 {
 {
+       int32_t cnt;
        int i;
 
        int i;
 
-       if (list == NULL) return -1;
+       cnt = (*count);
+       for (i = 0; i < cnt; i++) {
+               if (list[i] == g) return;
+       }
 
 
-       if (*count == 0)
-       {
-               *list = (gid_t *)calloc(1, sizeof(gid_t));
-               if (list == NULL)
-               {
-                       errno = ENOMEM;
-                       return -1;
-               }
+       list[cnt] = g;
+       (*count)++;
+}
 
 
-               (*list)[(*count)++] = g;
-               return 0;
-       }
+static int32_t
+_getgrouplist_2_internal(const char *name, gid_t basegid, gid_t **groups)
+{
+       int32_t i, count;
+       si_item_t *item;
+       gid_t *gids;
+       si_grouplist_t *gl;
+
+       item = si_grouplist(si_search(), name, INT_MAX);
+       LI_set_thread_item(CATEGORY_GROUPLIST, item);
+       if (item == NULL) return -1;
 
 
-       for (i = 0; i < *count; i++) if ((*list)[i] == g) return 0;
+       gl = (si_grouplist_t *) ((uintptr_t) item + sizeof(si_item_t));
+       
+       /*
+        * we can allocate enough up-front, we'll only use what we need
+        * we add one to the count that was found in case the basegid is not there
+        */
+       gids = calloc(gl->gl_count + 1, sizeof(gid_t));
 
 
-       *list = (gid_t *)reallocf(*list, (*count + 1) * sizeof(gid_t));
-       (*list)[(*count)++] = g;
-       return 0;
+       count = 0;
+       merge_gid(gids, basegid, &count);
+       if (gl->gl_gid != NULL) {
+               for (i = 0; i < gl->gl_count; i++) {
+                       merge_gid(gids, gl->gl_gid[i], &count);
+               }
+       }
+       
+       (*groups) = gids;
+       
+       return count;
 }
 
 int32_t
 getgrouplist_2(const char *name, gid_t basegid, gid_t **groups)
 {
 }
 
 int32_t
 getgrouplist_2(const char *name, gid_t basegid, gid_t **groups)
 {
-       int32_t i, status, count;
-       gid_t g;
-       si_item_t *item;
-       si_grouplist_t *gl;
-
        /*
         * Passes back a gid_t list containing all the users groups (and basegid).
         * Caller must free the list.
         * Returns the number of gids in the list or -1 on failure.
         */
        /*
         * Passes back a gid_t list containing all the users groups (and basegid).
         * Caller must free the list.
         * Returns the number of gids in the list or -1 on failure.
         */
-
+       
 #ifdef CALL_TRACE
        fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
 #endif
 #ifdef CALL_TRACE
        fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
 #endif
-
+       
        if (name == NULL) return 0;
        if (groups == NULL) return 0;
        if (name == NULL) return 0;
        if (groups == NULL) return 0;
-
-       item = si_grouplist(si_search(), name);
-       LI_set_thread_item(CATEGORY_GROUPLIST, item);
-       if (item == NULL) return -1;
-
-       gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t));
-
-       count = 0;
-       *groups = NULL;
-
-       status = merge_gid(groups, basegid, &count);
-       if (status != 0) return status;
-
-       status = merge_gid(groups, gl->gl_basegid, &count);
-       if (status != 0) return status;
-
-       for (i = 0; i < gl->gl_count; i++)
-       {
-               g = (gid_t)*(gl->gl_gid[i]);
-               status = merge_gid(groups, g, &count);
-               if (status != 0) return status;
-       }
-
-       return count;
+       
+#if DS_AVAILABLE
+       _check_groups("getgrouplist_2", INT_MAX);
+#endif
+       
+       return _getgrouplist_2_internal(name, basegid, groups);
 }
 
 int32_t
 getgroupcount(const char *name, gid_t basegid)
 {
 }
 
 int32_t
 getgroupcount(const char *name, gid_t basegid)
 {
-       int32_t i, status, count;
-       gid_t g;
-       si_item_t *item;
-       si_grouplist_t *gl;
+       int32_t count;
        gid_t *groups;
 
 #ifdef CALL_TRACE
        fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
 #endif
 
        gid_t *groups;
 
 #ifdef CALL_TRACE
        fprintf(stderr, "-> %s %s %d\n", __func__, name, basegid);
 #endif
 
-       if (name == NULL) return 0;
-
-       item = si_grouplist(si_search(), name);
-       LI_set_thread_item(CATEGORY_GROUPLIST, item);
-       if (item == NULL) return -1;
-
-       gl = (si_grouplist_t *)((uintptr_t)item + sizeof(si_item_t));
+#if DS_AVAILABLE
+       _check_groups("getgroupcount", INT_MAX);
+#endif
 
 
-       count = 0;
        groups = NULL;
        groups = NULL;
-
-       status = merge_gid(&groups, basegid, &count);
-       if (status != 0) return status;
-
-       status = merge_gid(&groups, gl->gl_basegid, &count);
-       if (status != 0) return status;
-
-       for (i = 0; i < gl->gl_count; i++)
-       {
-               g = (gid_t)*(gl->gl_gid[i]);
-               status = merge_gid(&groups, g, &count);
-               if (status != 0) return status;
-       }
-
+       count = _getgrouplist_2_internal(name, basegid, &groups);
        if (groups != NULL) free(groups);
 
        return count;
        if (groups != NULL) free(groups);
 
        return count;
@@ -770,19 +816,19 @@ initgroups(const char *name, int basegid)
        {
                p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
                uid = p->pw_uid;
        {
                p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
                uid = p->pw_uid;
-
                si_item_release(item);
        }
 #endif
 
        ngroups = NGROUPS;
 
                si_item_release(item);
        }
 #endif
 
        ngroups = NGROUPS;
 
-       status = getgrouplist_internal(name, basegid, groups, &ngroups, 0);
        /*
         * Ignore status.
         * A failure either means that user belongs to more than NGROUPS groups 
         * or no groups at all.
         */
        /*
         * Ignore status.
         * A failure either means that user belongs to more than NGROUPS groups 
         * or no groups at all.
         */
+    
+       (void) getgrouplist_internal(name, basegid, groups, &ngroups);
 
        status = __initgroups(ngroups, groups, uid);
        if (status < 0) return -1;
 
        status = __initgroups(ngroups, groups, uid);
        if (status < 0) return -1;
@@ -3046,6 +3092,37 @@ getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize, struct gr
        return 0;
 }
 
        return 0;
 }
 
+int
+getgruuid_r(uuid_t uuid, struct group *grp, char *buffer, size_t bufsize, struct group **result)
+{
+       si_item_t *item;
+       struct group *g;
+       int status;
+       
+#ifdef CALL_TRACE
+       uuid_string_t uuidstr;
+       uuid_unparse_upper(uuid, uuidstr);
+       fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
+#endif
+
+       if (result != NULL) *result = NULL;
+
+       if ((grp == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
+       
+       item = si_group_byuuid(si_search(), uuid);
+       if (item == NULL) return 0;
+       
+       g = (struct group *)((uintptr_t)item + sizeof(si_item_t));
+       
+       status = copy_group_r(g, grp, buffer, bufsize);
+       si_item_release(item);
+       
+       if (status != 0) return ERANGE;
+       
+       *result = grp;
+       return 0;
+}
+
 int
 getpwnam_r(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
 {
 int
 getpwnam_r(const char *name, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
 {
@@ -3104,6 +3181,37 @@ getpwuid_r(uid_t uid, struct passwd *pw, char *buffer, size_t bufsize, struct pa
        return 0;
 }
 
        return 0;
 }
 
+int
+getpwuuid_r(uuid_t uuid, struct passwd *pw, char *buffer, size_t bufsize, struct passwd **result)
+{
+       si_item_t *item;
+       struct passwd *p;
+       int status;
+
+#ifdef CALL_TRACE
+       uuid_string_t uuidstr;
+       uuid_unparse_upper(uuid, uuidstr);
+       fprintf(stderr, "-> %s %s\n", __func__, uuidstr);
+#endif
+
+       if (result != NULL) *result = NULL;
+
+       if ((pw == NULL) || (buffer == NULL) || (result == NULL) || (bufsize == 0)) return ERANGE;
+
+       item = si_user_byuuid(si_search(), uuid);
+       if (item == NULL) return 0;
+
+       p = (struct passwd *)((uintptr_t)item + sizeof(si_item_t));
+
+       status = copy_user_r(p, pw, buffer, bufsize);
+       si_item_release(item);
+
+       if (status != 0) return ERANGE;
+
+       *result = pw;
+       return 0;
+}
+
 /* misc */
 
 char *
 /* misc */
 
 char *
index 7f23aadd63f33cc4333171045d481ba6a100a702..27a907f9ea2e1e6b40228b8367db27d8fc27fd7f 100644 (file)
@@ -1515,9 +1515,9 @@ _mdns_search(const char *name, int class, int type, const char *interface, DNSSe
                        extra.tv_sec = SHORT_AAAA_EXTRA;
                        extra.tv_nsec = 0;
 
                        extra.tv_sec = SHORT_AAAA_EXTRA;
                        extra.tv_nsec = 0;
 
-                       // if delta is really small, we probably got a result from mDNSResponder's cache
-                       if ((delta.tv_sec == 0) && (delta.tv_nsec <= 200000000)) {
-                               extra.tv_sec = LONG_AAAA_EXTRA;
+                       // if delta is small (<= 20 milliseconds), we probably got a result from mDNSResponder's cache
+                       if ((delta.tv_sec == 0) && (delta.tv_nsec <= 20000000)) {
+                               extra.tv_sec = MEDIUM_AAAA_EXTRA;
                        }
                        else if (n_iface_4 == 0) {
                                extra.tv_sec = LONG_AAAA_EXTRA;
                        }
                        else if (n_iface_4 == 0) {
                                extra.tv_sec = LONG_AAAA_EXTRA;
diff --git a/lookup.subproj/pwd.h b/lookup.subproj/pwd.h
new file mode 100644 (file)
index 0000000..d58d696
--- /dev/null
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ * Portions Copyright(C) 1995, Jason Downs.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pwd.h       8.2 (Berkeley) 1/21/94
+ */
+/* Portions copyright (c) 2000-2011 Apple Inc. All rights reserved. */
+
+#ifndef _PWD_H_
+#define        _PWD_H_
+
+#include <_types.h>
+
+#ifndef _GID_T
+typedef __darwin_gid_t         gid_t;
+#define _GID_T
+#endif
+
+#ifndef _SIZE_T
+#define _SIZE_T
+typedef        __darwin_size_t         size_t;
+#endif
+
+#ifndef _UID_T
+typedef __darwin_uid_t         uid_t;
+#define _UID_T
+#endif
+
+#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
+#define        _PATH_PWD               "/etc"
+#define        _PATH_PASSWD            "/etc/passwd"
+#define        _PASSWD                 "passwd"
+#define        _PATH_MASTERPASSWD      "/etc/master.passwd"
+#define        _PATH_MASTERPASSWD_LOCK "/etc/ptmp"
+#define        _MASTERPASSWD           "master.passwd"
+
+#define        _PATH_MP_DB             "/etc/pwd.db"
+#define        _MP_DB                  "pwd.db"
+#define        _PATH_SMP_DB            "/etc/spwd.db"
+#define        _SMP_DB                 "spwd.db"
+
+#define        _PATH_PWD_MKDB          "/usr/sbin/pwd_mkdb"
+
+#define        _PW_KEYBYNAME           '1'     /* stored by name */
+#define        _PW_KEYBYNUM            '2'     /* stored by entry in the "file" */
+#define        _PW_KEYBYUID            '3'     /* stored by uid */
+
+#define        _PASSWORD_EFMT1         '_'     /* extended encryption format */
+
+#define        _PASSWORD_LEN           128     /* max length, not counting NULL */
+
+#define _PASSWORD_NOUID                0x01    /* flag for no specified uid. */
+#define _PASSWORD_NOGID                0x02    /* flag for no specified gid. */
+#define _PASSWORD_NOCHG                0x04    /* flag for no specified change. */
+#define _PASSWORD_NOEXP                0x08    /* flag for no specified expire. */
+
+#define _PASSWORD_WARNDAYS     14      /* days to warn about expiry */
+#define _PASSWORD_CHGNOW       -1      /* special day to force password
+                                        * change at next login */
+#endif
+
+struct passwd {
+       char    *pw_name;               /* user name */
+       char    *pw_passwd;             /* encrypted password */
+       uid_t   pw_uid;                 /* user uid */
+       gid_t   pw_gid;                 /* user gid */
+       __darwin_time_t pw_change;              /* password change time */
+       char    *pw_class;              /* user access class */
+       char    *pw_gecos;              /* Honeywell login info */
+       char    *pw_dir;                /* home directory */
+       char    *pw_shell;              /* default shell */
+       __darwin_time_t pw_expire;              /* account expiration */
+};
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+struct passwd  *getpwuid(uid_t);
+struct passwd  *getpwnam(const char *);
+int             getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **);
+int             getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **);
+struct passwd  *getpwent(void);
+void            setpwent(void);
+void            endpwent(void);
+__END_DECLS
+
+#if (!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || defined(_DARWIN_C_SOURCE)
+#include <uuid/uuid.h>
+__BEGIN_DECLS
+int             setpassent(int);
+char           *user_from_uid(uid_t, int);
+struct passwd  *getpwuuid(uuid_t);
+int             getpwuuid_r(uuid_t, struct passwd *, char *, size_t, struct passwd **);
+__END_DECLS
+#endif
+
+#endif /* !_PWD_H_ */
index 2b17317cacf348fc6f6e1455cb1f7875de3c605a..7d4f0ece349d791980d638e5efe84a2286663fc9 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2008-2010 Apple Inc.  All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc.  All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -223,6 +223,37 @@ search_item_bynumber(si_mod_t *si, uint32_t number, int cat, si_item_t *(*call)(
        return NULL;
 }
 
        return NULL;
 }
 
+static si_item_t *
+search_item_byuuid(si_mod_t *si, uuid_t uuid, int cat, si_item_t *(*call)(si_mod_t *, uuid_t))
+{
+       int i;
+       search_si_private_t *pp;
+       si_item_t *item;
+       si_mod_t *src;
+
+       if (si == NULL) return NULL;
+       if (call == NULL) return NULL;
+
+       pp = (search_si_private_t *)si->private;
+       if (pp == NULL) return NULL;
+
+       i = 0;
+
+       while (NULL != (src = search_get_module(pp, cat, &i)))
+       {
+               item = call(src, uuid);
+               if (item != NULL)
+               {
+                       /*
+                        * N.B. item not added to cache, since the data does not
+                        * contain the uuid that was used to find it.
+                        */
+                       return item;
+               }
+       }
+
+       return NULL;
+}
 static si_list_t *
 search_list(si_mod_t *si, int cat, si_list_t *(*call)(si_mod_t *))
 {
 static si_list_t *
 search_list(si_mod_t *si, int cat, si_list_t *(*call)(si_mod_t *))
 {
@@ -280,6 +311,12 @@ search_user_byuid(si_mod_t *si, uid_t uid)
        return search_item_bynumber(si, (uint32_t)uid, CATEGORY_USER, si_user_byuid);
 }
 
        return search_item_bynumber(si, (uint32_t)uid, CATEGORY_USER, si_user_byuid);
 }
 
+static si_item_t *
+search_user_byuuid(si_mod_t *si, uuid_t uuid)
+{
+       return search_item_byuuid(si, uuid, CATEGORY_USER, si_user_byuuid);
+}
+
 static si_list_t *
 search_user_all(si_mod_t *si)
 {
 static si_list_t *
 search_user_all(si_mod_t *si)
 {
@@ -295,7 +332,13 @@ search_group_byname(si_mod_t *si, const char *name)
 static si_item_t *
 search_group_bygid(si_mod_t *si, gid_t gid)
 {
 static si_item_t *
 search_group_bygid(si_mod_t *si, gid_t gid)
 {
-       return search_item_bynumber(si, (uint32_t)gid, CATEGORY_USER, si_group_bygid);
+       return search_item_bynumber(si, (uint32_t)gid, CATEGORY_GROUP, si_group_bygid);
+}
+
+static si_item_t *
+search_group_byuuid(si_mod_t *si, uuid_t uuid)
+{
+       return search_item_byuuid(si, uuid, CATEGORY_GROUP, si_group_byuuid);
 }
 
 static si_list_t *
 }
 
 static si_list_t *
@@ -305,9 +348,30 @@ search_group_all(si_mod_t *si)
 }
 
 static si_item_t *
 }
 
 static si_item_t *
-search_groupist(si_mod_t *si, const char *name)
+search_groupist(si_mod_t *si, const char *name, uint32_t count)
 {
 {
-       return search_item_byname(si, name, CATEGORY_GROUPLIST, si_grouplist);
+       int i;
+       search_si_private_t *pp;
+       si_item_t *item = NULL;
+       si_mod_t *src;
+       
+       if (si == NULL) return NULL;
+       
+       pp = (search_si_private_t *)si->private;
+       if (pp == NULL) return NULL;
+       
+       i = 0;
+       
+       while (NULL != (src = search_get_module(pp, CATEGORY_GROUPLIST, &i))) {
+               if (src == pp->cache) continue;
+               
+               if (src->vtable->sim_grouplist != NULL) {
+                       item = src->vtable->sim_grouplist(si, name, count);
+                       if (item != NULL) break;
+               }
+       }
+       
+       return item;
 }
 
 static si_list_t *
 }
 
 static si_list_t *
@@ -333,6 +397,7 @@ search_netgroup_byname(si_mod_t *si, const char *name)
        }
 
        i = 0;
        }
 
        i = 0;
+       null_res = 0;
 
        all = NULL;
        while (NULL != (src = search_get_module(pp, cat, &i)))
 
        all = NULL;
        while (NULL != (src = search_get_module(pp, cat, &i)))
@@ -368,7 +433,6 @@ search_in_netgroup(si_mod_t *si, const char *group, const char *host, const char
 
        cat = CATEGORY_NETGROUP;
        i = 0;
 
        cat = CATEGORY_NETGROUP;
        i = 0;
-       innetgr = 0;
 
        while (NULL != (src = search_get_module(pp, cat, &i)))
        {
 
        while (NULL != (src = search_get_module(pp, cat, &i)))
        {
@@ -808,10 +872,12 @@ si_module_static_search(void)
 
                .sim_user_byname = &search_user_byname,
                .sim_user_byuid = &search_user_byuid,
 
                .sim_user_byname = &search_user_byname,
                .sim_user_byuid = &search_user_byuid,
+               .sim_user_byuuid = &search_user_byuuid,
                .sim_user_all = &search_user_all,
 
                .sim_group_byname = &search_group_byname,
                .sim_group_bygid = &search_group_bygid,
                .sim_user_all = &search_user_all,
 
                .sim_group_byname = &search_group_byname,
                .sim_group_bygid = &search_group_bygid,
+               .sim_group_byuuid = &search_group_byuuid,
                .sim_group_all = &search_group_all,
 
                .sim_grouplist = &search_groupist,
                .sim_group_all = &search_group_all,
 
                .sim_grouplist = &search_groupist,
@@ -897,20 +963,24 @@ si_module_static_search(void)
                si_module_config_modules_for_category(pp, CATEGORY_DEFAULT, count, modules);
                pp->cache = pp->search_list[CATEGORY_DEFAULT].module[0];
 
                si_module_config_modules_for_category(pp, CATEGORY_DEFAULT, count, modules);
                pp->cache = pp->search_list[CATEGORY_DEFAULT].module[0];
 
-               FILE *conf = fopen(_PATH_SI_CONF, "r");
-               errno = 0;
-               if (conf != NULL)
+               char *check = getenv("SYSINFO_CONF_ENABLE");
+               if ((check != NULL) && (!strcmp(check, "1")))
                {
                {
-                       forever
+                       FILE *conf = fopen(_PATH_SI_CONF, "r");
+                       errno = 0;
+                       if (conf != NULL)
                        {
                        {
-                               char *line = _fsi_get_line(conf);
-                               if (line == NULL) break;
+                               forever
+                               {
+                                       char *line = _fsi_get_line(conf);
+                                       if (line == NULL) break;
 
 
-                               si_module_config_parse_line(pp, line);
-                               free(line);
-                       }
+                                       si_module_config_parse_line(pp, line);
+                                       free(line);
+                               }
 
 
-                       fclose(conf);
+                               fclose(conf);
+                       }
                }
        });
 
                }
        });
 
index f4bdabfadc33d6aa1bb2f9a7e3841de7c53f60f6..a0bbf51bfad70d7ac658a727b79a8209afe08209 100644 (file)
@@ -61,8 +61,8 @@ static uint32_t net_v4_count = 0;
 static uint32_t net_v6_count = 0;      // includes 6to4 addresses
 static pthread_mutex_t net_config_mutex = PTHREAD_MUTEX_INITIALIZER;
 
 static uint32_t net_v6_count = 0;      // includes 6to4 addresses
 static pthread_mutex_t net_config_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-// forward - temporary until we move this SPI to Libc
-int inet_aton_check(const char *cp, struct in_addr *addr, int strict);
+// Libc SPI
+int _inet_aton_check(const char *cp, struct in_addr *addr, int strict);
 
 typedef struct {
        struct hostent host;
 
 typedef struct {
        struct hostent host;
@@ -648,7 +648,7 @@ _gai_numerichost(const char* nodename, uint32_t *family, int flags, struct in_ad
                if (numerichost == 0)
                {
                        /* inet_pton doesn't allow "a", "a.b", or "a.b.c" forms, so we re-check */
                if (numerichost == 0)
                {
                        /* inet_pton doesn't allow "a", "a.b", or "a.b.c" forms, so we re-check */
-                       numerichost = inet_aton_check(nodename, a4, 1);
+                       numerichost = _inet_aton_check(nodename, a4, 1);
                }
 
                if (numerichost == 1)
                }
 
                if (numerichost == 1)
@@ -1662,180 +1662,3 @@ si_ipnode_byname(si_mod_t *si, const char *name, int family, int flags, const ch
 
        return item6;
 }
 
        return item6;
 }
-
-// Temporary until we move this SPI to Libc
-
-/*
- * Copyright (c) 1983, 1990, 1993
- *    The Regents of the University of California.  All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
- * 
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies, and that
- * the name of Digital Equipment Corporation not be used in advertising or
- * publicity pertaining to distribution of the document or software without
- * specific, written prior permission.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
- * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*%
- * Check whether "cp" is a valid ascii representation
- * of an Internet address and convert to a binary address.
- * Returns 1 if the address is valid, 0 if not.
- * This replaces inet_addr, the return value from which
- * cannot distinguish between failure and a local broadcast address.
- */
-int
-inet_aton_check(const char *cp, struct in_addr *addr, int strict) {
-       u_long val;
-       int base, n;
-       char c;
-       u_int8_t parts[4];
-       u_int8_t *pp = parts;
-       int digit;
-       
-       c = *cp;
-       for (;;) {
-               /*
-                * Collect number up to ``.''.
-                * Values are specified as for C:
-                * 0x=hex, 0=octal, isdigit=decimal.
-                */
-               if (!isdigit((unsigned char)c))
-                       return (0);
-               val = 0; base = 10; digit = 0;
-               if (c == '0') {
-                       c = *++cp;
-                       if (c == 'x' || c == 'X')
-                               base = 16, c = *++cp;
-                       else {
-                               base = 8;
-                               digit = 1 ;
-                       }
-               }
-               for (;;) {
-                       if (isascii(c) && isdigit((unsigned char)c)) {
-                               if (base == 8 && (c == '8' || c == '9'))
-                                       return (0);
-                               val = (val * base) + (c - '0');
-                               c = *++cp;
-                               digit = 1;
-                       } else if (base == 16 && isascii(c) && 
-                                          isxdigit((unsigned char)c)) {
-                               val = (val << 4) |
-                               (c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
-                               c = *++cp;
-                               digit = 1;
-                       } else
-                               break;
-               }
-               if (c == '.') {
-                       /*
-                        * Internet format:
-                        *      a.b.c.d
-                        *      a.b.c   (with c treated as 16 bits)
-                        *      a.b     (with b treated as 24 bits)
-                        */
-                       if (pp >= parts + 3 || val > 0xffU)
-                               return (0);
-                       *pp++ = val;
-                       c = *++cp;
-               } else
-                       break;
-       }
-       /*
-        * Check for trailing characters.
-        */
-       if (c != '\0') {
-               if (strict) return (0);
-               if (!isascii(c) || !isspace(c)) return (0);
-       }
-       /*
-        * Did we get a valid digit?
-        */
-       if (!digit)
-               return (0);
-       /*
-        * Concoct the address according to
-        * the number of parts specified.
-        */
-       n = pp - parts + 1;
-       switch (n) {
-               case 1:                         /*%< a -- 32 bits */
-                       break;
-                       
-               case 2:                         /*%< a.b -- 8.24 bits */
-                       if (val > 0xffffffU)
-                               return (0);
-                       val |= parts[0] << 24;
-                       break;
-                       
-               case 3:                         /*%< a.b.c -- 8.8.16 bits */
-                       if (val > 0xffffU)
-                               return (0);
-                       val |= (parts[0] << 24) | (parts[1] << 16);
-                       break;
-                       
-               case 4:                         /*%< a.b.c.d -- 8.8.8.8 bits */
-                       if (val > 0xffU)
-                               return (0);
-                       val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
-                       break;
-       }
-       if (addr != NULL)
-               addr->s_addr = htonl(val);
-       return (1);
-}
index b0fc5870fc5b2e1cf5d62accce57bb520928de46..86c00164fa20c52c68600f657400eec255574f76 100644 (file)
@@ -32,7 +32,7 @@
 #include <pthread.h>
 #include <mach/mach.h>
 #include <dispatch/dispatch.h>
 #include <pthread.h>
 #include <mach/mach.h>
 #include <dispatch/dispatch.h>
-
+#include <dispatch/private.h>
 #include "si_module.h"
 
 #define PLUGIN_DIR_PATH "/usr/lib/info"
 #include "si_module.h"
 
 #define PLUGIN_DIR_PATH "/usr/lib/info"
@@ -521,6 +521,14 @@ si_user_byuid(si_mod_t *si, uid_t uid)
        return si->vtable->sim_user_byuid(si, uid);
 }
 
        return si->vtable->sim_user_byuid(si, uid);
 }
 
+si_item_t *
+si_user_byuuid(si_mod_t *si, uuid_t uuid)
+{
+       if (si == NULL) return NULL;
+       if (si->vtable->sim_user_byuuid == NULL) return NULL;
+       return si->vtable->sim_user_byuuid(si, uuid);
+}
+
 si_list_t *
 si_user_all(si_mod_t *si)
 {
 si_list_t *
 si_user_all(si_mod_t *si)
 {
@@ -545,6 +553,14 @@ si_group_bygid(si_mod_t *si, gid_t gid)
        return si->vtable->sim_group_bygid(si, gid);
 }
 
        return si->vtable->sim_group_bygid(si, gid);
 }
 
+si_item_t *
+si_group_byuuid(si_mod_t *si, uuid_t uuid)
+{
+       if (si == NULL) return NULL;
+       if (si->vtable->sim_group_byuuid == NULL) return NULL;
+       return si->vtable->sim_group_byuuid(si, uuid);
+}
+
 si_list_t *
 si_group_all(si_mod_t *si)
 {
 si_list_t *
 si_group_all(si_mod_t *si)
 {
@@ -554,11 +570,11 @@ si_group_all(si_mod_t *si)
 }
 
 si_item_t *
 }
 
 si_item_t *
-si_grouplist(si_mod_t *si, const char *name)
+si_grouplist(si_mod_t *si, const char *name, uint32_t count)
 {
        if (si == NULL) return NULL;
        if (si->vtable->sim_grouplist == NULL) return NULL;
 {
        if (si == NULL) return NULL;
        if (si->vtable->sim_grouplist == NULL) return NULL;
-       return si->vtable->sim_grouplist(si, name);
+       return si->vtable->sim_grouplist(si, name, count);
 }
 
 si_list_t *
 }
 
 si_list_t *
@@ -772,7 +788,7 @@ si_item_call(struct si_mod_s *si, int call, const char *str1, const char *str2,
                case SI_CALL_USER_BYUID: return si_user_byuid(si, (uid_t)num1);
                case SI_CALL_GROUP_BYNAME: return si_group_byname(si, str1);
                case SI_CALL_GROUP_BYGID: return si_group_bygid(si, (gid_t)num1);
                case SI_CALL_USER_BYUID: return si_user_byuid(si, (uid_t)num1);
                case SI_CALL_GROUP_BYNAME: return si_group_byname(si, str1);
                case SI_CALL_GROUP_BYGID: return si_group_bygid(si, (gid_t)num1);
-               case SI_CALL_GROUPLIST: return si_grouplist(si, str1);
+               case SI_CALL_GROUPLIST: return si_grouplist(si, str1, (int) num1);
                case SI_CALL_ALIAS_BYNAME: return si_alias_byname(si, str1);
                case SI_CALL_HOST_BYNAME: return si_host_byname(si, str1, num1, str3, err);
                case SI_CALL_HOST_BYADDR: return si_host_byaddr(si, (void *)str1, num1, str3, err);
                case SI_CALL_ALIAS_BYNAME: return si_alias_byname(si, str1);
                case SI_CALL_HOST_BYNAME: return si_host_byname(si, str1, num1, str3, err);
                case SI_CALL_HOST_BYADDR: return si_host_byaddr(si, (void *)str1, num1, str3, err);
@@ -986,6 +1002,12 @@ si_async_workunit_release(si_async_workunit_t *r)
        if (r->str2 != NULL) free(r->str2);
        if (r->str3 != NULL) free(r->str3);
 
        if (r->str2 != NULL) free(r->str2);
        if (r->str3 != NULL) free(r->str3);
 
+       /* release send-once right if it has not been used */
+       if (r->send != MACH_PORT_NULL) mach_port_deallocate(mach_task_self(), r->send);
+
+       /* release receive right */
+       mach_port_mod_refs(mach_task_self(), r->port, MACH_PORT_RIGHT_RECEIVE, -1);
+
        free(r);
 }
 
        free(r);
 }
 
@@ -1033,6 +1055,7 @@ si_async_launchpad(si_async_workunit_t *r)
 
        msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, MACH_MSGH_BITS_ZERO);
        msg.header.msgh_remote_port = r->send;
 
        msg.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, MACH_MSGH_BITS_ZERO);
        msg.header.msgh_remote_port = r->send;
+       r->send = MACH_PORT_NULL;
        msg.header.msgh_local_port = MACH_PORT_NULL;
        msg.header.msgh_size = sizeof(mach_msg_empty_send_t);
        msg.header.msgh_id = r->call;
        msg.header.msgh_local_port = MACH_PORT_NULL;
        msg.header.msgh_size = sizeof(mach_msg_empty_send_t);
        msg.header.msgh_id = r->call;
@@ -1101,7 +1124,7 @@ si_async_cancel(mach_port_t p)
 
        /*
         * Test and set the WORKUNIT_CANCELLED flag.
 
        /*
         * Test and set the WORKUNIT_CANCELLED flag.
-        * If it was already set, this work item has been executed - too late to cancel.
+        * If it was already set, this work item has been executed - too late to really cancel.
         */
        if (OSAtomicTestAndSetBarrier(WORKUNIT_CANCELLED_BIT_ADDRESS, &(r->flags)) == 1)
        {
         */
        if (OSAtomicTestAndSetBarrier(WORKUNIT_CANCELLED_BIT_ADDRESS, &(r->flags)) == 1)
        {
@@ -1109,7 +1132,6 @@ si_async_cancel(mach_port_t p)
 #ifdef CALL_TRACE
                fprintf(stderr, "** %s worklist item %p has executed\n", __func__, r);
 #endif
 #ifdef CALL_TRACE
                fprintf(stderr, "** %s worklist item %p has executed\n", __func__, r);
 #endif
-               return;
        }
 
 #ifdef CALL_TRACE
        }
 
 #ifdef CALL_TRACE
@@ -1123,8 +1145,6 @@ si_async_cancel(mach_port_t p)
        }
 
        si_async_workunit_release(r);
        }
 
        si_async_workunit_release(r);
-
-       mach_port_mod_refs(mach_task_self(), p, MACH_PORT_RIGHT_RECEIVE, -1);
 }
 
 void
 }
 
 void
@@ -1169,8 +1189,6 @@ si_async_handle_reply(mach_msg_header_t *msg)
        }
 
        si_async_workunit_release(r);
        }
 
        si_async_workunit_release(r);
-
-       mach_port_mod_refs(mach_task_self(), reply, MACH_PORT_RIGHT_RECEIVE, -1);
 }
 
 char *
 }
 
 char *
index 37635c097de3a66dd097906bda2946d5856233be..a87c6292b2108a83dfd1779757e4bdf4a18d0fbe 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2008-2009 Apple Inc.  All rights reserved.
+ * Copyright (c) 2008-2011 Apple Inc.  All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -30,6 +30,7 @@
 #include <sys/socket.h>
 #include <pwd.h>
 #include <grp.h>
 #include <sys/socket.h>
 #include <pwd.h>
 #include <grp.h>
+#include <uuid/uuid.h>
 #include <netdb.h>
 #include <aliasdb.h>
 #include <fstab.h>
 #include <netdb.h>
 #include <aliasdb.h>
 #include <fstab.h>
@@ -150,9 +151,9 @@ typedef void (*list_async_callback)(si_list_t *, uint32_t, void *);
 typedef struct grouplist_s
 {
        char *gl_user;
 typedef struct grouplist_s
 {
        char *gl_user;
-       gid_t gl_basegid;
        int gl_count;
        int gl_count;
-       gid_t **gl_gid;
+       int gl_gid_siz;
+       gid_t *gl_gid;
 } si_grouplist_t;
 
 typedef struct addrinfo_s
 } si_grouplist_t;
 
 typedef struct addrinfo_s
@@ -211,13 +212,15 @@ struct si_mod_vtable_s
 
        si_item_t *(*sim_user_byname)(struct si_mod_s *si, const char *name);
        si_item_t *(*sim_user_byuid)(struct si_mod_s *si, uid_t uid);
 
        si_item_t *(*sim_user_byname)(struct si_mod_s *si, const char *name);
        si_item_t *(*sim_user_byuid)(struct si_mod_s *si, uid_t uid);
+       si_item_t *(*sim_user_byuuid)(struct si_mod_s *si, uuid_t uuid);
        si_list_t *(*sim_user_all)(struct si_mod_s *si);
 
        si_item_t *(*sim_group_byname)(struct si_mod_s *si, const char *name);
        si_item_t *(*sim_group_bygid)(struct si_mod_s *si, gid_t gid);
        si_list_t *(*sim_user_all)(struct si_mod_s *si);
 
        si_item_t *(*sim_group_byname)(struct si_mod_s *si, const char *name);
        si_item_t *(*sim_group_bygid)(struct si_mod_s *si, gid_t gid);
+       si_item_t *(*sim_group_byuuid)(struct si_mod_s *si, uuid_t uuid);
        si_list_t *(*sim_group_all)(struct si_mod_s *si);
 
        si_list_t *(*sim_group_all)(struct si_mod_s *si);
 
-       si_item_t *(*sim_grouplist)(struct si_mod_s *si, const char *name);
+       si_item_t *(*sim_grouplist)(struct si_mod_s *si, const char *name, uint32_t count);
 
        si_list_t *(*sim_netgroup_byname)(struct si_mod_s *si, const char *name);
        int (*sim_in_netgroup)(struct si_mod_s *si, const char *name, const char *host, const char *user, const char *domain);
 
        si_list_t *(*sim_netgroup_byname)(struct si_mod_s *si, const char *name);
        int (*sim_in_netgroup)(struct si_mod_s *si, const char *name, const char *host, const char *user, const char *domain);
@@ -296,13 +299,15 @@ int si_item_is_valid(si_item_t *item);
 
 si_item_t *si_user_byname(si_mod_t *si, const char *name);
 si_item_t *si_user_byuid(si_mod_t *si, uid_t uid);
 
 si_item_t *si_user_byname(si_mod_t *si, const char *name);
 si_item_t *si_user_byuid(si_mod_t *si, uid_t uid);
+si_item_t *si_user_byuuid(si_mod_t *si, uuid_t uuid);
 si_list_t *si_user_all(si_mod_t *si);
 
 si_item_t *si_group_byname(si_mod_t *si, const char *name);
 si_item_t *si_group_bygid(si_mod_t *si, gid_t gid);
 si_list_t *si_user_all(si_mod_t *si);
 
 si_item_t *si_group_byname(si_mod_t *si, const char *name);
 si_item_t *si_group_bygid(si_mod_t *si, gid_t gid);
+si_item_t *si_group_byuuid(si_mod_t *si, uuid_t uuid);
 si_list_t *si_group_all(si_mod_t *si);
 
 si_list_t *si_group_all(si_mod_t *si);
 
-si_item_t *si_grouplist(si_mod_t *si, const char *name);
+si_item_t *si_grouplist(si_mod_t *si, const char *name, uint32_t count);
 
 int si_in_netgroup(struct si_mod_s *si, const char *name, const char *host, const char *user, const char *domain);
 si_list_t *si_netgroup_byname(struct si_mod_s *si, const char *name);
 
 int si_in_netgroup(struct si_mod_s *si, const char *name, const char *host, const char *user, const char *domain);
 si_list_t *si_netgroup_byname(struct si_mod_s *si, const char *name);
index 5f947c3f49b5525dd45415f2bb3ad0eff7ffdb81..7467ad8bc2878487512b1ea3aa320e5a4984ed52 100644 (file)
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2005-2007 Apple Inc
+.\" Copyright (c) 2005-2011 Apple Inc
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" SUCH DAMAGE.
 .\"
 .\"
 .\" SUCH DAMAGE.
 .\"
 .\"
-.Dd February 3, 2005
+.Dd November 5, 2011
 .Dt MBR_CHECK_MEMBERSHIP 3
 .Os "Mac OS X"
 .Sh NAME
 .Dt MBR_CHECK_MEMBERSHIP 3
 .Os "Mac OS X"
 .Sh NAME
-.Nm mbr_check_membership
-.Nd check whether a user is a member of a group
+.Nm mbr_check_membership,
+.Nm mbr_check_service_membership
+.Nd check whether a user is a member of a group or service ACL
 .Sh SYNOPSIS
 .In membership.h
 .Ft int
 .Fn mbr_check_membership "uuid_t user" "uuid_t group" "int *ismember"
 .Sh SYNOPSIS
 .In membership.h
 .Ft int
 .Fn mbr_check_membership "uuid_t user" "uuid_t group" "int *ismember"
+.Ft int
+.Fn mbr_check_service_membership "uuid_t user" "const char *service" "int *ismember"
 .Sh DESCRIPTION
 .Fn mbr_check_membership
 .Sh DESCRIPTION
 .Fn mbr_check_membership
-tests if a given user is a member of a group, individually or as a member of a nested group.
+tests if a given user is a member of a group (either direct or indirect via a
+nested group).
 .Fa ismember
 .Fa ismember
-is set to 1 if the user is a member of the group, and 0 otherwise.  
+is set to 1 if the user is a member or 0 if not a member of the group.  
+.Fn mbr_check_service_membership
+similarly tests if a given user is a member of a service ACL group.  Service
+ACLs are special groups defined with the prefix "com.apple.access_".  The
+service is then prefixed (e.g., "afp" would check "com.apple.access_afp").
+There is a special group that grants accessto all services called
+"com.apple.access_all_services".
 .Pp
 Users may belong to any number of groups.
 .Fn mbr_check_membership
 .Pp
 Users may belong to any number of groups.
 .Fn mbr_check_membership
-should be always be used to check group membership, rather than
-calling
-.Xr getgroups 2 ,
-and checking the returned list of gids.
+should always be used to check group membership, rather than calling
+.Xr getgroups 2
+or
+.Xr getgrouplist 2 .
 The
 .Xr setgroups 2
 and
 The
 .Xr setgroups 2
 and
@@ -65,29 +75,35 @@ uuid is equal to the reserved "everyone" uuid (ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000
 .Fa ismember
 will be set to 1 for any valid user.
 .Pp
 .Fa ismember
 will be set to 1 for any valid user.
 .Pp
-Group membership information is managed by the
-.Xr DirectoryService 8
-daemon.
+Group membership information is managed by
+.Xr opendirectoryd 8 .
 .Sh RETURN VALUES
 .Fn mbr_check_membership
 .Sh RETURN VALUES
 .Fn mbr_check_membership
-returns 0 on success.
-It returns EIO if it is unable to communicate with the
-.Xr DirectoryService 8
-daemon.
-ENOENT is returned if
-.Fa user
-cannot be found.
-.Pp
-Note that 
-.Fn mbr_check_membership
 does not test whether
 .Fa group
 exists or not.
 Querying membership for a nonexistent group will result in
 .Fa ismember
 does not test whether
 .Fa group
 exists or not.
 Querying membership for a nonexistent group will result in
 .Fa ismember
-being to 0 and a return value of 0.
+being set to 0.  The function returns 0 on success or one of the following error
+codes on failure:
+.Bl -tag -width Er
+.It Bq Er EIO
+Communication with
+.Xr openditectoryd 8
+failed.
+.It Bq Er ENOENT
+.Fa user
+can not be found.
+.El
+.Pp
+.Fn mbr_check_service_membership
+is identical to
+.Fn mbr_check_membership
+except that ENOENT means no service ACL has been defined.
+.Pp
 .Sh SEE ALSO
 .Sh SEE ALSO
+.Xr odutil 1 ,
 .Xr setgroups 2 ,
 .Xr getgroups 2 ,
 .Xr mbr_uid_to_uuid 3 ,
 .Xr setgroups 2 ,
 .Xr getgroups 2 ,
 .Xr mbr_uid_to_uuid 3 ,
-.Xr DirectoryService 8
+.Xr opendirectoryd 8
index a778aeade6fbb7ff5a2b4aa439028d4f9ac0e04b..9ca8ec9dab5784926da475df257ba8c25e6bff98 100644 (file)
@@ -26,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"
 .\" SUCH DAMAGE.
 .\"
 .\"
-.Dd August 25, 2010
+.Dd October 10, 2011
 .Dt MBR_UID_TO_UUID 3
 .Os "Mac OS X"
 .Sh NAME
 .Dt MBR_UID_TO_UUID 3
 .Os "Mac OS X"
 .Sh NAME
@@ -59,9 +59,8 @@ every user or group can be referenced by a 128 bit uuid.
 Additionally, if the user or group is hosted on a PDC
 or Active Directory server, it will have a 128 bit or larger sid.
 .Pp
 Additionally, if the user or group is hosted on a PDC
 or Active Directory server, it will have a 128 bit or larger sid.
 .Pp
-These routines communicate with the
-.Xr DirectoryService 8
-daemon.
+These routines communicate with
+.Xr openditectoryd 8 .
 .Pp
 .Fn mbr_uid_to_uuid
 takes a uid and looks up the associated user account.
 .Pp
 .Fn mbr_uid_to_uuid
 takes a uid and looks up the associated user account.
@@ -109,23 +108,30 @@ The converted string is terminated with a nul character.
 .Fn mbr_string_to_sid
 converts an external string representation into a sid.
 .Sh RETURN VALUES
 .Fn mbr_string_to_sid
 converts an external string representation into a sid.
 .Sh RETURN VALUES
-These functions return 0 on success, or EIO if communications with the
-.Xr DirectoryService 8
-daemon fails.
-ENOENT is returned if the mapping can not be performed.
+These functions return 0 on success or one of the following error codes on failure:
+.Bl -tag -width Er
+.It Bq Er EIO
+Communication with
+.Xr openditectoryd 8
+failed.
+.It Bq Er ENOENT
+The mapping can not be performed.
+.It Bq Er EAUTH
+Communication with
+.Xr openditectoryd 8
+failed due to an authentication error.
+.It Bq Er EINVAL
+Invalid arguments were provided.
+.It Bq Er ENOMEM
+Insufficient storage space is available.
+.El
 .Pp
 .Fn mbr_gid_to_uuid
 and
 .Fn mbr_uid_to_uuid
 return 0 (success), even if the user/group does not exist.
 .Pp
 .Fn mbr_gid_to_uuid
 and
 .Fn mbr_uid_to_uuid
 return 0 (success), even if the user/group does not exist.
-.Pp
-The 
-.Fn mbr_sid_to_string
-and 
-.Fn mbr_string_to_sid
-functions return 0 on success, or an errno value on failure.
 .Sh SEE ALSO
 .Xr getpwuid 3 ,
 .Xr getgrgid 3 ,
 .Xr mbr_check_membership 3 ,
 .Sh SEE ALSO
 .Xr getpwuid 3 ,
 .Xr getgrgid 3 ,
 .Xr mbr_check_membership 3 ,
-.Xr DirectoryService 8
\ No newline at end of file
+.Xr openditectoryd 8
index b2c980cece19f1c0bf2cd071d1eb3e73d841c8e5..80baf4afa0373c42ea33110f8d40281595100330 100644 (file)
 #include <servers/bootstrap.h>
 #include <libkern/OSByteOrder.h>
 #ifdef DS_AVAILABLE
 #include <servers/bootstrap.h>
 #include <libkern/OSByteOrder.h>
 #ifdef DS_AVAILABLE
-#include "DSmemberdMIG.h"
-#endif
+#include <xpc/xpc.h>
+#include <xpc/private.h>
+#include <opendirectory/odipc.h>
+#include <pthread.h>
 
 
-#ifdef DS_AVAILABLE
-extern mach_port_t _mbr_port;
-extern int _ds_running(void);
+#ifdef __i386__
+/* <rdar://problem/10675978> */
+__attribute__((weak_import))
+xpc_pipe_t xpc_pipe_create(const char *name, uint64_t flags);
+
+__attribute__((weak_import))
+void xpc_pipe_invalidate(xpc_pipe_t pipe);
+
+__attribute__((weak_import))
+int xpc_pipe_routine(xpc_pipe_t pipe, xpc_object_t message, xpc_object_t *reply);
+#endif /* __i386__ */
+#endif /* DS_AVAILABLE */
 
 static const uuid_t _user_compat_prefix = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00};
 static const uuid_t _group_compat_prefix = {0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00};
 
 #define COMPAT_PREFIX_LEN      (sizeof(uuid_t) - sizeof(id_t))
 
 
 static const uuid_t _user_compat_prefix = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00};
 static const uuid_t _group_compat_prefix = {0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00};
 
 #define COMPAT_PREFIX_LEN      (sizeof(uuid_t) - sizeof(id_t))
 
-#define MAX_LOOKUP_ATTEMPTS 10
+#ifdef DS_AVAILABLE
+
+int _si_opendirectory_disabled;
+static xpc_pipe_t __mbr_pipe; /* use accessor */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+__private_extern__ xpc_object_t _od_rpc_call(const char *procname, xpc_object_t payload, xpc_pipe_t (*get_pipe)(bool));
+
 #endif
 
 #endif
 
-uid_t
-audit_token_uid(audit_token_t a)
+#ifdef DS_AVAILABLE
+static void
+_mbr_fork_child(void)
 {
 {
-       /*
-        * This should really call audit_token_to_au32,
-        * but that's in libbsm, not in a Libsystem library.
-        */
-       return (uid_t)a.val[1];
+       if (__mbr_pipe != NULL) {
+               xpc_pipe_invalidate(__mbr_pipe);
+               /* disable release due to 10649340, it will cause a minor leak for each fork without exec */
+               // xpc_release(__mbr_pipe);
+               __mbr_pipe = NULL;
+       }
+       
+       pthread_mutex_unlock(&mutex);
 }
 }
+#endif
 
 #ifdef DS_AVAILABLE
 
 #ifdef DS_AVAILABLE
-static int
-_mbr_MembershipCall(struct kauth_identity_extlookup *req)
+static void
+_mbr_fork_prepare(void)
 {
 {
-       audit_token_t token;
-       kern_return_t status;
-       uint32_t i;
-
-       /* call _ds_running() to look up _mbr_port */
-       _ds_running();
-       if (_mbr_port == MACH_PORT_NULL) return EIO;
-
-       memset(&token, 0, sizeof(audit_token_t));
-
-       status = MIG_SERVER_DIED;
-       for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++)
-       {
-               status = memberdDSmig_MembershipCall(_mbr_port, req, &token);
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1);
-                       _mbr_port = MACH_PORT_NULL;
-                       _ds_running();
-                       status = MIG_SERVER_DIED;
-               }
-       }
-
-       if (status != KERN_SUCCESS) return EIO;
-       if (audit_token_uid(token) != 0) return EAUTH;
-
-       return 0;
+       pthread_mutex_lock(&mutex);
 }
 #endif
 
 #ifdef DS_AVAILABLE
 }
 #endif
 
 #ifdef DS_AVAILABLE
-static int
-_mbr_MapName(char *name, int type, guid_t *uu)
+static void
+_mbr_fork_parent(void)
 {
 {
-       kern_return_t status;
-       audit_token_t token;
-       uint32_t i;
-
-       if (name == NULL) return EINVAL;
-       if (strlen(name) > 255) return EINVAL;
-
-       /* call _ds_running() to look up _mbr_port */
-       _ds_running();
-       if (_mbr_port == MACH_PORT_NULL) return EIO;
-
-       memset(&token, 0, sizeof(audit_token_t));
-
-       status = MIG_SERVER_DIED;
-       for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++)
-       {
-               status = memberdDSmig_MapName(_mbr_port, type, name, uu, &token);
-               if (status == KERN_FAILURE) return ENOENT;
-
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1);
-                       _mbr_port = MACH_PORT_NULL;
-                       _ds_running();
-                       status = MIG_SERVER_DIED;
-               }
-       }
-
-       if (status != KERN_SUCCESS) return EIO;
-       if (audit_token_uid(token) != 0) return EAUTH;
-
-       return 0;
+       pthread_mutex_unlock(&mutex);
 }
 #endif
 
 #ifdef DS_AVAILABLE
 }
 #endif
 
 #ifdef DS_AVAILABLE
-static int
-_mbr_ClearCache()
+XPC_RETURNS_RETAINED
+static xpc_pipe_t
+_mbr_xpc_pipe(bool resetPipe)
 {
 {
-       kern_return_t status;
-       uint32_t i;
+       static dispatch_once_t once;
+       xpc_pipe_t pipe = NULL;
 
 
-       /* call _ds_running() to look up _mbr_port */
-       _ds_running();
-       if (_mbr_port == MACH_PORT_NULL) return EIO;
+#ifdef __i386__
+       if (xpc_pipe_create == NULL) {
+               _si_opendirectory_disabled = 1;
+               return NULL;
+       }
+#endif
 
 
-       status = MIG_SERVER_DIED;
-       for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++)
-       {
-               status = memberdDSmig_ClearCache(_mbr_port);
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1);
-                       _mbr_port = MACH_PORT_NULL;
-                       _ds_running();
-                       status = MIG_SERVER_DIED;
+       dispatch_once(&once, ^(void) {
+               char *rc_xbs;
+               
+               /* if this is a build environment we ignore opendirectoryd */
+               rc_xbs = getenv("RC_XBS");
+               if (rc_xbs != NULL && strcmp(rc_xbs, "YES") == 0) {
+                       _si_opendirectory_disabled = 1;
+                       return;
                }
                }
+               
+               pthread_atfork(_mbr_fork_prepare, _mbr_fork_parent, _mbr_fork_child);
+       });
+       
+       if (_si_opendirectory_disabled == 1) {
+               return NULL;
        }
        }
-
-       if (status != KERN_SUCCESS) return EIO;
-
-       return 0;
+       
+       pthread_mutex_lock(&mutex);
+       if (resetPipe) {
+               xpc_release(__mbr_pipe);
+               __mbr_pipe = NULL;
+       }
+       
+       if (__mbr_pipe == NULL) {
+               if (!issetugid() && getenv("OD_DEBUG_MODE") != NULL) {
+                       __mbr_pipe = xpc_pipe_create(kODMachMembershipPortNameDebug, 0);
+               } else {
+                       __mbr_pipe = xpc_pipe_create(kODMachMembershipPortName, XPC_PIPE_FLAG_PRIVILEGED);
+               }
+       }
+       
+       if (__mbr_pipe != NULL) pipe = xpc_retain(__mbr_pipe);
+       pthread_mutex_unlock(&mutex);
+       
+       return pipe;
 }
 #endif
 
 }
 #endif
 
-#ifdef DS_AVAILABLE
-static int
-_mbr_SetIdentifierTTL(int idType, const void *identifier, size_t identifier_size, unsigned int seconds)
+static bool
+_mbr_od_available(void)
 {
 {
-       kern_return_t status;
-       uint32_t i;
+#if DS_AVAILABLE
+       xpc_pipe_t pipe = _mbr_xpc_pipe(false);
+       if (pipe != NULL) {
+               xpc_release(pipe);
+               return true;
+       }
+#endif
+       return false;
+}
+
+int
+mbr_identifier_translate(int id_type, const void *identifier, size_t identifier_size, int target_type, void **result, int *rec_type)
+{
+#if DS_AVAILABLE
+       xpc_object_t payload, reply;
+#endif
+       id_t tempID;
+       size_t identifier_len;
+       int rc = EIO;
        
        
-       /* call _ds_running() to look up _mbr_port */
-       _ds_running();
-       if (_mbr_port == MACH_PORT_NULL) return EIO;
+       if (identifier == NULL || result == NULL || identifier_size == 0) return EIO;
        
        
-       status = MIG_SERVER_DIED;
-       for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++)
-       {
-               status = memberdDSmig_SetIdentifierTTL(_mbr_port, idType, (identifier_data_t)identifier, identifier_size, seconds);
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1);
-                       _mbr_port = MACH_PORT_NULL;
-                       _ds_running();
-                       status = MIG_SERVER_DIED;
+       if (identifier_size == -1) {
+               identifier_size = strlen(identifier);
+       } else {
+               /* 10898647: For types that are known to be strings, send the smallest necessary amount of data. */
+               switch (id_type) {
+               case ID_TYPE_USERNAME:
+               case ID_TYPE_GROUPNAME:
+               case ID_TYPE_GROUP_NFS:
+               case ID_TYPE_USER_NFS:
+               case ID_TYPE_X509_DN:
+               case ID_TYPE_KERBEROS:
+               case ID_TYPE_NAME:
+                       identifier_len = strlen(identifier);
+                       if (identifier_size > identifier_len) {
+                               identifier_size = identifier_len;
+                       }
+                       break;
+               }
+       }
+
+       switch (target_type) {
+               case ID_TYPE_GID:
+               case ID_TYPE_UID:
+               case ID_TYPE_UID_OR_GID:
+                       /* shortcut UUIDs using compatibilty prefixes */
+                       if (id_type == ID_TYPE_UUID) {
+                               const uint8_t *uu = identifier;
+                               
+                               if (identifier_size != sizeof(uuid_t)) return EINVAL;
+                               
+                               if (memcmp(uu, _user_compat_prefix, COMPAT_PREFIX_LEN) == 0) {
+                                       id_t *tempRes = malloc(sizeof(*tempRes));
+                                       memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID));
+                                       (*tempRes) = ntohl(tempID);
+                                       (*result) = tempRes;
+                                       if (rec_type != NULL) {
+                                               (*rec_type) = MBR_REC_TYPE_USER;
+                                       }
+                                       return 0;
+                               } else if (memcmp(uu, _group_compat_prefix, COMPAT_PREFIX_LEN) == 0) {
+                                       id_t *tempRes = malloc(sizeof(*tempRes));
+                                       memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID));
+                                       (*tempRes) = ntohl(tempID);
+                                       (*result) = tempRes;
+                                       if (rec_type != NULL) {
+                                               (*rec_type) = MBR_REC_TYPE_GROUP;
+                                       }
+                                       return 0;
+                               }
+                       }
+                       break;
+                       
+               case ID_TYPE_UUID:
+                       /* if this is a UID or GID translation, we shortcut UID/GID 0 */
+                       /* or if no OD, we return compatibility UUIDs */
+                       switch (id_type) {
+                               case ID_TYPE_UID:
+                                       if (identifier_size != sizeof(tempID)) return EINVAL;
+                                       
+                                       tempID = *((id_t *) identifier);
+                                       if ((tempID == 0) || (_mbr_od_available() == false)) {
+                                               uint8_t *tempUU = malloc(sizeof(uuid_t));
+                                               uuid_copy(tempUU, _user_compat_prefix);
+                                               *((id_t *) &tempUU[COMPAT_PREFIX_LEN]) = htonl(tempID);
+                                               (*result) = tempUU;
+                                               if (rec_type != NULL) {
+                                                       (*rec_type) = MBR_REC_TYPE_USER;
+                                               }
+                                               return 0;
+                                       }
+                                       break;
+                                       
+                               case ID_TYPE_GID:
+                                       if (identifier_size != sizeof(tempID)) return EINVAL;
+                                       
+                                       tempID = *((id_t *) identifier);
+                                       if ((tempID == 0) || (_mbr_od_available() == false)) {
+                                               uint8_t *tempUU = malloc(sizeof(uuid_t));
+                                               uuid_copy(tempUU, _group_compat_prefix);
+                                               *((id_t *) &tempUU[COMPAT_PREFIX_LEN]) = htonl(tempID);
+                                               (*result) = tempUU;
+                                               if (rec_type != NULL) {
+                                                       (*rec_type) = MBR_REC_TYPE_GROUP;
+                                               }
+                                               return 0;
+                                       }
+                                       break;
+                       }
+                       break;
+       }
+       
+#if DS_AVAILABLE
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return EIO;
+       
+       xpc_dictionary_set_int64(payload, "requesting", target_type);
+       xpc_dictionary_set_int64(payload, "type", id_type);
+       xpc_dictionary_set_data(payload, "identifier", identifier, identifier_size);
+       
+       reply = _od_rpc_call("mbr_identifier_translate", payload, _mbr_xpc_pipe);
+       if (reply != NULL) {
+               const void *reply_id;
+               size_t idLen;
+               
+               rc = (int) xpc_dictionary_get_int64(reply, "error");
+               if (rc == 0) {
+                       reply_id = xpc_dictionary_get_data(reply, "identifier", &idLen);
+                       if (reply_id != NULL) {
+                               char *identifier = malloc(idLen);
+                               
+                               memcpy(identifier, reply_id, idLen); // should already be NULL terminated, etc.
+                               (*result) = identifier;
+                               
+                               if (rec_type != NULL) {
+                                       (*rec_type) = (int) xpc_dictionary_get_int64(reply, "rectype");
+                               }
+                       } else {
+                               (*result) = NULL;
+                               rc = ENOENT;
+                       }
                }
                }
+               
+               xpc_release(reply);
        }
        
        }
        
-       if (status != KERN_SUCCESS) return EIO;
+       xpc_release(payload);
+#endif
        
        
-       return 0;
+       return rc;
 }
 }
-#endif
 
 int
 mbr_uid_to_uuid(uid_t id, uuid_t uu)
 
 int
 mbr_uid_to_uuid(uid_t id, uuid_t uu)
@@ -201,80 +315,38 @@ mbr_gid_to_uuid(gid_t id, uuid_t uu)
 int
 mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type)
 {
 int
 mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type)
 {
-#ifdef DS_AVAILABLE
-       struct kauth_identity_extlookup request;
-       int status;
-       id_t tempID;
-
-       if (id == NULL) return EIO;
-       if (id_type == NULL) return EIO;
-
-       if (!memcmp(uu, _user_compat_prefix, COMPAT_PREFIX_LEN))
-       {
-               memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID));
-               *id = ntohl(tempID);
-               *id_type = ID_TYPE_UID;
-               return 0;
-       }
-       else if (!memcmp(uu, _group_compat_prefix, COMPAT_PREFIX_LEN))
-       {
-               memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID));
-               *id = ntohl(tempID);
-               *id_type = ID_TYPE_GID;
-               return 0;
-       }
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_UID | KAUTH_EXTLOOKUP_WANT_GID;
-       memcpy(&request.el_uguid, uu, sizeof(guid_t));
-       memcpy(&request.el_gguid, uu, sizeof(guid_t));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UID) != 0)
-       {
-               *id = request.el_uid;
-               *id_type = ID_TYPE_UID;
-       }
-       else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GID) != 0)
-       {
-               *id = request.el_gid;
-               *id_type = ID_TYPE_GID;
-       }
-       else
-       {
-               return ENOENT;
+       id_t *result;
+       int local_type;
+       int rc;
+       
+       rc = mbr_identifier_translate(ID_TYPE_UUID, uu, sizeof(uuid_t), ID_TYPE_UID_OR_GID, (void **) &result, &local_type);
+       if (rc == 0) {
+               switch (local_type) {
+                       case MBR_REC_TYPE_GROUP:
+                               (*id_type) = ID_TYPE_GID;
+                               break;
+                               
+                       case MBR_REC_TYPE_USER:
+                               (*id_type) = ID_TYPE_UID;
+                               break;
+                               
+                       default:
+                               (*id_type) = -1;
+                               break;
+               }
+               
+               (*id) = (*result);
+               free(result);
        }
        }
-
-       return 0;
-#else
-       return EIO;
-#endif
+       
+       return rc;
 }
 
 int
 mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu)
 {
 #ifdef DS_AVAILABLE
 }
 
 int
 mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu)
 {
 #ifdef DS_AVAILABLE
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_GSID | KAUTH_EXTLOOKUP_WANT_GGUID | KAUTH_EXTLOOKUP_VALID_USID | KAUTH_EXTLOOKUP_WANT_UGUID;
-       memset(&request.el_gsid, 0, sizeof(ntsid_t));
-       memcpy(&request.el_gsid, sid, KAUTH_NTSID_SIZE(sid));
-       memset(&request.el_usid, 0, sizeof(ntsid_t));
-       memcpy(&request.el_usid, sid, KAUTH_NTSID_SIZE(sid));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GGUID) != 0) memcpy(uu, &request.el_gguid, sizeof(guid_t));
-       else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_UGUID) != 0) memcpy(uu, &request.el_uguid, sizeof(guid_t));
-       else return ENOENT;
-
-       return 0;
+       return mbr_identifier_to_uuid(ID_TYPE_SID, sid, sizeof(*sid), uu);
 #else
        return EIO;
 #endif
 #else
        return EIO;
 #endif
@@ -283,136 +355,49 @@ mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu)
 int
 mbr_identifier_to_uuid(int id_type, const void *identifier, size_t identifier_size, uuid_t uu)
 {
 int
 mbr_identifier_to_uuid(int id_type, const void *identifier, size_t identifier_size, uuid_t uu)
 {
-#ifdef DS_AVAILABLE
-       kern_return_t status;
-       audit_token_t token;
-       vm_offset_t ool = 0;
-       mach_msg_type_number_t oolCnt = 0;
-       uint32_t i;
-       id_t tempID;
-#if __BIG_ENDIAN__
-       id_t newID;
-#endif
-
-       if (identifier == NULL) return EINVAL;
-       if (identifier_size == 0) return EINVAL;
-       else if (identifier_size == -1) identifier_size = strlen((char*) identifier) + 1;
-
-       /* call _ds_running() to look up _mbr_port */
-       _ds_running();
-
-       /* if this is a UID or GID translation, we shortcut UID/GID 0 */
-       /* if no DS, we return compatibility UUIDs */
-       switch (id_type)
-       {
-               case ID_TYPE_UID:
-               {
-                       if (identifier_size != sizeof(tempID)) return EINVAL;
-
-                       tempID = *((id_t *) identifier);
-                       if ((tempID == 0) || (_mbr_port == MACH_PORT_NULL))
-                       {
-                               uuid_copy(uu, _user_compat_prefix);
-                               *((id_t *) &uu[COMPAT_PREFIX_LEN]) = htonl(tempID);
-                               return 0;
-                       }
-                       break;
-               }
-               case ID_TYPE_GID:
-               {
-                       if (identifier_size != sizeof(tempID)) return EINVAL;
-
-                       tempID = *((id_t *) identifier);
-                       if ((tempID == 0) || (_mbr_port == MACH_PORT_NULL))
-                       {
-                               uuid_copy(uu, _group_compat_prefix);
-                               *((id_t *) &uu[COMPAT_PREFIX_LEN]) = htonl(tempID);
-                               return 0;
-                       }
-                       break;
-               }
-       }
-
-       if (_mbr_port == MACH_PORT_NULL) return EIO;
-
-       memset(&token, 0, sizeof(audit_token_t));
-
-#if __BIG_ENDIAN__
-       switch (id_type)
-       {
-               case ID_TYPE_UID:
-               case ID_TYPE_GID:
-                       if (identifier_size < sizeof(id_t)) return EINVAL;
-                       newID = OSSwapInt32(*((id_t *) identifier));
-                       identifier = &newID;
-                       break;
-       }
-#endif
-
-       if (identifier_size > MAX_MIG_INLINE_DATA)
-       {
-               if (vm_read(mach_task_self(), (vm_offset_t) identifier, identifier_size, &ool, &oolCnt) != 0) return ENOMEM;
-               identifier = NULL;
-               identifier_size = 0;
-       }
-
-       status = MIG_SERVER_DIED;
-       for (i = 0; (_mbr_port != MACH_PORT_NULL) && (status == MIG_SERVER_DIED) && (i < MAX_LOOKUP_ATTEMPTS); i++)
-       {
-               status = memberdDSmig_MapIdentifier(_mbr_port, id_type, (identifier_data_t) identifier, identifier_size, ool, oolCnt, (guid_t *)uu, &token);
-               if (status == KERN_FAILURE) return ENOENT;
-
-               if (status == MACH_SEND_INVALID_DEST)
-               {
-                       if (ool != 0) vm_deallocate(mach_task_self(), ool, oolCnt);
-
-                       mach_port_mod_refs(mach_task_self(), _mbr_port, MACH_PORT_RIGHT_SEND, -1);
-                       _mbr_port = MACH_PORT_NULL;
-                       _ds_running();
-                       status = MIG_SERVER_DIED;
-               }
+       uint8_t *result;
+       int rc;
+       
+       rc = mbr_identifier_translate(id_type, identifier, identifier_size, ID_TYPE_UUID, (void **) &result, NULL);
+       if (rc == 0) {
+               uuid_copy(uu, result);
+               free(result);
        }
        }
-
-       if (status != KERN_SUCCESS) return EIO;
-       if (audit_token_uid(token) != 0) return EAUTH;
-
-       return 0;
-#else
-       return EIO;
-#endif
+       
+       return rc;
 }
 
 int
 mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type)
 {
 #ifdef DS_AVAILABLE
 }
 
 int
 mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type)
 {
 #ifdef DS_AVAILABLE
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_USID | KAUTH_EXTLOOKUP_WANT_GSID;
-       memcpy(&request.el_uguid, uu, sizeof(guid_t));
-       memcpy(&request.el_gguid, uu, sizeof(guid_t));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_USID) != 0)
-       {
-               *id_type = SID_TYPE_USER;
-               memcpy(sid, &request.el_usid, sizeof(nt_sid_t));
-       }
-       else if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_GSID) != 0)
-       {
-               *id_type = SID_TYPE_GROUP;
-               memcpy(sid, &request.el_gsid, sizeof(nt_sid_t));
-       }
-       else
-       {
-               return ENOENT;
+       void *result;
+       int local_type;
+       int rc;
+       
+       rc = mbr_identifier_translate(ID_TYPE_UUID, uu, sizeof(uuid_t), ID_TYPE_SID, &result, &local_type);
+       if (rc == 0) {
+               memcpy(sid, result, sizeof(nt_sid_t));
+               if (id_type != NULL) {
+                       /* remap ID types */
+                       switch (local_type) {
+                               case MBR_REC_TYPE_USER:
+                                       (*id_type) = SID_TYPE_USER;
+                                       break;
+
+                               case MBR_REC_TYPE_GROUP:
+                                       (*id_type) = SID_TYPE_GROUP;
+                                       break;
+
+                               default:
+                                       break;
+                       }
+               }
+               
+               free(result);
        }
        }
-
-       return 0;
+       
+       return rc;
 #else
        return EIO;
 #endif
 #else
        return EIO;
 #endif
@@ -438,44 +423,66 @@ mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid)
 int
 mbr_check_membership(const uuid_t user, const uuid_t group, int *ismember)
 {
 int
 mbr_check_membership(const uuid_t user, const uuid_t group, int *ismember)
 {
-#ifdef DS_AVAILABLE
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP;
-       memcpy(&request.el_uguid, user, sizeof(guid_t));
-       memcpy(&request.el_gguid, group, sizeof(guid_t));
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT;
-
-       *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0);
-       return 0;
-#else
-       return EIO;
-#endif
+       return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 0, ismember);
 }
 
 int
 mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember)
 {
 }
 
 int
 mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember)
 {
-#ifdef DS_AVAILABLE
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GGUID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP | (1<<15);
-       memcpy(&request.el_uguid, user, sizeof(guid_t));
-       memcpy(&request.el_gguid, group, sizeof(guid_t));
+       return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 1, ismember);
+}
 
 
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT;
+int
+mbr_check_membership_ext(int userid_type, const void *userid, size_t userid_size, int groupid_type, const void *groupid, int refresh, int *isMember)
+{
+#ifdef DS_AVAILABLE
+       xpc_object_t payload, reply;
+       int rc = 0;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return ENOMEM;
 
 
-       *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0);
-       return 0;
+       xpc_dictionary_set_int64(payload, "user_idtype", userid_type);
+       xpc_dictionary_set_data(payload, "user_id", userid, userid_size);
+       xpc_dictionary_set_int64(payload, "group_idtype", groupid_type);
+       
+       switch (groupid_type) {
+               case ID_TYPE_GROUPNAME:
+               case ID_TYPE_GROUP_NFS:
+                       xpc_dictionary_set_data(payload, "group_id", groupid, strlen(groupid));
+                       break;
+                       
+               case ID_TYPE_GID:
+                       xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(id_t));
+                       break;
+                       
+               case ID_TYPE_SID:
+                       xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(nt_sid_t));
+                       break;
+                       
+               case ID_TYPE_UUID:
+                       xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(uuid_t));
+                       break;
+                       
+               default:
+                       rc = EINVAL;
+                       break;
+       }
+       
+       if (rc == 0) {
+               reply = _od_rpc_call("mbr_check_membership", payload, _mbr_xpc_pipe);
+               if (reply != NULL) {
+                       rc = (int) xpc_dictionary_get_int64(reply, "error");
+                       (*isMember) = xpc_dictionary_get_bool(reply, "ismember");
+                       xpc_release(reply);
+               } else {
+                       rc = EIO;
+               }
+       }
+       
+       xpc_release(payload);
+       
+       return rc;
 #else
        return EIO;
 #endif
 #else
        return EIO;
 #endif
@@ -484,31 +491,15 @@ mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember)
 int
 mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember)
 {
 int
 mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember)
 {
-#ifdef DS_AVAILABLE
-       struct kauth_identity_extlookup request;
-       int status;
-
-       request.el_seqno = 1;
-       request.el_flags = KAUTH_EXTLOOKUP_VALID_UGUID | KAUTH_EXTLOOKUP_VALID_GID | KAUTH_EXTLOOKUP_WANT_MEMBERSHIP;
-       memcpy(&request.el_uguid, user, sizeof(guid_t));
-       request.el_gid = group;
-
-       status = _mbr_MembershipCall(&request);
-       if (status != 0) return status;
-       if ((request.el_flags & KAUTH_EXTLOOKUP_VALID_MEMBERSHIP) == 0) return ENOENT;
-
-       *ismember = ((request.el_flags & KAUTH_EXTLOOKUP_ISMEMBER) != 0);
-       return 0;
-#else
-       return EIO;
-#endif
+       return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_GID, &group, 0, ismember);
 }
 
 int
 mbr_reset_cache()
 {
 #ifdef DS_AVAILABLE
 }
 
 int
 mbr_reset_cache()
 {
 #ifdef DS_AVAILABLE
-       return _mbr_ClearCache();
+       _od_rpc_call("mbr_cache_flush", NULL, _mbr_xpc_pipe);
+       return 0;
 #else
        return EIO;
 #endif
 #else
        return EIO;
 #endif
@@ -517,54 +508,42 @@ mbr_reset_cache()
 int
 mbr_user_name_to_uuid(const char *name, uuid_t uu)
 {
 int
 mbr_user_name_to_uuid(const char *name, uuid_t uu)
 {
-#ifdef DS_AVAILABLE
-       return _mbr_MapName((char *)name, 1, (guid_t *)uu);
-#else
-       return EIO;
-#endif
+       return mbr_identifier_to_uuid(ID_TYPE_USERNAME, name, -1, uu);
 }
 
 int
 mbr_group_name_to_uuid(const char *name, uuid_t uu)
 {
 }
 
 int
 mbr_group_name_to_uuid(const char *name, uuid_t uu)
 {
-#ifdef DS_AVAILABLE
-       return _mbr_MapName((char *)name, 0, (guid_t *)uu);
-#else
-       return EIO;
-#endif
+       return mbr_identifier_to_uuid(ID_TYPE_GROUPNAME, name, -1, uu);
 }
 
 int
 mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember)
 {
 #ifdef DS_AVAILABLE
 }
 
 int
 mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember)
 {
 #ifdef DS_AVAILABLE
-       char *prefix = "com.apple.access_";
-       char *all_services = "com.apple.access_all_services";
-       char groupName[256];
-       uuid_t group_uu;
-       int result;
-
-       if (servicename == NULL) return EINVAL;
-       if (strlen(servicename) > 255 - strlen(prefix)) return EINVAL;
-
-       /* start by checking "all services" */
-       result = mbr_group_name_to_uuid(all_services, group_uu);
-
-       if (result == EAUTH) return result;
+       xpc_object_t payload, reply;
+       int result = EIO;
 
 
-       if (result == ENOENT)
-       {
-               /* all_services group didn't exist, check individual group */
-               memcpy(groupName, prefix, strlen(prefix));
-               strcpy(groupName + strlen(prefix), servicename);
-               result = mbr_group_name_to_uuid(groupName, group_uu);
-       }
-
-       if (result == 0)
-       {
-               /* refreshes are driven at a higher level, just check membership */
-               result = mbr_check_membership(user, group_uu, ismember);
+       if (ismember == NULL || servicename == NULL) return EINVAL;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return EIO;
+       
+       xpc_dictionary_set_data(payload, "user_id", user, sizeof(uuid_t));
+       xpc_dictionary_set_int64(payload, "user_idtype", ID_TYPE_UUID);
+       xpc_dictionary_set_string(payload, "service", servicename);
+       
+       reply = _od_rpc_call("mbr_check_service_membership", payload, _mbr_xpc_pipe);
+       if (reply != NULL) {
+               result = (int) xpc_dictionary_get_int64(reply, "error");
+               (*ismember) = xpc_dictionary_get_bool(reply, "ismember");
+               
+               xpc_release(reply);
+       } else {
+               (*ismember) = 0;
        }
        }
+       
+       xpc_release(payload);
 
        return result;
 #else
 
        return result;
 #else
@@ -674,114 +653,47 @@ mbr_string_to_sid(const char *string, nt_sid_t *sid)
 #endif
 }
 
 #endif
 }
 
-#ifdef DS_AVAILABLE
-static void
-ConvertBytesToHex(char **string, char **data, int numBytes)
-{
-       int i;
-
-       for (i=0; i < numBytes; i++)
-       {
-               unsigned char hi = ((**data) >> 4) & 0xf;
-               unsigned char low = (**data) & 0xf;
-               if (hi < 10)
-                       **string = '0' + hi;
-               else
-                       **string = 'A' + hi - 10;
-
-               (*string)++;
-
-               if (low < 10)
-                       **string = '0' + low;
-               else
-                       **string = 'A' + low - 10;
-
-               (*string)++;
-               (*data)++;
-       }
-}
-#endif
-
 int
 mbr_uuid_to_string(const uuid_t uu, char *string)
 {
 int
 mbr_uuid_to_string(const uuid_t uu, char *string)
 {
-#ifdef DS_AVAILABLE
-       char *guid = (char*)uu;
-       char *strPtr = string;
-       ConvertBytesToHex(&strPtr, &guid, 4);
-       *strPtr = '-'; strPtr++;
-       ConvertBytesToHex(&strPtr, &guid, 2);
-       *strPtr = '-'; strPtr++;
-       ConvertBytesToHex(&strPtr, &guid, 2);
-       *strPtr = '-'; strPtr++;
-       ConvertBytesToHex(&strPtr, &guid, 2);
-       *strPtr = '-'; strPtr++;
-       ConvertBytesToHex(&strPtr, &guid, 6);
-       *strPtr = '\0';
-
+       uuid_unparse_upper(uu, string);
+       
        return 0;
        return 0;
-#else
-       return EIO;
-#endif
 }
 
 int
 mbr_string_to_uuid(const char *string, uuid_t uu)
 {
 }
 
 int
 mbr_string_to_uuid(const char *string, uuid_t uu)
 {
-#ifdef DS_AVAILABLE
-       short dataIndex = 0;
-       int isFirstNibble = 1;
-
-       if (string == NULL) return EINVAL;
-       if (strlen(string) > MBR_UU_STRING_SIZE) return EINVAL;
-
-       while (*string != '\0' && dataIndex < 16)
-       {
-               char nibble;
-
-               if (*string >= '0' && *string <= '9')
-                       nibble = *string - '0';
-               else if (*string >= 'A' && *string <= 'F')
-                       nibble = *string - 'A' + 10;
-               else if (*string >= 'a' && *string <= 'f')
-                       nibble = *string - 'a' + 10;
-               else
-               {
-                       if (*string != '-')
-                               return EINVAL;
-                       string++;
-                       continue;
-               }
-
-               if (isFirstNibble)
-               {
-                       uu[dataIndex] = nibble << 4;
-                       isFirstNibble = 0;
-               }
-               else
-               {
-                       uu[dataIndex] |= nibble;
-                       dataIndex++;
-                       isFirstNibble = 1;
-               }
-
-               string++;
-       }
-
-       if (dataIndex != 16) return EINVAL;
-
-       return 0;
-#else
-       return EIO;
-#endif
+       return uuid_parse(string, uu);
 }
 
 int 
 mbr_set_identifier_ttl(int id_type, const void *identifier, size_t identifier_size, unsigned int seconds)
 {
 #ifdef DS_AVAILABLE
 }
 
 int 
 mbr_set_identifier_ttl(int id_type, const void *identifier, size_t identifier_size, unsigned int seconds)
 {
 #ifdef DS_AVAILABLE
-       _mbr_SetIdentifierTTL(id_type, identifier, identifier_size, seconds);
-       return 0;
+       xpc_object_t payload, reply;
+       int rc = 0;
+       
+       payload = xpc_dictionary_create(NULL, NULL, 0);
+       if (payload == NULL) return ENOMEM;
+       
+       xpc_dictionary_set_int64(payload, "type", id_type);
+       xpc_dictionary_set_data(payload, "identifier", identifier, identifier_size);
+       xpc_dictionary_set_int64(payload, "ttl", seconds);
+       
+       if (rc == 0) {
+               reply = _od_rpc_call("mbr_set_identifier_ttl", payload, _mbr_xpc_pipe);
+               if (reply != NULL) {
+                       rc = (int) xpc_dictionary_get_int64(reply, "error");
+                       xpc_release(reply);
+               } else {
+                       rc = EIO;
+               }
+       }
+       
+       xpc_release(payload);
+       
+       return rc;
 #else
        return EIO;
 #endif
 #else
        return EIO;
 #endif
index ea724474f43625fb66fc8ac30ec45676872dfdca..193f8dd5561128b9e394017564ed40f89400648b 100644 (file)
 */
 #define ID_TYPE_GROUPNAME              5
 
 */
 #define ID_TYPE_GROUPNAME              5
 
+/*!
+       @defined        ID_TYPE_UUID
+       @abstract       is of type uuid_t
+       @discussion     is of type uuid_t
+*/
+#define ID_TYPE_UUID                   6
+
+/*!
+    @defined    ID_TYPE_GROUP_NFS
+    @abstract   is a NULL terminated UTF8 string
+    @discussion is a NULL terminated UTF8 string
+*/
+#define ID_TYPE_GROUP_NFS      7
+
+/*!
+    @defined    ID_TYPE_USER_NFS
+    @abstract   is a NULL terminated UTF8 string
+    @discussion is a NULL terminated UTF8 string
+*/
+#define ID_TYPE_USER_NFS               8
+
 /*!
        @defined    ID_TYPE_GSS_EXPORT_NAME
        @abstract       is a gss exported name
 /*!
        @defined    ID_TYPE_GSS_EXPORT_NAME
        @abstract       is a gss exported name
index 83abd35b699c8b8b6fa3ee4e3ec3a4d688a8f27c..ae5406690c8a08fbaa486e2e5f5ac7f40816a1ad 100644 (file)
 #define SID_TYPE_USER 0
 #define SID_TYPE_GROUP 1
 
 #define SID_TYPE_USER 0
 #define SID_TYPE_GROUP 1
 
+#define MBR_REC_TYPE_USER 1
+#define MBR_REC_TYPE_GROUP 2
+
+/* only supported by mbr_identifier_translate for target type */
+#define ID_TYPE_UID_OR_GID 30
+#define ID_TYPE_NAME 31
+
 __BEGIN_DECLS
 
 int mbr_reset_cache();
 __BEGIN_DECLS
 
 int mbr_reset_cache();
@@ -39,11 +46,24 @@ int mbr_user_name_to_uuid(const char *name, uuid_t uu);
 int mbr_group_name_to_uuid(const char *name, uuid_t uu);
 int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember);
 int mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember);
 int mbr_group_name_to_uuid(const char *name, uuid_t uu);
 int mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember);
 int mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember);
-int mbr_uuid_to_string(const uuid_t uu, char *string);
-int mbr_string_to_uuid(const char *string, uuid_t uu);
+
+/* mbr_uuid_to_string should use uuid_unparse from uuid.h */
+int mbr_uuid_to_string(const uuid_t uu, char *string) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_8, __IPHONE_NA, __IPHONE_NA);
+
+/* mbr_string_to_uuid should use uuid_parse from uuid.h */
+int mbr_string_to_uuid(const char *string, uuid_t uu) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_4, __MAC_10_8, __IPHONE_NA, __IPHONE_NA);
+
 int mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type);
 int mbr_set_identifier_ttl(int id_type, const void *identifier, size_t identifier_size, unsigned int seconds);
 
 int mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type);
 int mbr_set_identifier_ttl(int id_type, const void *identifier, size_t identifier_size, unsigned int seconds);
 
+/* new SPI to allow translation from any-to-any type, pass ID_TYPE_UID_OR_GID when translating to a UID */
+int mbr_identifier_translate(int id_type, const void *identifier, size_t identifier_size, int target_type, void **result, int *rec_type);
+
+/* 
+ * groupid_type does not support ID_TYPE_GSS_EXPORT_NAME
+ */
+int mbr_check_membership_ext(int userid_type, const void *userid, size_t userid_size, int groupid_type, const void *groupid, int refresh, int *isMember);
+
 __END_DECLS
 
 #endif /* !_MEMBERSHIPPRIV_H_ */
 __END_DECLS
 
 #endif /* !_MEMBERSHIPPRIV_H_ */
index 75a44aa4dd2595ae344d56763dc11d9094910b85..d1b6522e19c0b14ecfb3050ed152492eec2c24c9 100644 (file)
@@ -119,8 +119,6 @@ clntraw_create(prog, vers)
 {
        register struct clntraw_private *clp = clntraw_private;
        struct rpc_msg call_msg;
 {
        register struct clntraw_private *clp = clntraw_private;
        struct rpc_msg call_msg;
-       XDR *xdrs = &clp->xdr_stream;
-       CLIENT *client = &clp->client_object;
 
        if (clp == 0) {
                clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
 
        if (clp == 0) {
                clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
@@ -128,6 +126,8 @@ clntraw_create(prog, vers)
                        return (0);
                clntraw_private = clp;
        }
                        return (0);
                clntraw_private = clp;
        }
+       XDR *xdrs = &clp->xdr_stream;
+       CLIENT *client = &clp->client_object;
        /*
         * pre-serialize the staic part of the call msg and stash it away
         */
        /*
         * pre-serialize the staic part of the call msg and stash it away
         */
index 0299d1d2772d90fee097d1fcacfce9ec1aaf0b9c..64532bd4059bdc1fcb7de38273c76f16809d9614 100644 (file)
@@ -260,7 +260,7 @@ rejected(rjct_stat, error)
 
        switch (rjct_stat) {
 
 
        switch (rjct_stat) {
 
-       case RPC_VERSMISMATCH:
+       case RPC_MISMATCH:
                error->re_status = RPC_VERSMISMATCH;
                return;
 
                error->re_status = RPC_VERSMISMATCH;
                return;
 
index 4157e3fc39a691a42da72761245af6c047460e0b..9cae64335693b67ee96f9e213bc24ea1b37fbc50 100755 (executable)
@@ -23,8 +23,10 @@ InstallHeaders /usr/include \
        gen.subproj/ifaddrs.h \
        lookup.subproj/aliasdb.h \
        lookup.subproj/bootparams.h \
        gen.subproj/ifaddrs.h \
        lookup.subproj/aliasdb.h \
        lookup.subproj/bootparams.h \
+       lookup.subproj/grp.h \
        lookup.subproj/netdb.h \
        lookup.subproj/printerdb.h \
        lookup.subproj/netdb.h \
        lookup.subproj/printerdb.h \
+       lookup.subproj/pwd.h \
        membership.subproj/membership.h \
        membership.subproj/ntsid.h
 
        membership.subproj/membership.h \
        membership.subproj/ntsid.h
 
@@ -206,6 +208,9 @@ LinkManPages mbr_uid_to_uuid.3 \
        mbr_gid_to_uuid.3 mbr_sid_to_uuid.3 mbr_uuid_to_id.3 mbr_uuid_to_sid.3 \
        mbr_sid_to_string.3 mbr_string_to_sid.3
 
        mbr_gid_to_uuid.3 mbr_sid_to_uuid.3 mbr_uuid_to_id.3 mbr_uuid_to_sid.3 \
        mbr_sid_to_string.3 mbr_string_to_sid.3
 
+LinkManPages mbr_check_membership.3 \
+       mbr_check_service_membership.3
+
 LinkManPages getrpcent.3 \
        getrpcbyname.3 getrpcbynumber.3 endrpcent.3 setrpcent.3
 
 LinkManPages getrpcent.3 \
        getrpcbyname.3 getrpcbynumber.3 endrpcent.3 setrpcent.3