]> git.saurik.com Git - apple/libinfo.git/blobdiff - lookup.subproj/lu_host_async.c
Libinfo-278.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_host_async.c
index 6b5047133024b67331d85985a02a8ae7b7edbe76..14a0eca0d8dca56c1979d49277d915c1cd63ff2f 100644 (file)
  */
 
 #include <netdb.h>
-/* async gethostbyXXX function prototypes */
 #include <netdb_async.h>
 #include <pthread.h>
 #include <stdlib.h>
 #include <mach/mach.h>
-#include <netinfo/_lu_types.h>
-#include <netinfo/lookup.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <ifaddrs.h>
 #include <net/if.h>
-#include <libkern/OSByteOrder.h>
+#include <errno.h>
 
 #include "lu_host.h"
 #include "lu_utils.h"
 
-extern mach_port_t _lu_port;
-extern int _lu_running(void);
+#define IPV6_ADDR_LEN 16
+#define IPV4_ADDR_LEN 4
 
-extern int h_errno;
-
-#define msgh_request_port msgh_remote_port
-#define msgh_reply_port msgh_local_port
-
-
-typedef union
+typedef struct
 {
-       gethostbyaddr_async_callback hostAddr;
-       gethostbyname_async_callback hostName;
-       getipnodebyaddr_async_callback nodeAddr;
-       getipnodebyname_async_callback nodeName;
-} a_request_callout_t;
-
-typedef struct a_requests
-{
-       struct a_requests *next;
-       int retry;
-       struct
-       {
-               int proc;
-               ooline_data data;
-               unsigned int dataLen;
-               int want;
-       } request;
-       mach_port_t replyPort;
-       a_request_callout_t callout;
-       void *context;
-       struct hostent *hent;           /* if reply known in XXX_start() */
-} a_requests_t;
-
-static a_requests_t *a_requests = NULL;
-static pthread_mutex_t a_requests_lock = PTHREAD_MUTEX_INITIALIZER;
-
-#define MAX_LOOKUP_ATTEMPTS 10
+       void *user_context;
+       int want;
+} my_context_t;
 
-static kern_return_t
-_lookup_all_tx(mach_port_t server, int proc, ooline_data indata, mach_msg_type_number_t indataCnt, mach_port_t *replyPort)
+mach_port_t
+gethostbyaddr_async_start(const char *addr, int len, int family, gethostbyaddr_async_callback callback, void *context)
 {
-       typedef struct
-       {
-               mach_msg_header_t Head;
-               NDR_record_t NDR;
-               int proc;
-               mach_msg_type_number_t indataCnt;
-               unit indata[4096];
-       } Request;
-
-       Request In;
-       register Request *InP = &In;
-       mach_msg_return_t mr;
-       unsigned int msgh_size;
-
-       if (indataCnt > 4096) return MIG_ARRAY_TOO_LARGE;
-
-       if (*replyPort == MACH_PORT_NULL)
-       {
-               mr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, replyPort);
-               if (mr != KERN_SUCCESS) return mr;
-       }
-
-       msgh_size = (sizeof(Request) - 16384) + ((4 * indataCnt));
-       InP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
-//     InP->Head.msgh_size = msgh_size;        /* msgh_size passed as argument */
-       InP->Head.msgh_request_port = server;
-       InP->Head.msgh_reply_port = *replyPort;
-       InP->Head.msgh_id = 4241776;
-       InP->NDR = NDR_record;
-       InP->proc = proc;
-       InP->indataCnt = indataCnt;
-       memcpy((char *)InP->indata, (const char *)indata, 4 * indataCnt);
-
-       mr = mach_msg(&InP->Head,       /* msg */
-               MACH_SEND_MSG,          /* options */
-               msgh_size,              /* send_size */
-               0,                      /* rcv_size */
-               MACH_PORT_NULL,         /* rcv_name */
-               MACH_MSG_TIMEOUT_NONE,  /* timeout */
-               MACH_PORT_NULL);        /* notify */
-
-       switch (mr)
-       {
-               case MACH_MSG_SUCCESS:
-                       mr = KERN_SUCCESS;
-                       break;
-               case MACH_SEND_INVALID_REPLY :
-                       (void)mach_port_mod_refs(mach_task_self(), *replyPort, MACH_PORT_RIGHT_RECEIVE, -1);
-                       *replyPort = MACH_PORT_NULL;
-                       break;
-               default:
-                       break;
-       }
-
-       return mr;
-}
+       static int proc = 1;
+       int32_t want, status;
+       kvbuf_t *request;
+       mach_port_t mp;
+       my_context_t *my_context;
 
-static kern_return_t
-_lookup_all_rx(void *msg, ooline_data *outdata, mach_msg_type_number_t *outdataCnt, security_token_t *token)
-{
-       typedef struct
-       {
-               mach_msg_header_t Head;
-               mach_msg_body_t msgh_body;
-               mach_msg_ool_descriptor_t outdata;
-               NDR_record_t NDR;
-               mach_msg_type_number_t outdataCnt;
-               mach_msg_format_0_trailer_t trailer;
-       } Reply;
+       mp = MACH_PORT_NULL;
 
-       /*
-        * typedef struct {
-        * mach_msg_header_t Head;
-        * NDR_record_t NDR;
-        * kern_return_t RetCode;
-        * } mig_reply_error_t;
-        */
+       if (addr == NULL) return MACH_PORT_NULL;
+       if (len == 0) return MACH_PORT_NULL;
+       if ((family != AF_INET) && (family != AF_INET6)) return MACH_PORT_NULL;
 
-       register Reply *OutP = msg;
-       mach_msg_format_0_trailer_t *TrailerP;
-       boolean_t msgh_simple;
+       want = WANT_A4_ONLY;
+       if (family == AF_INET6) want = WANT_A6_ONLY;
 
-       if (OutP->Head.msgh_id != (4241776 + 100))
+       if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr)))
        {
-               if (OutP->Head.msgh_id == MACH_NOTIFY_SEND_ONCE) return MIG_SERVER_DIED;
-               else return MIG_REPLY_MISMATCH;
+               addr += 12;
+               len = 4;
+               family = AF_INET;
+               want = WANT_MAPPED_A4_ONLY;
        }
 
