/*
- * 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_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>
 #include <errno.h>
 #include <arpa/inet.h>
 #include <sys/stat.h>
+#include <pthread.h>
 #include <ils.h>
-#include "kvbuf.h"
 #include <pwd.h>
 #include <grp.h>
 #include <fstab.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 "DSlibinfoMIG.h"
-#include "DSmemberdMIG.h"
+#include <opendirectory/DSlibinfoMIG_types.h>
 #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 int _si_opendirectory_disabled;
 
 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
-_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;
-       _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
        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.
         */
-       return (uid_t)a.val[1];
+       xpc_dictionary_get_audit_token(reply, &token);
+       
+       return ((uid_t) token.val[1] == 0);
 }
 
 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;
                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);
        }
 }
 
-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;
-       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 *
-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;
+       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;
 }
 
-/*
- * 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 
        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 *
-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 (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 *
-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 (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 *
-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;
-       uint32_t d, k, kcount;
-       char *empty[1];
+       si_item_t *item;
 
        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 *
-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;
-       char *empty[1];
-       uint32_t d, k, kcount;
+       si_item_t *item;
 
        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 *
-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;
-       uint32_t d, k, kcount;
-       char *empty[1];
+       si_item_t *item;
 
        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 *
-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;
-       uint32_t d, k, kcount;
-       char *empty[1];
+       si_item_t *item;
 
        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 *
-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;
-       uint32_t d, k, kcount;
-       char *file;
 
        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 *
-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;
-       if (in == NULL) return NULL;
+       if (reply == 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);
+       
        free(cmac);
+       
        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;
-       if (in == NULL) return NULL;
+       if (reply == 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;
 }
 
-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;
 }
 
-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 *
-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;
 
-       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 *
-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 *
-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 *
-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 int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        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)
 {
-       static int proc = -1;
        unsigned char f1, f2, f3;
        char val[64];
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
 
+       if (!_od_running()) return NULL;
+       
        f1 = addr & 0xff;
        addr >>= 8;
        f2 = addr & 0xff;
        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)
 {
-       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 int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
        struct servent *s;
 
+       if (!_od_running()) return NULL;
        if (name == NULL) name = "";
        if (proto == NULL) proto = "";
 
                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)
 {
-       static int proc = -1;
-       uint16_t sport;
-       char val[16];
-       kvbuf_t *request;
+       xpc_object_t payload;
        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)
 {
-       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 int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        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)
 {
-       static int proc = -1;
-       char val[16];
-       kvbuf_t *request;
+       xpc_object_t payload;
        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)
 {
-       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 int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        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)
 {
-       static int proc = -1;
-       char val[16];
-       kvbuf_t *request;
+       xpc_object_t payload;
        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)
 {
-       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 int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        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)
 {
-       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 *
        uint32_t i;
        struct fstab *f;
 
+       if (!_od_running()) return NULL;
        if (name == NULL) return NULL;
 
        list = ds_fs_all(si);
 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;
 
-       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)
 {
-       static int proc = -1;
-       kvbuf_t *request;
+       xpc_object_t payload;
        si_item_t *item;
        char *cmac;
+       
+       if (!_od_running()) 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);
-       kvbuf_free(request);
+       xpc_release(payload);
+       
        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 =
        {
-               .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_byuuid = &ds_user_byuuid,
                .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_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,
                        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;
                }
 
                        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));
                }
 
 
 #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))
 
-#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
 
-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
-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
-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
-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
 
-#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_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
-       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
 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
-       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
 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)
 {
-#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
 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
-       return _mbr_ClearCache();
+       _od_rpc_call("mbr_cache_flush", NULL, _mbr_xpc_pipe);
+       return 0;
 #else
        return EIO;
 #endif
 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)
 {
-#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
-       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
 #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)
 {
-#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;
-#else
-       return EIO;
-#endif
 }
 
 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
-       _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