-       msgh_simple = !(OutP->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);
-
-       TrailerP = (mach_msg_format_0_trailer_t *)((vm_offset_t)OutP + round_msg(OutP->Head.msgh_size));
-       if (TrailerP->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0) return MIG_TRAILER_ERROR;
-
-       if (OutP->NDR.int_rep != NDR_record.int_rep)
+       if (proc < 0)
        {
-               if (msgh_simple)
-               {
-                       ((mig_reply_error_t *)OutP)->RetCode = OSReadSwapInt32(&(((mig_reply_error_t *)OutP)->RetCode), 0);
-               }
-               else
-               {
-                       OutP->outdataCnt = OSReadSwapInt32(&(OutP->outdataCnt), 0);
-               }
+               status = LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc);
+               if (status != KERN_SUCCESS) return MACH_PORT_NULL;
        }
 
-       if (msgh_simple && ((mig_reply_error_t *)OutP)->RetCode != KERN_SUCCESS) return ((mig_reply_error_t *)OutP)->RetCode;
-
-       *outdata = (ooline_data)(OutP->outdata.address);
-       *outdataCnt = OutP->outdataCnt;
-
-       *token = TrailerP->msgh_sender;
-
-       return KERN_SUCCESS;
-}
+       request = kvbuf_query("ksku", "address", addr, "family", want);
+       if (request == NULL) return MACH_PORT_NULL;
 
-static a_requests_t *
-request_extract(mach_port_t port)
-{
-       a_requests_t *request0, *request;
+       my_context = (my_context_t *)calloc(1, sizeof(my_context_t));
+       if (my_context == NULL) return MACH_PORT_NULL;
 
-       pthread_mutex_lock(&a_requests_lock);
+       my_context->user_context = context;
+       my_context->want = want;
 
-       request0 = NULL;
-       request = a_requests;
+       status = LI_async_start(&mp, proc, request, (void *)callback, my_context);
 
-       while (request != NULL)
-       {
-               if (port == request->replyPort)
-               {
-                       /* request found, remove from list */
-                       if (request0 != NULL)
-                       {
-                               request0->next = request->next;
-                       }
-                       else
-                       {
-                               a_requests = request->next;
-                       }
-
-                       break;
-               }
-               else
-               {
-                       /* not this request, skip to next */
-                       request0 = request;
-                       request = request->next;
-               }
-       }
-
-       pthread_mutex_unlock(&a_requests_lock);
-
-       return request;
+       kvbuf_free(request);
+       return mp;
 }
 
-static void
-request_queue(a_requests_t *request)
+void
+gethostbyaddr_async_cancel(mach_port_t port)
 {
-       pthread_mutex_lock(&a_requests_lock);
+       my_context_t *my_context;
 
-       request->next = a_requests;
-       a_requests = request;
+       my_context = NULL;
 
-       pthread_mutex_unlock(&a_requests_lock);
+       LI_async_call_cancel(port, (void **)&my_context);
 
-       return;
+       if (my_context != NULL) free(my_context);
 }
 
-static boolean_t
-sendCannedReply(a_requests_t *request, int *error)
+void
+gethostbyaddr_async_handleReply(void *msg)
 {
-       /*
-        * typedef struct {
-        * mach_msg_header_t Head;
-        * NDR_record_t NDR;
-        * kern_return_t RetCode;
-        * } mig_reply_error_t;
-        */
-
-       mig_reply_error_t Out;
-       register mig_reply_error_t *OutP = &Out;
-       kern_return_t kr;
-       mach_msg_return_t mr;
-       unsigned int msgh_size;
+       gethostbyaddr_async_callback callback;
+       struct hostent *out;
+       uint32_t len, want;
+       int status;
+       kvarray_t *reply;
+       my_context_t *my_context;
+       void *context;
 
-       mach_port_t sendPort;
-       mach_msg_type_name_t sendType;
+       callback = (gethostbyaddr_async_callback)NULL;
+       my_context = NULL;
+       context = NULL;
+       len = 0;
+       reply = NULL;
 
-       /*
-        * allocate reply port
-        */
-       kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &request->replyPort);
-       if (kr != KERN_SUCCESS)
+       status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context);
+       if ((status != KERN_SUCCESS) || (reply == NULL))
        {
-               *error = NO_RECOVERY;
-               return FALSE;
+               if (status == MIG_REPLY_MISMATCH) return;
+               if (callback != NULL)
+               {
+                       if (my_context != NULL) context = my_context->user_context;
+                       callback(NULL, context);
+                       free(my_context);
+                       return;
+               }
        }
 
-       kr = mach_port_extract_right(mach_task_self(), request->replyPort, MACH_MSG_TYPE_MAKE_SEND_ONCE, &sendPort, &sendType);
-       if (kr != KERN_SUCCESS)
+       want = WANT_A4_ONLY;
+       if (my_context != NULL)
        {
-               (void)mach_port_destroy(mach_task_self(), request->replyPort);
-               request->replyPort = MACH_PORT_NULL;
-               *error = NO_RECOVERY;
-               return FALSE;
+               context = my_context->user_context;
+               want = my_context->want;
+               free(my_context);
        }
 
-       /*
-        * queue reply message
-        */
-       msgh_size = sizeof(Out);
-       OutP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0);
-//     OutP->Head.msgh_size = msgh_size;       /* msgh_size passed as argument */
-       OutP->Head.msgh_request_port = sendPort;
-       OutP->Head.msgh_reply_port = MACH_PORT_NULL;
-       OutP->Head.msgh_id = 4241776 + 100;
-       OutP->RetCode = MIG_REMOTE_ERROR;
-       OutP->NDR = NDR_record;
-
-       mr = mach_msg(&OutP->Head, MACH_SEND_MSG, msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-       if (mr != MACH_MSG_SUCCESS)
-       {
-               if (mr == MACH_SEND_INVALID_REPLY)
-               {
-                       (void)mach_port_destroy(mach_task_self(), request->replyPort);
-                       request->replyPort = MACH_PORT_NULL;
-               }
-
-               *error = NO_RECOVERY;
-               return FALSE;
-       }
+       out = extract_host(reply, want);
+       kvarray_free(reply);
 
-       return TRUE;
+       callback(out, context);
 }
 
-static void
-_async_cancel(mach_port_t port)
+mach_port_t
+getipnodebyaddr_async_start(const void *addr, size_t len, int family, int *error, getipnodebyaddr_async_callback callback, void *context)
 {
-       a_requests_t *request;
-
-       request = request_extract(port);
-       if (request)
-       {
-               (void)mach_port_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1);
-               if (request->request.data) free(request->request.data);
-               if (request->hent) freehostent(request->hent);
-               free(request);
-       }
+       static int proc = 1;
+       int32_t want, status;
+       kvbuf_t *request;
+       mach_port_t mp;
+       my_context_t *my_context;
 
-       return;
-}
+       mp = MACH_PORT_NULL;
 
-static mach_port_t
-_gethostbyaddr_async_start(const char *addr, int len, int type, a_request_callout_t callout, void *context, int *error)
-{
-       void *address;
-       int proc;
-       a_requests_t *request;
-       int want;
-       static int proc4 = -1;
-       struct in_addr *v4addr;
-       static int proc6 = -1;
-       struct in6_addr *v6addr;
+       if (addr == NULL) return MACH_PORT_NULL;
+       if (len == 0) return MACH_PORT_NULL;
+       if ((family != AF_INET) && (family != AF_INET6)) return MACH_PORT_NULL;
 
        want = WANT_A4_ONLY;
-       if (type == AF_INET6) want = WANT_A6_ONLY;
+       if (family == AF_INET6) want = WANT_A6_ONLY;
 
-       if ((type == AF_INET6) && (len == 16) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr)))
+       if ((family == AF_INET6) && (len == IPV6_ADDR_LEN) && (is_a4_mapped((const char *)addr) || is_a4_compat((const char *)addr)))
        {
                addr += 12;
                len = 4;
-               type = AF_INET;
+               family = AF_INET;
                want = WANT_MAPPED_A4_ONLY;
        }
 
-       switch (type)
+       if (proc < 0)
        {
-               case AF_INET:
-               {
-                       if (proc4 < 0)
-                       {
-                               if (_lookup_link(_lu_port, "gethostbyaddr", &proc4) != KERN_SUCCESS)
-                               {
-                                       *error = NO_RECOVERY;
-                                       return MACH_PORT_NULL;
-                               }
-                       }
-
-                       if (len != sizeof(struct in_addr))
-                       {
-                               *error = NO_RECOVERY;
-                               return MACH_PORT_NULL;
-                       }
-
-                       v4addr = malloc(len);
-                       memmove(v4addr, addr, len);
-
-                       address = (void *)v4addr;
-                       proc = proc4;
-                       break;
-               }
-
-               case AF_INET6:
-               {
-                       if (proc6 < 0)
-                       {
-                               if (_lookup_link(_lu_port, "getipv6nodebyaddr", &proc6) != KERN_SUCCESS)
-                               {
-                                       *error = NO_RECOVERY;
-                                       return MACH_PORT_NULL;
-                               }
-                       }
-
-                       if (len != sizeof(struct in6_addr))
-                       {
-                               *error = NO_RECOVERY;
-                               return MACH_PORT_NULL;
-                       }
-
-                       v6addr = malloc(len);
-                       memmove(v6addr, addr, len);
-                       v6addr->__u6_addr.__u6_addr32[0] = htonl(v6addr->__u6_addr.__u6_addr32[0]);
-                       v6addr->__u6_addr.__u6_addr32[1] = htonl(v6addr->__u6_addr.__u6_addr32[1]);
-                       v6addr->__u6_addr.__u6_addr32[2] = htonl(v6addr->__u6_addr.__u6_addr32[2]);
-                       v6addr->__u6_addr.__u6_addr32[3] = htonl(v6addr->__u6_addr.__u6_addr32[3]);
-
-                       address = (void *)v6addr;
-                       proc = proc6;
-                       break;
-               }
-
-               default:
-               *error = NO_RECOVERY;
-               return MACH_PORT_NULL;
+               status = LI_DSLookupGetProcedureNumber("gethostbyaddr", &proc);
+               if (status != KERN_SUCCESS) return MACH_PORT_NULL;
        }
 
-       request = malloc(sizeof(a_requests_t));
-       request->next = NULL;
-       request->retry = MAX_LOOKUP_ATTEMPTS;
-       request->request.proc = proc;
-       request->request.data = (ooline_data)address;
-       request->request.dataLen = len / BYTES_PER_XDR_UNIT;
-       request->request.want = want;
-       request->replyPort = MACH_PORT_NULL;
-       request->callout = callout;
-       request->context = context;
-       request->hent = NULL;
-
-       /*
-        * allocate reply port, send query to lookupd
-        */
-       if (_lookup_all_tx(_lu_port, request->request.proc, request->request.data, request->request.dataLen, &request->replyPort) == KERN_SUCCESS)
-       {
-               request_queue(request);
-       }
-       else
-       {
-               if (request->request.data) free(request->request.data);
-               free(request);
-               *error = NO_RECOVERY;
-               return MACH_PORT_NULL;
-       }
+       request = kvbuf_query("ksku", "address", addr, "family", want);
+       if (request == NULL) return MACH_PORT_NULL;
 
-       return request->replyPort;
-}
+       my_context = (my_context_t *)calloc(1, sizeof(my_context_t));
+       if (my_context == NULL) return MACH_PORT_NULL;
 
-static boolean_t
-_gethostbyaddr_async_handleReply(void *replyMsg, a_requests_t **requestP, struct hostent **he, int *error)
-{
-       int count;
-       ooline_data data;
-       unsigned int datalen;
-       XDR inxdr;
-       mach_msg_header_t *msg = (mach_msg_header_t *)replyMsg;
-       a_requests_t *request;
-       kern_return_t status;
-       security_token_t token;
-
-       request = request_extract(msg->msgh_local_port);
-       if (!request)
-       {
-               /* excuse me, what happenned to the request info? */
-               return FALSE;
-       }
+       my_context->user_context = context;
+       my_context->want = want;
 
-       *requestP = request;
-       *he = NULL;
-       *error = 0;
+       status = LI_async_start(&mp, proc, request, (void *)callback, my_context);
 
-       /* unpack the reply */
-       status = _lookup_all_rx(replyMsg, &data, &datalen, &token);
-       switch (status)
-       {
-               case KERN_SUCCESS:
-                       break;
-
-               case MIG_SERVER_DIED:
-                       if (--request->retry > 0)
-                       {
-                               /* retry the request */
-                               if (_lookup_all_tx(_lu_port, request->request.proc, request->request.data, request->request.dataLen, &request->replyPort) == KERN_SUCCESS)
-                               {
-                                       request_queue(request);
-                                       return FALSE;
-                               }
-                       }
-                       /* fall through */
-
-               default:
-                       *error = HOST_NOT_FOUND;
-                       return TRUE;
-       }
-
-       datalen *= BYTES_PER_XDR_UNIT;
-
-       if (token.val[0] != 0)
-       {
-               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
-               *error = NO_RECOVERY;
-               return TRUE;
-       }
-
-       xdrmem_create(&inxdr, data, datalen, XDR_DECODE);
-
-       count = 0;
-       if (!xdr_int(&inxdr, &count))
-       {
-               xdr_destroy(&inxdr);
-               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
-               *error = NO_RECOVERY;
-               return TRUE;
-       }
-
-       if (count == 0)
-       {
-               xdr_destroy(&inxdr);
-               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
-               *error = HOST_NOT_FOUND;
-               *he = NULL;
-               return TRUE;
-       }
-
-       *he = extract_host(&inxdr, request->request.want, error);
-       xdr_destroy(&inxdr);
-       vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
-       return TRUE;
-}
-
-mach_port_t
-gethostbyaddr_async_start(const char *addr, int len, int type, gethostbyaddr_async_callback callout, void *context)
-{
-       a_request_callout_t cb;
-       mach_port_t mp;
-
-       if (!_lu_running())
-       {
-               h_errno = NO_RECOVERY;
-               return MACH_PORT_NULL;
-       }
-
-       cb.hostAddr = callout;
-       mp = _gethostbyaddr_async_start(addr, len, type, cb, context, &h_errno);
-       return mp;
-}
-
-void
-gethostbyaddr_async_cancel(mach_port_t port)
-{
-       _async_cancel(port);
-       return;
-}
-
-void
-gethostbyaddr_async_handleReply(void *replyMsg)
-{
-       int error = 0;
-       struct hostent *he = NULL;
-       a_requests_t *request = NULL;
-
-       if (_gethostbyaddr_async_handleReply(replyMsg, &request, &he, &error))
-       {
-               /* if we have an answer to provide */
-               h_errno = error;
-               (request->callout.hostAddr)(he, request->context);
-
-               (void)mach_port_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1);
-               if (request->request.data) free(request->request.data);
-               free(request);
-               if (he != NULL) freehostent(he);
-       }
-
-       return;
-}
-
-mach_port_t
-getipnodebyaddr_async_start(const void *addr, size_t len, int af, int *error, getipnodebyaddr_async_callback callout, void *context)
-{
-       a_request_callout_t cb;
-       mach_port_t mp;
-
-       if (!_lu_running())
-       {
-               *error = NO_RECOVERY;
-               return MACH_PORT_NULL;
-       }
-
-       cb.nodeAddr = callout;
-       mp = _gethostbyaddr_async_start(addr, len, af, cb, context, error);
+       kvbuf_free(request);
        return mp;
 }
 
 void
 getipnodebyaddr_async_cancel(mach_port_t port)
 {
-       _async_cancel(port);
-       return;
-}
+       my_context_t *my_context;
 
-void
-getipnodebyaddr_async_handleReply(void *replyMsg)
-{
-       int error = 0;
-       struct hostent *he = NULL;
-       a_requests_t *request = NULL;
+       my_context = NULL;
 
-       if (_gethostbyaddr_async_handleReply(replyMsg, &request, &he, &error))
-       {
-               /* if we have an answer to provide */
-               (request->callout.nodeAddr)(he, error, request->context);
-
-               (void)mach_port_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1);
-               if (request->request.data) free(request->request.data);
-               free(request);
-               /*
-                * Note: it is up to the callback function to call
-                * freehostent().
-                */
-       }
+       LI_async_call_cancel(port, (void **)&my_context);
 
-       return;
+       if (my_context != NULL) free(my_context);
 }
 
-static mach_port_t
-_gethostbyname_async_start(const char *name, int want, int *error, a_request_callout_t callout, void *context)
+void
+getipnodebyaddr_async_handleReply(void *msg)
 {
-       int af;
-       boolean_t is_addr = FALSE;
-       mach_port_t mp = MACH_PORT_NULL;
-       XDR outxdr;
-       static int proc;
-       a_requests_t *request;
-       static int proc4 = -1;
-       static int proc6 = -1;
-       struct in_addr v4addr;
-       struct in6_addr v6addr;
-
-       if ((name == NULL) || (name[0] == '\0'))
-       {
-               *error = NO_DATA;
-               return MACH_PORT_NULL;
-       }
-
-       af = (want == WANT_A4_ONLY) ? AF_INET: AF_INET6;
-
-       if ((af == AF_INET) || (want == WANT_MAPPED_A4_ONLY))
-       {
-               if (proc4 < 0)
-               {
-                       if (_lookup_link(_lu_port, "gethostbyname", &proc4) != KERN_SUCCESS)
-                       {
-                               *error = NO_RECOVERY;
-                               return MACH_PORT_NULL;
-                       }
-               }
-               proc = proc4;
-       }
-       else /* if (af == AF_INET6) */
-       {
-               if (proc6 < 0)
-               {
-                       if (_lookup_link(_lu_port, "getipv6nodebyname", &proc6) != KERN_SUCCESS)
-                       {
-                               *error = NO_RECOVERY;
-                               return MACH_PORT_NULL;
-                       }
-               }
-               proc = proc6;
-       }
-
-       request = malloc(sizeof(a_requests_t));
-       request->next = NULL;
-       request->retry = MAX_LOOKUP_ATTEMPTS;
-       request->request.proc = proc;
-       request->request.data = NULL;
-       request->request.dataLen = 0;
-       request->request.want = want;
-       request->replyPort = MACH_PORT_NULL;
-       request->callout = callout;
-       request->context = context;
-       request->hent = NULL;
-
-       switch (af)
-       {
-               case AF_INET:
-               {
-                       memset(&v4addr, 0, sizeof(struct in_addr));
-                       if (inet_aton(name, &v4addr) == 1)
-                       {
-                               /* return a fake hostent */
-                               request->hent = fake_hostent(name, v4addr);
-                               is_addr = TRUE;
-                       }
-                       break;
-               }
-
-               case AF_INET6:
-               {
-                       memset(&v6addr, 0, sizeof(struct in6_addr));
-                       if (inet_pton(af, name, &v6addr) == 1)
-                       {
-                               /* return a fake hostent */
-                               request->hent = fake_hostent6(name, v6addr);
-                               is_addr = TRUE;
-                               break;
-                       } 
-
-                       memset(&v4addr, 0, sizeof(struct in_addr));
-                       if (inet_aton(name, &v4addr) == 1)
-                       {
-                               if (want == WANT_A4_ONLY)
-                               {
-                                       free(request);
-                                       *error = HOST_NOT_FOUND;
-                                       return MACH_PORT_NULL;
-                               }
-
-                               v6addr.__u6_addr.__u6_addr32[0] = 0x00000000;
-                               v6addr.__u6_addr.__u6_addr32[1] = 0x00000000;
-                               v6addr.__u6_addr.__u6_addr32[2] = htonl(0x0000ffff);
-                               memmove(&(v6addr.__u6_addr.__u6_addr32[3]), &(v4addr.s_addr), sizeof(struct in_addr));
-
-                               /* return a fake hostent */
-                               request->hent = fake_hostent6(name, v6addr);
-                               is_addr = TRUE;
-                       }
-                       break;
-               }
+       getipnodebyaddr_async_callback callback;
+       struct hostent *out;
+       uint32_t len, want;
+       int status;
+       kvarray_t *reply;
+       my_context_t *my_context;
+       void *context;
 
-               default:
-               free(request);
-               *error = NO_RECOVERY;
-               return MACH_PORT_NULL;
-       }
+       callback = (getipnodebyaddr_async_callback)NULL;
+       my_context = NULL;
+       context = NULL;
+       len = 0;
+       reply = NULL;
 
-       if (is_addr)
+       status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context);
+       if ((status != KERN_SUCCESS) || (reply == NULL))
        {
-               /*
-                * queue reply message
-                */
-               if (sendCannedReply(request, error))
+               if (status == MIG_REPLY_MISMATCH) return;
+               if (callback != NULL)
                {
-                       request_queue(request);
-                       return request->replyPort;
-               }
-               else
-               {
-                       freehostent(request->hent);
-                       free(request);
-                       return MACH_PORT_NULL;
+                       if (my_context != NULL) context = my_context->user_context;
+                       callback(NULL, NO_RECOVERY, context);
+                       free(my_context);
+                       return;
                }
        }
 
-       request->request.dataLen = _LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT;
-       request->request.data = malloc(request->request.dataLen);
-
-       xdrmem_create(&outxdr, request->request.data, request->request.dataLen, XDR_ENCODE);
-       if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
+       want = WANT_A4_ONLY;
+       if (my_context != NULL)
        {
-               xdr_destroy(&outxdr);
-               free(request->request.data);
-               free(request);
-               *error = NO_RECOVERY;
-               return MACH_PORT_NULL;
+               context = my_context->user_context;
+               want = my_context->want;
+               free(my_context);
        }
 
-       request->request.dataLen = xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT;
+       out = extract_host(reply, want);
+       kvarray_free(reply);
 
-       /*
-        * allocate reply port, send query to lookupd
-        */
-       if (_lookup_all_tx(_lu_port, request->request.proc, request->request.data, request->request.dataLen, &request->replyPort) == KERN_SUCCESS)
-       {
-               request_queue(request);
-               mp = request->replyPort;
-       }
-       else
+       if (out == NULL)
        {
-               free(request->request.data);
-               free(request);
-               *error = NO_RECOVERY;
-               mp = MACH_PORT_NULL;
+               callback(NULL, HOST_NOT_FOUND, context);
+               return;
        }
 
-       xdr_destroy(&outxdr);
-       return mp;
+       callback(out, 0, context);
 }
 
-static boolean_t
-_gethostbyname_async_handleReply(void *replyMsg, a_requests_t **requestP, struct hostent **he, int *error)
+mach_port_t
+gethostbyname_async_start(const char *name, gethostbyname_async_callback callback, void *context)
 {
-       int count;
-       unsigned int datalen;
-       XDR inxdr;
-       ooline_data data;
-       mach_msg_header_t *msg = (mach_msg_header_t *)replyMsg;
-       a_requests_t *request;
-       kern_return_t status;
-       security_token_t token;
-       int want;
-
-       request = request_extract(msg->msgh_local_port);
-       if (!request)
-       {
-               /* excuse me, what happenned to the request info? */
-               return FALSE;
-       }
-
-       *requestP = request;
-       *he = NULL;
-       *error = 0;
-
-       if (request->hent)
-       {
-               /*
-                * if the reply was already available when the
-                * request was made
-                */
-               *he = request->hent;
-               return TRUE;
-       }
-
-       /* unpack the reply */
-       status = _lookup_all_rx(replyMsg, &data, &datalen, &token);
-       switch (status)
-       {
-               case KERN_SUCCESS:
-                       break;
-
-               case MIG_SERVER_DIED:
-                       if (--request->retry > 0)
-                       {
-                               /*
-                                * retry the request
-                                */
-                               if (_lookup_all_tx(_lu_port, request->request.proc, request->request.data, request->request.dataLen, &request->replyPort) == KERN_SUCCESS)
-                               {
-                                       request_queue(request);
-                                       return FALSE;
-                               }
-                       }
-                       /* fall through */
-
-               default:
-                       *error = HOST_NOT_FOUND;
-                       return TRUE;
-       }
-
-       datalen *= BYTES_PER_XDR_UNIT;
+       static int proc = 1;
+       int32_t status;
+       kvbuf_t *request;
+       mach_port_t mp;
 
-       if (token.val[0] != 0)
-       {
-               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
-               *error = NO_RECOVERY;
-               return TRUE;
-       }
+       mp = MACH_PORT_NULL;
 
-       xdrmem_create(&inxdr, data, datalen, XDR_DECODE);
+       if (name == NULL) return MACH_PORT_NULL;
 
-       count = 0;
-       if (!xdr_int(&inxdr, &count))
+       if (proc < 0)
        {
-               xdr_destroy(&inxdr);
-               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
-               *error = NO_RECOVERY;
-               return TRUE;
+               status = LI_DSLookupGetProcedureNumber("gethostbyname", &proc);
+               if (status != KERN_SUCCESS) return MACH_PORT_NULL;
        }
 
-       if (count == 0)
-       {
-               xdr_destroy(&inxdr);
-               vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
-               *error = HOST_NOT_FOUND;
-               return TRUE;
-       }
+       request = kvbuf_query("ksksks", "name", name, "ipv4", "1", "ipv6", "0");
+       if (request == NULL) return MACH_PORT_NULL;
 
-       want = request->request.want;
-       if (want == WANT_A6_OR_MAPPED_A4_IF_NO_A6) want = WANT_A6_ONLY;
-
-       *he = extract_host(&inxdr, want, error);
-       xdr_destroy(&inxdr);
-       vm_deallocate(mach_task_self(), (vm_address_t)data, datalen);
-       return TRUE;
-}
-
-mach_port_t
-gethostbyname_async_start(const char *name, gethostbyname_async_callback callout, void *context)
-{
-       a_request_callout_t cb;
-       int error;
-       mach_port_t mp = MACH_PORT_NULL;
-
-       if (!_lu_running())
-       {
-               h_errno = NO_RECOVERY;
-               return MACH_PORT_NULL;
-       }
-
-       cb.hostName = callout;
-       mp = _gethostbyname_async_start(name, WANT_A4_ONLY, &error, cb, context);
-       if (mp == MACH_PORT_NULL)
-       {
-               h_errno = error;
-       }
+       status = LI_async_start(&mp, proc, request, (void *)callback, context);
 
+       kvbuf_free(request);
        return mp;
 }
 
 void
 gethostbyname_async_cancel(mach_port_t port)
 {
-       _async_cancel(port);
-       return;
+       LI_async_call_cancel(port, NULL);
 }
 
 void
-gethostbyname_async_handleReply(void *replyMsg)
+gethostbyname_async_handleReply(void *msg)
 {
-       int error;
-       struct hostent *he;
-       a_requests_t *request;
+       gethostbyname_async_callback callback;
+       struct hostent *out;
+       uint32_t len;
+       int status;
+       kvarray_t *reply;
+       void *context;
+
+       callback = (gethostbyname_async_callback)NULL;
+       context = NULL;
+       len = 0;
+       reply = NULL;
 
-       if (_gethostbyname_async_handleReply(replyMsg, &request, &he, &error))
+       status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&context);
+       if ((status != KERN_SUCCESS) || (reply == NULL))
        {
-               /* if we have an answer to provide */
-               h_errno = error;
-               (request->callout.hostAddr)(he, request->context);
-
-               (void)mach_port_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1);
-               if (request->request.data) free(request->request.data);
-               free(request);
-               if (he != NULL) freehostent(he);
+               if (status == MIG_REPLY_MISMATCH) return;
+               if (callback != NULL)
+               {
+                       callback(NULL, context);
+                       return;
+               }
        }
 
-       return;
+       out = extract_host(reply, AF_INET);
+       kvarray_free(reply);
+
+       callback(out, context);
 }
 
 mach_port_t
-getipnodebyname_async_start(const char *name, int af, int flags, int *error, getipnodebyname_async_callback callout, void *context)
+getipnodebyname_async_start(const char *name, int family, int flags, int *err, getipnodebyname_async_callback callback, void *context)
 {
-       a_request_callout_t cb;
-       int if4 = 0;
-       int if6 = 0;
-       mach_port_t mp = MACH_PORT_NULL;
-       int want = WANT_A4_ONLY;
+       static int proc = 1;
+       int32_t status, want, want4, want6, if4, if6;
+       kvbuf_t *request;
+       mach_port_t mp;
        struct ifaddrs *ifa, *ifap;
+       struct in_addr addr4;
+       struct in6_addr addr6;
+       my_context_t *my_context;
 
-       if (!_lu_running())
-       {
-               h_errno = NO_RECOVERY;
-               return MACH_PORT_NULL;
-       }
+       if (name == NULL) return MACH_PORT_NULL;
+
+       if (err != NULL) *err = 0;
+
+       if4 = 0;
+       if6 = 0;
+       mp = MACH_PORT_NULL;
+       memset(&addr4, 0, sizeof(struct in_addr));
+       memset(&addr6, 0, sizeof(struct in6_addr));
 
-       /*
-        * IF AI_ADDRCONFIG is set, we need to know what interface flavors we really have.
-        */
        if (flags & AI_ADDRCONFIG)
        {
                if (getifaddrs(&ifa) < 0)
                {
-                       *error = NO_RECOVERY;
+                       if (err != NULL) *err = NO_RECOVERY;
                        return MACH_PORT_NULL;
                }
 
@@ -970,14 +357,8 @@ getipnodebyname_async_start(const char *name, int af, int flags, int *error, get
                {
                        if (ifap->ifa_addr == NULL) continue;
                        if ((ifap->ifa_flags & IFF_UP) == 0) continue;
-                       if (ifap->ifa_addr->sa_family == AF_INET)
-                       {
-                               if4++;
-                       }
-                       else if (ifap->ifa_addr->sa_family == AF_INET6)
-                       {
-                               if6++;
-                       }
+                       if (ifap->ifa_addr->sa_family == AF_INET) if4++;
+                       else if (ifap->ifa_addr->sa_family == AF_INET6) if6++;
                }
 
                freeifaddrs(ifa);
@@ -985,7 +366,7 @@ getipnodebyname_async_start(const char *name, int af, int flags, int *error, get
                /* Bail out if there are no interfaces */
                if ((if4 == 0) && (if6 == 0))
                {
-                       *error = NO_ADDRESS;
+                       if (err != NULL) *err = NO_RECOVERY;
                        return MACH_PORT_NULL;
                }
        }
@@ -994,108 +375,133 @@ getipnodebyname_async_start(const char *name, int af, int flags, int *error, get
         * Figure out what we want.
         * If user asked for AF_INET, we only want V4 addresses.
         */
-       switch (af)
+       want = WANT_A4_ONLY;
+
+       if (family == AF_INET)
        {
-               case AF_INET:
+               if ((flags & AI_ADDRCONFIG) && (if4 == 0))
                {
-                       want = WANT_A4_ONLY;
-                       if ((flags & AI_ADDRCONFIG) && (if4 == 0))
-                       {
-                               *error = NO_ADDRESS;
-                               return MACH_PORT_NULL;
-                       }
+                       if (err != NULL) *err = NO_RECOVERY;
+                       return MACH_PORT_NULL;
                }
-               break;
+       }
+       else
+       {
+               /* family == AF_INET6 */
+               want = WANT_A6_ONLY;
 
-               case AF_INET6:
+               if (flags & (AI_V4MAPPED | AI_V4MAPPED_CFG))
                {
-                       want = WANT_A6_ONLY;
-                       if (flags & (AI_V4MAPPED|AI_V4MAPPED_CFG))
+                       if (flags & AI_ALL)
                        {
-                               if (flags & AI_ALL)
-                               {
-                                       want = WANT_A6_PLUS_MAPPED_A4;
-                               }
-                               else
-                               {
-                                       want = WANT_A6_OR_MAPPED_A4_IF_NO_A6;
-                               }
+                               want = WANT_A6_PLUS_MAPPED_A4;
                        }
                        else
                        {
-                               if ((flags & AI_ADDRCONFIG) && (if6 == 0))
-                               {
-                                       *error = NO_ADDRESS;
-                                       return MACH_PORT_NULL;
-                               }
+                               want = WANT_A6_OR_MAPPED_A4_IF_NO_A6;
+                       }
+               }
+               else
+               {
+                       if ((flags & AI_ADDRCONFIG) && (if6 == 0)) 
+                       {
+                               if (err != NULL) *err = NO_RECOVERY;
+                               return MACH_PORT_NULL;
                        }
                }
-               break;
        }
 
-       cb.nodeName = callout;
-       mp = _gethostbyname_async_start(name, want, &h_errno, cb, context);
+       if (proc < 0)
+       {
+               status = LI_DSLookupGetProcedureNumber("gethostbyname", &proc);
+               if (status != KERN_SUCCESS) return MACH_PORT_NULL;
+       }
+
+       my_context = (my_context_t *)calloc(1, sizeof(my_context_t));
+       if (my_context == NULL)
+       {
+               *err = NO_RECOVERY;
+               return MACH_PORT_NULL;
+       }
+
+       my_context->user_context = context;
+       my_context->want = want;
+
+       want4 = 1;
+       want6 = 1;
+
+       if (want == WANT_A4_ONLY) want6 = 0;
+       else if (want == WANT_A6_ONLY) want4 = 0;
+       else if (WANT_MAPPED_A4_ONLY) want6 = 0;
+
+       request = kvbuf_query("kskuku", "name", name, "ipv4", want4, "ipv6", want6);
+       if (request == NULL) return MACH_PORT_NULL;
+
+       status = LI_async_start(&mp, proc, request, (void *)callback, my_context);
+
+       kvbuf_free(request);
        return mp;
 }
 
 void
 getipnodebyname_async_cancel(mach_port_t port)
 {
-       _async_cancel(port);
-       return;
+       my_context_t *my_context;
+
+       my_context = NULL;
+
+       LI_async_call_cancel(port, (void **)&my_context);
+
+       if (my_context != NULL) free(my_context);
 }
 
 void
-getipnodebyname_async_handleReply(void *replyMsg)
+getipnodebyname_async_handleReply(void *msg)
 {
-       int error = 0;
-       struct hostent *he = NULL;
-       a_requests_t *request = NULL;
-       static int proc4 = -1;
+       getipnodebyname_async_callback callback;
+       struct hostent *out;
+       uint32_t len, want;
+       int status, err;
+       kvarray_t *reply;
+       my_context_t *my_context;
+       void *context;
+
+       callback = (getipnodebyname_async_callback)NULL;
+       my_context = NULL;
+       context = NULL;
+       len = 0;
+       reply = NULL;
 
-       if (_gethostbyname_async_handleReply(replyMsg, &request, &he, &error))
+       status = LI_async_handle_reply(msg, &reply, (void **)&callback, (void **)&my_context);
+       if ((status != KERN_SUCCESS) || (reply == NULL))
        {
-               /*
-                * we have an answer to provide
-                */
-               if ((he == NULL) && (error == HOST_NOT_FOUND) && ((request->request.want == WANT_A6_PLUS_MAPPED_A4) || (request->request.want == WANT_A6_OR_MAPPED_A4_IF_NO_A6)))
+               if (status == MIG_REPLY_MISMATCH) return;
+               if (callback != NULL)
                {
-                       /*
-                        * no host found (yet), if requested we send a
-                        * followup query to lookupd.
-                        */
-                       if (proc4 < 0)
-                       {
-                               if (_lookup_link(_lu_port, "gethostbyname", &proc4) != KERN_SUCCESS)
-                               {
-                                       error = NO_RECOVERY;
-                                       goto answer;
-                               }
-                       }
-
-                       request->request.proc = proc4;
-                       request->request.want = WANT_MAPPED_A4_ONLY;
-                       if (_lookup_all_tx(_lu_port, request->request.proc, request->request.data, request->request.dataLen, &request->replyPort) == KERN_SUCCESS)
-                       {
-                               request_queue(request);
-                               return;
-                       }
-                       else
-                       {
-                               error = NO_RECOVERY;
-                       }
+                       if (my_context != NULL) context = my_context->user_context;
+                       callback(NULL, NO_RECOVERY, context);
+                       free(my_context);
+                       return;
                }
+       }
+
+       want = WANT_A4_ONLY;
+       if (my_context != NULL)
+       {
+               context = my_context->user_context;
+               want = my_context->want;
+               free(my_context);
+       }
 
-answer:
-               (request->callout.nodeName)(he, error, request->context);
-               (void)mach_port_mod_refs(mach_task_self(), request->replyPort, MACH_PORT_RIGHT_RECEIVE, -1);
-               if (request->request.data != NULL) free(request->request.data);
-               free(request);
-               /*
-                * Note: it is up to the callback function to call
-                * freehostent().
-                */
+       out = extract_host(reply, want);
+       kvarray_free(reply);
+
+       if (out == NULL)
+       {
+               err = HOST_NOT_FOUND;
+               callback(NULL, err, context);
+               return;
        }
 
-       return;
+       callback(out, 0, context);
 }